Approaches for writing interaction data from native mobile apps to Sitecore with examples for Android (Kotlin)

Leveraging  tracking not only on the web channel but also on mobile apps will provide greater and more detailed reports for marketers to identify patterns and trends to achieve better conversion.

In this blog post I will share what are available approaches for writing interaction data from native mobile apps to Sitecore, with examples for Android, using Kotlin.

As you might know, Sitecore web tracker tracks a contact’s activity and submits that data to xConnect at the end of the session. However, xConnect can  receive data only from trusted clients with the correct client certificates. Therefore, it is not feasible to write data directly to xConnect Collection service from a mobile application installed on a mobile phone.

There are a couple of options on how to implement tracking of contact’s activity in native mobile applications.

First option: Sitecore Universal Tracker

SitecoreTrackingForMobileUT

Figure 1. How interaction data from the native mobile apps ends up shown in the  Sitecore Marketing and Analytics Tools by using the Sitecore Universal Tracker.

I would recommend checking out Universal Tracker blog series by Akshay Sura in order to find out detailed information about the Sitecore Universal Tracker. Additionally, you can go through Sitecore Documentation for the Universal Tracker . Meanwhile, I will focus on providing more details on how it can be used in the context of native mobile applications with a few examples, which should help with setting up tracking of contact’s activity on native mobile apps with Sitecore faster.

The Sitecore Universal tracker is a set of services that lets you to collect interaction data from any channel, including mobile applications. The Universal Tracker (UT) collects live interactions, which consist of multiple events, as they happen, and submits them to xConnect when they are completed. The events that are submitted to the collection service of the Universal Tracker are mapped to the corresponding xConnect events, defined in Sitecore Marketing Control Panel. Event, goal, outcome, pageview, campaign, download, and search events are mapped out of the box.  You can specify additional types, if needed. The UT needs to be installed separately as it does not come with Sitecore out of the box. The documentation says that is is compatible with Sitecore 9.1 Initial Release, but it seems to work also with newer versions too.

How can I use it with native mobile apps?
Even though there is Sitecore Universal Tracker SDK available, it was built to be used only by client .NET applications. Currently there are no native platform SDKs available for Android and iOS (Java/Kotlin, Objective C/Swift). You can find out more information about UT SDK on Sitecore Documentation site.

It’s a great thing that the UT collection service is a REST API service, so it’s easy to send requests to it using an HTTP client. Below you can see examples of how to use the Sitecore Universal Tracker to submit interaction data from an Android native mobile app. The examples are shown using Kotlin and OkHttp HTTP client, though you can use any HTTP client/networking library of your preference.

The Universal Tracker Collection Service provides these public endpoints:

  • `/interaction`
  • `/event`
  • `/interaction/complete`

1. Start an interaction.
In order to start tracking a contact’s activity, at first, we need to submit PUT request to the interaction endpoint of the Collection Service, as shown in the example below.


@Serializable
data class SubmitInteractionRequest(
val channelId : String,
val initiator : String,
val userAgent : String,
val contact : Contact,
val events : Array
)

@Serializable
data class Contact (
val source : String,
val identifier : String
)

@Serializable
data class Event (
val type : String,
val definitionId : String,
val timestamp : String
)

val contact = Contact(source = "mobileApp", identifier = "username")
val event = Event(type = "goal", definitionId = "dd290bd9-e7d6-4e0b-bf46-347252e39a4a", timestamp = "2019-06-10T21:08:00Z")
val interactionRequest = SubmitInteractionRequest(channelId = "1914da0e-9c3a-4ec3-a2c2-a12eed2a4577", initiator = "contact",
												userAgent = "YourMobileAppName/5.1.0 (Android 10.0;)", contact, event)

val events = arrayOf(event)

val json = JSON.stringify(interactionRequest)

val okHttpClient = OkHttpClient()
val requestBody = json.toRequestBody()
val request = Request.Builder()
        .method("PUT", requestBody)
        .url("https://sitecore.tracking.collection.service/interaction")
        .build()
okHttpClient.newCall(request).enqueue(object : Callback {
    override fun onFailure(call: Call, e: IOException) {
        e.printStackTrace();
    }

    override fun onResponse(call: Call, response: Response) {
        //interaction id is returned and it has
        //to be passed for subsequent requests when submitting events
    }
})

The code above will submit the following JSON body to the endpoint:

{
  "ChannelId": "1914da0e-9c3a-4ec3-a2c2-a12eed2a4577", //App usage channel
  "Initiator": "contact",
  "UserAgent": "YourMobileAppName/5.1.0 (Android 10.0;)",
  "Contact": {
    "Source": "mobileApp",
    "Identifier": "username"
  },
  "Events": [
    {
      "type": "goal",
      "DefinitionId": "dd290bd9-e7d6-4e0b-bf46-347252e39a4a",
      "Timestamp": "2019-06-10T21:08:00Z"
    }
  ]
}

`ChannelId` and an event `DefinitionId` can be looked up in Sitecore Marketing Control Panel. There are already a few apps-related channels defined, which come out of the box, though, it is likely that you would want to add more goals and events. Along with that, a contact source and identifier have to be provided. You can find detailed information about contact identifiers here.

An Id of the interaction will be returned as a response. The interaction Id will have to be passed together with subsequent requests when submitting additional events.

Please note, it is useful to submit a User-Agent string for your mobile app, to provide details about the mobile app version and a device system information.
It will help to generate more insightful analytics reports, provides possibilities for triggering specific goals.
An example of a User-Agent string for a native mobile app can be:

[AppName]/[AppVersion]5.0 (Android [system details])

2. Submit more events.
When an interaction has started, we can submit more events as they occur. For this you can send `PUT` request to the `event` endpoint. It accepts an array of events.


@Serializable
data class Event (
val type : String,
val definitionId : String,
val timestamp : String,
val trackingInteractionId : String //the Id returned from the previous request
)

val loginEvent = Event(type = "goal", definitionId = "ds500bd9-e7d6-4e0b-bf46-347252e39a4a", timestamp = "2019-06-10T22:01:00Z",
trackingInteractionId="d3bfef78-5d14-4810-941b-69562450d60c")

val usageEvent = Event(type = "goal", definitionId = "ba290bd9-e7d6-4e0b-bf46-347252e39a4a", timestamp = "2019-06-10T22:02:00Z",
trackingInteractionId="d3bfef78-5d14-4810-941b-69562450d60c")

val events = arrayOf(loginEvent, usageEvent)
val json = JSON.stringify(events)

val okHttpClient = OkHttpClient()
val requestBody = json.toRequestBody()
val request = Request.Builder()
        .method("PUT", requestBody)
        .url("https://sitecore.tracking.collection.service/event")
        .build()
okHttpClient.newCall(request).enqueue(object : Callback {
    override fun onFailure(call: Call, e: IOException) {
        e.printStackTrace();
    }

    override fun onResponse(call: Call, response: Response) {
        //handle
    }
})

The following JSON body will be submitted to the `event` endpoint of the Collection Service:

[
  {
    "type": "goal",
    "DefinitionId": "ds500bd9-e7d6-4e0b-bf46-347252e39a4a",
    "Timestamp": "2019-06-10T22:01:00Z",
    "TrackingInteractionId": "d3bfef78-5d14-4810-941b-69562450d60c"
  },
  {
    "type": "event",
    "DefinitionId": "ba290bd9-e7d6-4e0b-bf46-347252e39a4a",
    "Timestamp": "2019-06-10T22:02:00Z",
    "TrackingInteractionId": "d3bfef78-5d14-4810-941b-69562450d60c"
  }
]

3. Complete the interaction.
This request is an optional one, if an interaction is not completed, it will be closed by a time out. In order to close the interaction, a `POST` request can be sent to the `interaction/complete` endpoint. The request body contains only the id of the interaction.


val interactionId = "d3bfef78-5d14-4810-941b-69562450d60c"

val okHttpClient = OkHttpClient()
val requestBody = interactionId.toRequestBody()
val request = Request.Builder()
        .method("POST", requestBody)
        .url("https://sitecore.tracking.collection.service/interaction/complete")
        .build()
okHttpClient.newCall(request).enqueue(object : Callback {
    override fun onFailure(call: Call, e: IOException) {
        e.printStackTrace();
    }

    override fun onResponse(call: Call, response: Response) {
        //if successful, 'true' is returned
    }
})

If the interaction was completed successfully, true will be returned as a response.

After that, the interaction data will be processed and submitted to xConnect and will be available for marketers in Sitecore.

TL;DR;

One of the options of how you can approach tracking of a contact’s activity on native mobile applications is to use the Sitecore Universal Tracker, which provides a REST API service to submit interaction data and trigger events. This is a preferred approach that is relatively easy to set up and is easily scalable. In my next blog post I describe another approach of how interaction  data can be sent from native mobile apps to Sitecore using xConnect. The approach is less convenient comparing to handling tracking by using the Universal Tracker, though it can still be a viable solution for the cases when the Universal Tracker cannot be used, for example, when Sitecore version is lower than 9.1 or other limiting scenarios.

Related posts:

  1. An alternative approach for sending interaction data from native mobile apps to Sitecore
  2. Enabling contact-related personalization when retrieving Sitecore content for native mobile apps

Useful links:

  1. Universal Tracker blog series by Akshay Sura
  2. Sitecore Documentation for the Universal Tracker
  3. More details about xConnect Collection service

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s