Permutive Developer Hub

Welcome to the Permutive developer hub. You'll find comprehensive guides and documentation to help you start working with Permutive as quickly as possible, as well as support if you get stuck. Let's jump right in!

API Reference

Latest version: 1.4.4 Changelog

The Android SDK is comprised of one core SDK, and several kit libraries integrating with other 3rd Party SDKs.

Using multiple kit libraries enables feature-rich integration with minimal effort for developers and greater benefits to our clients.

For details information of our APIs please refer to our javadocs.

🚧

If you would like to use this SDK, please talk to your Customer Success Manager. Additional setup is required on your Permutive project for this SDK to function.

Download

To include in your Android application, add the following line to your dependencies:

//for androidx library version
implementation "com.permutive.android:core:1.4.4"

Migrating from older versions

Version 1.4.0 provides the PageTracker API to better track activity on a page/article. We recommend using permutive.trackPage(...) rather than manually using the general purprose eventTracker to track Pageview events.

Any event that should be tracked against a particular page, should be tracked using the PageTracker object, this will automatically include the page's context (title/url/referrer), as well as other page identification.

For this reason, we have deprecated the context methods setTitle/setUrl/setReferrer in favour of the PageTracker API - and in addition have been these methods non-persistent.

Initialise the SDK

The SDK requires that you provide it with a Project ID and API Key - which are available from the dashboard. None of the other functionality of the SDK is available until these are passed in.

🚧

Permutive singleton

The Permutive object should be created only once, we suggest initialising this in your application's onCreate method, or defining as a singleton in your DI graph. Creation of more than one Permutive object will result in undefined behaviour.

If you are using push notifications, we strongly recommend that you do not instantiate the Permutive object when receiving a push notification, but rather when the user interacts with the push notification.
.

Construction of the Permutive object is quick - it won't cause any issues with framerate drops. You can start making permutive calls straight away.

import com.permutive.android.Permutive
//..

  override fun onCreate() {
    //..
    val permutive = Permutive(context = this,
                              projectId = YOUR_PROJECT_ID,
                              apiKey = YOUR_API_KEY)
  }
import com.permutive.android.Permutive;

//..

  @Override
  void onCreate() {
  //..
    final Permutive permutive = new Permutive.Builder()
                                        .context(this)
                                        .projectId(YOUR_PROJECT_ID)
                                        .apiKey(YOUR_API_KEY)
                                        .build();
  }

Identity Management

You can set a custom identity for the user, whenever it's available. This may be appropriate when users login to your app, and a custom identity such as an internal identifier or email address may be available. Identifying a user with a custom identity is useful if you want to identify and synchronise users across platforms, for example across Android and web.

You can start the Permutive SDK with an optional identity, if you have this:

val customAliases = listOf(
         Alias.create(tag="internal",id="918635528918"),
         Alias.create(tag="email_md5",id="4E812201ADDB4289A1272E02B3C4F62D")
   )

    val permutive = Permutive(context = this,
                              projectId = YOUR_PROJECT_ID,
                              apiKey = YOUR_API_KEY,
                              identity = "918635528918", //alias with tag 'default'
                              customAliases = customAliases)
final Permutive permutive = new Permutive.Builder()
                                        .context(this)
                                        .projectId(YOUR_PROJECT_ID)
                                        .apiKey(YOUR_API_KEY)
                                        .identity("918635528918") //alias with tag 'default'                                                                                                                                                                                              .customAlias(Alias.create(tag="internal",id="918635528918")),
                                                                                                                        .customAlias(Alias.create(tag="email_md5",id="4E812201ADDB4289A1272E02B3C4F62D"))
                                        .build();

Or you can call setIdentity at any point after the Permutive SDK has been created.

//to set the 'default' alias
permutive.setIdentity("918635528918")

//or to set a list of custom aliases:
permutive.setIdentity(customAliases)
//to set the 'default' alias
permutive.setIdentity("918635528918");

//or to set a list of custom aliases:
permutive.setIdentity(customAliases);

To integrate automatically with the device's AAID (or GAID) - please read information on Tracking AAID identities below.

Event Tracking

Events represent any activity in your application worth tracking. Examples include entering and leaving app, engagement changes (i.e. scrolling inside an article) and any other user or environment driven inputs.

To track an event, grab an instance of a pageTracker or eventTracker object - and call the track method. The optional EventProperties passed in should conform to the schema of the event, and be less than 50 KB in size or it will be rejected.

Please note: event names and property names should only contain characters in [a-zA-Z0-9_]. Any character outside the allowed character set will result in an IllegalArgumentException.

As with all other Permutive SDK APIs, the eventTracker and pageTracker objects are lightweight and multiple instances may be be created, as needed. They are thread-safe, so feel free to track events from any thread & will not block the calling thread.

📘

Event schema rejection

Any event tracked by the SDK must be created in the Permutive Dashboard otherwise it will be rejected. The name must match and the properties must be correct - any properties that are unknown by the server or are the wrong type will result in a schema rejection.

To help debug any event issues, set developer mode on (permutive.setDeveloperMode(true)) and any issues will be logged to the adb console.

Page Tracking

Since version 1.4.0 we provide the PageTracker api to more easily track information on a page or article.

A Pageview event is automatically tracked when a PageTracker object is created, and a PageviewEngagmentAggregate event is tracked when that object is closed.

In order for the PageTracker object to accurately report how much time the user is viewing the page, call pause() or resume() at appropriate times of your Activity/Fragment's lifecycle.

The updatePercentageViewed function will record the total percentage of the page/article has been viewed.

//Start tracking a page with the given properties and context (title/url/referrer), automatically tracks a Pageview event with this information
val pageTracker = 
      permutive.trackPage(
          eventProperties = EventProperties.from("first_time" to true),
          title           = "Android Tutorial",
          url             = Uri.parse("http://www.permutive.com/android/tutorials"),
          referrer        = Uri.parse("http://www.permutive.com/android/tutorials?referrer=johnDoe"))
  
  
  //track another event against this page - this implicitly includes context (title/url/referrer) & page identifiers
  pageTracker.track("AgeGiven", EventProperties.from("age" to 21))
  
  
  //update the total percentage viewed to 77%
  pageTracker.updatePercentageViewed(0.77f)
  
  //call pause/resume at appropriate times in your Activity/Fragment lifecycle:
  override fun onPause() {
    pageTracker.pause()
  }

  override fun onResume() {
    pageTracker.resume()
  }
  
  //stop tracking the page, automatically tracks a PageviewEngagementAggregate event with the page information
  pageTracker.close()
//Start tracking a page with the given properties and context (title/url/referrer), automatically tracks a Pageview event with this information
PageTracker pageTracker = 
      permutive.trackPage(new EventProperties.Builder()
                             .with("first_time", true)
                             .build(),
                             "Android Tutorial",
                             Uri.parse("http://www.permutive.com/android/tutorials"),
                             Uri.parse("http://www.permutive.com/android/tutorials?referrer=johnDoe"));
  
  
  //track another event against this page - this implicitly includes context (title/url/referrer) & page identifiers
  pageTracker.track("AgeGiven", 
                    new EventProperties.Builder()
                             .with("age", 21)
                             .build());  
  
  //update the total percentage viewed to 77%
  pageTracker.updatePercentageViewed(0.77f);
  
  //call pause/resume at appropriate times in your Activity/Fragment lifecycle:
  void onPause() {
    pageTracker.pause();
  }

  void onResume() {
    pageTracker.resume();
  }
  
  //stop tracking the page, automatically tracks a PageviewEngagementAggregate event with the page information
  pageTracker.close();

Event Enrichment

Event enrichment replaces specific strings with other enriched information in the event properties. Android SDK supports the following types of enrichment:

  • Geographic information (EventProperties.GEO_INFO)
  • Isp information (EventProperties.ISP_INFO)
  • Hashed IP address (EventProperties.IP_ADDRESS_HASH)
  • Watson information (since v1.4.4 of the Android SDK) can be used if your project has this enabled & you have a URL set for the current page (see PageTracker API). For details see EventProperties.ALCHEMY_* properties.

To pass through geographic or ISP information for your custom events, you can pass through a special value when tracking the event:

val eventTracker = permutive.trackPage(); //or permutive.eventTracker()

with(eventTracker) {
  track("eventX",
        EventProperties.from(
            "geo_info" to EventProperties.GEO_INFO,
            "isp_info" to EventProperties.ISP_INFO,
            "hashed_ip" to EventProperties.IP_ADDRESS_HASH))
}
final EventTracker eventTracker = permutive.trackPage(); //or permutive.eventTracker()

final EventProperties eventProperties =
    new EventProperties.Builder()
        .with("geo_info", EventProperties.GEO_INFO)
        .with("isp_info", EventProperties.ISP_INFO)
        .with("hashed_ip", EventProperties.IP_ADDRESS_HASH)
        .build();

eventTracker.track("eventX" , eventProperties);

The event will be enriched to (for example):

{
    "geo_info": {
        "city": "Ayr",
        "continent": "Europe",
        "country": "United Kingdom",
        "postal_code": "KA7",
        "province": "South Ayrshire"
    },
    "isp_info": {
        "autonomous_system_number": 2856,
        "autonomous_system_organization": "British Telecommunications PLC",
        "isp": "BT",
        "organization": "BT"
    }
    "hashed_ip" : "de9aed029872179d95621f3301720b27"
}

This also applies to any values that are deeper in the properties tree (since properties can contain other Map<String, Any> objects as values).

If at the time no geo or isp information is available, these properties are stripped from the event information.

Current Segments

To get the current segments the user is in immediately without any updates, you can use the API calls below. If the Permutive SDK is initialising while currentSegments/currentReactions is called, a cached version is used.

val currentSegments = permutive.currentSegments //List<Int>
currentSegments.forEach {
  log("The user is in segment: $it")
}

val currentReactions = permutive.currentReactions //Map<String,List<Int>>
val dfpReactions = currentReactions["dfp"].orEmpty()
dfpReactions.forEach {
    log("The user is in dfp segment: $it")
}

val appNexusReactions = currentReactions["appnexus"].orEmpty()
//use appNexusReactions to enrich your appnexus ad targeting
final List<Integer> currentSegments = permutive.getCurrentSegments();
for (int segment: currentSegments) {
    log("The user is in segment: "+segment);
}

final Map<String,List<Integer> currentReactions = permutive.currentReactions;
final List<Integer> dfpReactions = currentReactions.getOrDefault("dfp",Collections.emptyList());
for (int segment: currentSegments) {
    log("The user is in dfp segment: "+segment);
}

final List<Integer> appNexusReactions = currentReactions.getOrDefault("appnexus",Collections.emptyList());
//use appNexusReactions to enrich your appnexus ad targeting

Segment Query

To track what segments the user belongs to, you can use the API call below. The callback will be called straight away with the current segments the user is in, and then called each time the segment list changes. Segments are returned as a list of Integers. These correspond to segment IDs setup in the Permutive Dashboard. The returned list is never null.

val triggersProvider = permutive.triggersProvider()
val segmentsTriggerAction = 
    triggersProvider.querySegments{ segments: List<Int> ->
                                     segments.forEach{
                                       log("The user is in segment: $it")
                                     }
                                   }

//when you wish to stop tracking changes, close the action
segmentsTriggerAction.close()
final TriggerProvider triggerProvider = permutive.triggerProvider();
final TriggerAction action =
    triggerProvider.querySegments(segments -> {
        for (int segment : segments){
            log("The user is in segment: "+segment);
        }
    });

Tracking Segment and Query Changes

To track real time changes to any queries, or segments, the developer can use trigger actions. Trigger actions contain a callback that is called immediately with the current value of that query/segment, and then each time that value changes. The value is never null. Please be aware that the callback may be called from a different thread than the one setting it up.

When you wish to stop receiving updates, call close on the trigger action. Not calling close on a trigger action may result in context leaks, it's a good idea to close any actions that are associated with your android component at an appropriate point in it's lifecycle (say for an Activity, at it's onPause/onStop callbacks).

Segments are always of type Boolean - so it is appropriate to use the triggerAction for these. Queries can be of a simple type - Boolean, String, Int, Long, Float, Double, or a more complex type: Map<String, Any> (where Any is of any of the simple types, or another Map of type <String, Any>).

If a query Id does not exist, the trigger will still be created, but the callback will never be called. If, however, the query does exist at a later point (the SDK may fetch a fresher version of the queries), then the callback will be called when a value is present, and then for each time the value changes.

Using a wrong type for a given query Id will immediately log an error to the console. The callback will never be called.

val triggersProvider = permutive.triggersProvider()

val triggerAction = 
    triggersProvider.triggerAction<Boolean>(queryId = 1) {
        log("Query 1 change: $it") //it is Boolean
    }

//when you wish to stop tracking changes, close the action
triggerAction.close()

val triggerActionMap = 
    triggersProvider.triggerActionMap(queryId = 2) {
        log("Query 2 change: $it") //it is Map<String,Any>
    }
final TriggersProvider triggersProvider = permutive.triggersProvider();

final TriggerAction triggerAction =
    triggersProvider.triggerAction(1, 
        value -> log("Query 1 change: "+value)); //value is Boolean

//when you wish to stop tracking changes, close the action
triggerAction.close()

final TriggerAction mapAction =
    triggersProvider.triggerActionMap(2,
        value -> log("Query 2 change: $it")); //value is Map<String,Any>

Tracking reactions

Tracking reactions is very similiar to tracking segment changes, once you register a listener, you will get the initial state, and on each change you will get an update until you close the trigger action.

val triggersProvider = permutive.triggersProvider()
val dfpReactionsTriggerAction = 
    triggersProvider
        .queryReactions("dfp"){ segments: List<Int> ->
                                segments.forEach{
                                  log("The user is in segment: $it")
                                }
                              }

//when you wish to stop tracking changes, close the action
dfpReactionsTriggerAction.close()
final TriggerProvider triggerProvider = permutive.triggerProvider();
final TriggerAction action =
    triggerProvider.queryReactions("dfp",segments -> {
        for (int segment : segments){
            log("The user is in segment: "+segment);
        }
    });

We have provided an easy way to add targeting for google ads requests. See the google-ads library instructions below.

Tracking AAID identities

In addition to identifying your user via a custom identity, you can also automatically track a user by their AAID. To do this, just include the google-ads dependency in your gradle build:

//for androidx library version
implementation "com.permutive.android:google-ads:1.4.4"

When creating the permutive object, simply add the AaidAliasProvider to the alias providers:

import com.permutive.android.Permutive
//..
  overide fun onCreate() {
  //..

      val permutive = Permutive(context = this,
                                projectId = YOUR_PROJECT_ID,
                                apiKey = YOUR_API_KEY,
                                aliasProviders = listOf(AaidAliasProvider(this))
  }
import com.permutive.android.Permutive;
//..

  @Override
  void onCreate() {
  //..

    final Permutive permutive =
        new Permutive.Builder()
            .context(this)
            .projectId(YOUR_PROJECT_ID)
            .apiKey(YOUR_API_KEY)
            .aliasProvider(new AaidAliasProvider(this)
            .build();
  }

The AAID will be tracked automatically by the SDK as soon as it is available.

Custom targeting with Google Ads

We provide an easy way to add custom targeting of your Permutive reactions to your google ads requests. To do this:

//To add custom targeting
val adRequest1 = 
            PublisherAdRequest.Builder()
                .addPermutiveTargeting(permutive)
                .build()

//Or simply without the build call:
val adRequest2 = 
        PublisherAdRequest.Builder()
            .buildWithPermutiveTargeting(permutive)
//In Java, you can use PermutiveAdRequestBuilder as a replacement
//for PublishAdRequest.Builder.
//PermutiveAdRequestBuilder has the same interface as
//PublishAdRequest.Builder
PublisherAdRequest request1 =
    new PermutiveAdRequestBuilder(permutive)
        .build();

//Or you can use the static methods to add permutive targeting
//to your existing PublisherAdRequests
PublishAdRequest.Builder builder =
    new PublisherAdRequest.Builder();

//to add custom targeting:
builder = PublisherAdRequestUtils
            .addPermutiveTargeting(builder, permutive);

//to add and build:
PublishAdRequest request2 = 
    PublishAdRequestUtils
        .buildWithPermutiveTargeting(builder, permutive);

Custom targeting with AppNexus

We have a beta add on library that provides custom targeting for AppNexus. Add the following dependency to your build.gradle:

implementation "com.permutive.android:appnexus:0.1.0"

Once this is installed, we provide two methods to add Permutive targeting to your AppNexus requests:

//for AddViews
banner.addPermutiveTargeting(permutive())
banner.loadAd()
  
//for NativeAdRequests  
nativeAd.addPermutiveTargeting(permutive())
//for AddViews
AdViewUtils.addPermutiveTargeting(banner, permutive());
banner.loadAd();
  
//for NativeAdRequests  
AdViewUtils.addPermutiveTargeting(nativeAd, permutive());

Developer mode

Activating developer mode will print more information to the console, which should help debugging common errors. We do not advise having this on when releasing.

permutive.setDeveloperMode(true)
permutive.setDeveloperMode(true);

Updated about a month ago

Android


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.