Migrating an analytics helper to Heap

When migrating to Heap from another analytics provider that uses a manual tracking setup, you’ll want an easy way to get up and running with Heap in as little time as possible.

One common pattern for implementing a manual tracking analytics solutions is to have a single helper or utility class through which all analytics calls run. This is beneficial to developers because it centralizes all tracking code in such a way that dependencies aren’t sprinkled throughout your code. It also provides an easy way to intercept and augment tracking calls before they’re executed without having to spread this logic throughout your entire app.

If your app utilizes a single helper class for routing all analytics calls, this example will show a basic example of how this class can be repurposed to be used with Heap.

📘

This example is written in Kotlin for Android, but the concept could be generalized to any framework or platform.

Example AnalyticsHelper Using Segment

// Example data model you'd want to include in tracking data.
data class Item(val id: Int, val name: String, val inCart: Boolean) {
  fun toMap() : Map<String, Any> {
    return mapOf(
      "id" to id,
      "name" to name,
      "inCart" to inCart
    )
  }
}

object AnalyticsHelper {
  var analyticsClient: Analytics? = null

  fun initAnalytics(context: Context) {
    analyticsClient = Analytics(
      "SOME_SEGMENT_KEY",
      context.applicationContext
    ) {
      collectDeviceId = true
    }
  }

  fun trackEvent(eventName: String, properties: Map<String, Any>) {
    analyticsClient?.track(eventName, mapToJson(properties))
  }

  fun trackItemViewed(item: Item) {
    trackEvent("item_viewed", item.toMap())
  }

  fun identifyUser(identity: String, properties: Map<String, Any>) {
    analyticsClient?.identify(identity, mapToJson(properties))
  }

  private fun mapToJson(properties: Map<String, Any>) : JSONObject {
    return JSONObject(properties)
  }
}

Example AnalyticsHelper Migrated to Heap

// No changes needed to the data model.
data class Item(val id: Int, val name: String, val inCart: Boolean) {
  fun toMap() : Map<String, Any> {
    return mapOf(
      "id" to id,
      "name" to name,
      "inCart" to inCart
    )
  }
}

// No changes to the public methods of this class. The rest of the app
// that uses this class to centralize tracking operations needs no updates.
object AnalyticsHelper {

  // No analytics client needed since Heap uses static functions.

  fun initAnalytics(context: Context) {
    // Replace analytics client creation with a call to startRecording.
    Heap.startRecording(
      context.applicationContext,
      "SOME_ENV_ID",
      Options(
        captureAdvertiserId = true
      )
    )
  }

  fun trackEvent(eventName: String, properties: Map<String, Any>) {
    // Track is similar. We use maps instead of Segment's JSONObject structure.
    Heap.track(eventName, properties)
  }

  fun trackItemViewed(item: Item) {
    // No change needed.
    trackEvent("item_viewed", item.toMap())
  }

  fun identifyUser(identity: String, properties: Map<String, Any>) {
    // Segment's identity takes properties, we do this in two calls.
    Heap.addUserProperties(properties)
    Heap.identify(identity)
  }
}

This example is purposely very basic to illustrate the concept, but this could be expanded to work with different analytics providers and different API calls. Be sure to check out our API reference for a complete list of API calls to understand how to migrate specific tracking calls to Heap.