Automatic integration

Smartlook can be automatically integrated into Segment as its source middleware:

// setup Smartlook
Smartlook.setupAndStartRecording(SMARTLOOK_API_KEY)

// initialize Segment analytics with Smartlook Middlewar
val analytics = Analytics.Builder(this, SEGMENT_API_KEY)
        .trackApplicationLifecycleEvents()
        .recordScreenViews()
        .useSourceMiddleware(Smartlook.createSegmentMiddleware())
        .build()

Analytics.setSingletonInstance(analytics)
// setup Smartlook
Smartlook.setupAndStartRecording(SMARTLOOK_API_KEY);

// initialize Segment analytics with Smartlook Middleware
Analytics analytics = new Analytics.Builder(this, SEGMENT_API_KEY)
        .trackApplicationLifecycleEvents()
        .recordScreenViews()
        .useSourceMiddleware(Smartlook.createSegmentMiddleware())
        .build();

Analytics.setSingletonInstance(analytics);

Smartlook Middleware integration translates Segment's track, screen, identify and alias calls to the respective Smartlook method calls. The options argument can filter unnecessary or unwanted mapping.

OptionSegment Event TypeSmartlook API Method(s)Notes
ENABLE_CUSTOM_EVENTStracktrackCustomEvent(name, props:)
ENABLE_SCREEN_EVENTSscreentrackNavigationEvent(name, ViewState.START)This mapping is not enabled in the .default option combination, as it interferes with Smartlook's Heatmaps generating.
When enabled, the Smartlook's ViewState is always .START.
ENABLE_IDENTIFYidentifysetUserIdentifier(userIdentifier)
setUserProperties(properties)
ENABLE_ALIASaliassetUserIdentifier(userIdentifier)This mapping is not enabled in the .default option combination, because Smartlook SDK doesn't have alias functionality. If enabled, alias is going to rewrite the previous user identifier.
ENABLE_ALLSets all options (all call mappings) enabled.
ENABLE_DEFAULTSets all options except for .screen and .alias to avoid Smartlook's Heatmaps mangling and the identifier rewriting.
val options = listOf(
  SegmentMiddlewareOption.ENABLE_CUSTOM_EVENTS,
  SegmentMiddlewareOption.ENABLE_IDENTIFY)

val smartlookMiddleware = Smartlook.createSegmentMiddleware(options)
List<SegmentMiddlewareOption> options = new ArrayList<>();
options.add(SegmentMiddlewareOption.ENABLE_CUSTOM_EVENTS);
options.add(SegmentMiddlewareOption.ENABLE_IDENTIFY);

Middleware smartlookMiddleware = Smartlook.createSegmentMiddleware(options);

Manual integration

There are recipes for straightforward Segment integration in Android.

// Make sure to setup and start Smartlook SDK before crating Segment Middleware   
fun createSegmentMiddleware() = Middleware { chain -> processSegmentPayload(chain.payload()) }

private fun processSegmentPayload(payload: BasePayload) {
    when(payload.type()) {
        BasePayload.Type.identify -> {
            identify(payload)
        }
        // handle other event types ...
    }
}

private fun identify(payload: BasePayload) {
    payload.userId()?.let { userIdentifier ->
        Smartlook.setUserIdentifier(userIdentifier)
    }

    payload.obtainMap("traits")?.let { traits ->
        Smartlook.setUserProperties(JSONObject(traits), false)
    }
}

private fun BasePayload.obtainMap(key: String): Map<*, *>? {
    this[key]?.let { map ->
        if (map is Map<*, *>) {
            return map
        }
    }
    return null
}
public Middleware createSegmentMiddleware() {
    return chain -> processSegmentPayload(chain.payload());
}

private void processSegmentPayload(BasePayload payload) {
    switch (payload.type()) {
        case BasePayload.Type.identify:
            identify(payload);
            break;

        // handle other event types ...
    }
}

private void identify(BasePayload payload) {
    String userId = payload.userId();
    if (userId != null) {
        Smartlook.setUserIdentifier(userId);
    }

    Map<Object, Object> traits = obtainMapFromPayload(payload, "traits");
    if (traits != null) {
        Smartlook.setUserProperties(new JSONObject(traits), false);
    }
}

private Map<Object, Object> obtainMapFromPayload(BasePayload payload, String key) {
    Object traits = payload.get(key);
    if (traits instanceof Map) {
        return (Map<Object, Object>) traits;
    }

    return null;
}

Full Segment documentation for mobile platforms can be found on the official website.