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.

Option

Segment Event Type

Smartlook API Method(s)

Notes

ENABLE_CUSTOM_EVENTS

track

trackCustomEvent(name, props:)

ENABLE_SCREEN_EVENTS

screen

trackNavigationEvent(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_IDENTIFY

identify

setUserIdentifier(userIdentifier)
setUserProperties(properties)

ENABLE_ALIAS

alias

setUserIdentifier(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_ALL

Sets all options (all call mappings) enabled.

ENABLE_DEFAULT

Sets 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.