Tracking deep links (Android)

If your application handles deep links, getting this data into Heap is important for measuring campaign performance and tracking navigation patterns in your app.

When a deep link is used to open your application, it will come through via an Activity class. Once a deep link has been passed to an Activity via an Intent, you can parse the deep link URI and pass relevant pieces of information to Heap to use in future analysis.

There is no built-in deep link event type at this time, but this data can be tracked using Heap’s custom event tracking API. An example of what this looks like is illustrated below.

// Example activity that would be registered to handle a deep link
// by registering the proper intent filter in the manifest.
class ExampleActivity : AppCompatActivity() {

  // If the activity isn't already running, this is the method that
  // will be called to create the activity to handle the deep link.
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    intent.data?.let { uri ->
      handleDeepLink(uri)
    }
  }
  
  // If the activity IS already running, this is the method that will
  // be called to handle any deep links that get passed to the already
  // running activity.
  override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    
    intent?.data?.let { uri ->
      handleDeepLink(uri)
    }
  }
  
  // Single method for parsing out deep link pieces and passing them to Heap.
  private fun handleDeepLink(deepLink: Uri) {
    // The full deep link is the only piece that's guaranteed to not
    // be null, so you should capture that in all situations.
    val properties = mutableMapOf<String, Any>(
      "deep_link_full" to deepLink.toString()
    )
    
    // All other parts of the deep link could be null, so you'll only want to 
    // add the parts of the link that aren't null for tracking purposes. This 
    // section is only needed if you want to perform analysis on individual 
    // query parameters or paths. If you only need the full link text, this 
    // section can be omitted.
    deepLink.scheme?.let { properties["deep_link_scheme"] to it }
    deepLink.authority?.let { properties["deep_link_domain"] to it }
    deepLink.path?.let { properties["deep_link_path"] to it }
    deepLink.queryParameterNames.forEach { param ->
      deepLink.getQueryParameter(param)?.let { properties["deep_link_param_$param"] to it }
    }
    
    // Manually track that a link was clicked and pass along the captured 
    // deep link element properties using the custom event tracking API.
    Heap.track("deep_link_received", properties)
  }
}
// Example activity that would be registered to handle a deep link
// by registering the proper intent filter in the manifest.
class ExampleActivity extends AppCompatActivity {

    // If the activity isn't already running, this is the method that
    // will be called to create the activity to handle the deep link.
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Uri uri = getIntent().getData();
        if(uri != null) {
            handleDeepLink(uri);
        }
    }

    // If the activity IS already running, this is the method that will
    // be called to handle any deep links that get passed to the already
    // running activity.
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        Uri uri = intent.getData();
        if(uri != null) {
            handleDeepLink(uri);
        }
    }

    // Single method for parsing out deep link pieces and passing them to Heap.
    private void handleDeepLink(@NonNull Uri deepLink) {
        // The full deep link is the only piece that's guaranteed to not
        // be null, so you should capture that in all situations.
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("deep_link_full", deepLink.toString());

        // All other parts of the deep link could be null, so you'll only want to 
        // add the parts of the link that aren't null for tracking purposes. This 
        // section is only needed if you want to perform analysis on individual 
        // query parameters or paths. If you only need the full link text, this 
        // section can be omitted.
        if(deepLink.getScheme() != null) { 
            properties.put("deep_link_scheme", deepLink.getScheme()); 
        }
        if(deepLink.getAuthority() != null) {
            properties.put("deep_link_authority", deepLink.getAuthority());
        }
        if(deepLink.getPath() != null) {
            properties.put("deep_link_path", deepLink.getPath());
        }
        Set<String> queryParams = deepLink.getQueryParameterNames();
        for(String param : queryParams) {
            String paramValue = deepLink.getQueryParameter(param);
            if(paramValue != null) {
                properties.put("deep_link_param_" + param, paramValue);
            }
        }

        // Manually track that a link was clicked and pass along the captured 
        // deep link element properties using the custom event tracking API.
        Heap.track("deep_link_received", properties);
    }
}