Android V2 V1

Integrate SDK into your Android project. As an example, use ready the demo app in Java and Kotlin.

Basic requirements

  • Oldest Android version supported – 4.0 (API Level 14).

  • Project must have Google Play Services (com.google.android.gms:play-services-ads-identifier module) and Google Play Install Referrer (com.android.installreferrer:installreferrer module) enabled.

  • If you publish an app to Huawei App Store, the project must have Huawei Media Services enabled (com.huawei.hms:hms-ads-identifier module), to myTracker can get Huawei OAID.

Integration

Using Gradle

Add build.gradle file to your project dependencies section:

dependencies {
//... other dependencies
implementation 'com.my.tracker:mytracker-sdk:2.0.+'
}

Manually

  • Download the latest version of myTracker.aar.

  • Add myTracker.aar to your project as a dependency.

  • Add next dependencies to your application build.gradle file:

    dependencies {
        ...
        implementation 'com.android.installreferrer:installreferrer:1.1.2'
        implementation 'com.google.android.gms:play-services-ads-identifier:15.0.1'
    }
  • (Optionally or when using jar) If using Proguard make sure to add an exception:

    -keep class com.my.tracker.** { *; }
    -dontwarn com.my.tracker.**
    -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {
        com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context);
    }
    -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info {
        java.lang.String getId();
        boolean isLimitAdTrackingEnabled();
    }
    -keep class com.android.installreferrer.** { *; }
    -keep class com.android.vending.billing.** { *; }
    -keep class com.android.billingclient.api.** { *; }

Required permissions

(Optionally or when using jar) Add required permissions to your app’s AndroidManifest.xml at «manifest» section:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
     >
    ...
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    ...
</manifest>

Initialization

For correct myTracker SDK operation, set it up and initialize inside of onCreate method of an Application class of your app. To initialize SDK, you have to enter your SDK_KEY. And before that, you may set different settings for the tracker (configurations, parameters, deeplinks, etc.).

public class YourApplicationClass extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();

        // Setting up the configuration if needed
        MyTrackerParams trackerParams = MyTracker.getTrackerParams();
        MyTrackerParams trackerConfig = MyTracker.getTrackerConfig();
        // …
        // Setting up params
        // …
        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, this);
    }
}
class YourApplicationClass : Application()
{
    override fun onCreate()
    {
        super.onCreate()

        // Setting up the configuration if needed
        val trackerParams = MyTracker.getTrackerParams()
        val trackerConfig = MyTracker.getTrackerConfig()
        // ...
        // Setting up params
        // ...

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, this)
    }
}

If you can't initialize myTracker inside Application class, you could do that in the first starting activity of your application. However, in this case you must call trackLaunchManually method of myTracker after initialization.

public class YourActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);


        // Setting up the configuration if needed
        MyTrackerParams trackerParams = MyTracker.getTrackerParams();
        MyTrackerParams trackerConfig = MyTracker.getTrackerConfig();
        // ...
        // Setting up params
        // ...

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, getApplication());

        //Enable activity tracking
        MyTracker.trackLaunchManually(this);
    }
}
class YourActivity : Activity()
{
    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)

        // Setting up the configuration if needed
        val trackerParams = MyTracker.getTrackerParams()
        val trackerConfig = MyTracker.getTrackerConfig()
        // ...
        // Setting up params
        // ...

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, getApplication())
        MyTracker.trackLaunchManually(this)
    }
}

API

Tracker configuration

Configuration can be set up in MyTrackerConfig class instance available through MyTracker.getTrackerConfig() method. All parameters can be set up in MyTrackerParams class instance available through MyTracker.getTrackerParams() method. Currently available:

TrackingLaunchEnabled: app launch tracking. True by default.

@NonNull MyTrackerConfig setTrackingLaunchEnabled(boolean trackingLaunchEnabled)
fun setTrackingLaunchEnabled(trackingLaunchEnabled: Boolean): MyTrackerConfig

LaunchTimeout: an interval (in seconds) during which a new launch is not tracked and a session is not interrupted while app is in background. 30 seconds by default. Possible value range: 30-7200 seconds.

@NonNull MyTrackerConfig setLaunchTimeout(int seconds)
fun setLaunchTimeout(seconds: Int): MyTrackerConfig

BufferingPeriod: an interval (in seconds) during which events will be accumulated locally on the device before sending to the server. Default value is 900 seconds, allowed values are: 1-86400 seconds (1 day).

@NonNull MyTrackerConfig setBufferingPeriod(int seconds)
fun setBufferingPeriod(seconds: Int): MyTrackerConfig

ForcingPeriod: an interval (in seconds) starting from application install/update during which any new event will be send to the server immediately, without local buffering. Default value is set to 0 (immediate sending is disabled), allowed values are 0-432000 seconds (5 days).

@NonNull MyTrackerConfig setForcingPeriod(int seconds)
fun setForcingPeriod(seconds: Int): MyTrackerConfig

AutotrackingPurchaseEnabled: if inApp purchase events should be tracked automatically. True by default.

@NonNull MyTrackerConfig setAutotrackingPurchaseEnabled(boolean autotrackingPurchaseEnabled)
fun setAutotrackingPurchaseEnabled(autotrackingPurchaseEnabled: Boolean): MyTrackerConfig

TrackingLocationEnabled: geolocation tracking. True by default.

@NonNull MyTrackerConfig setTrackingLocationEnabled(boolean trackingLocationEnabled)
fun setTrackingLocationEnabled(trackingLocationEnabled: Boolean): MyTrackerConfig

TrackingPreinstallEnabled: pre-installs tracking. True by default. myTracker will catch pre-installs if you share an application and a special JSON-file with the device manufacturer.

@NonNull MyTrackerConfig setTrackingPreinstallEnabled(boolean trackingPreinstallEnabled)
fun setTrackingPreinstallEnabled(trackingPreinstallEnabled: Boolean): MyTrackerConfig

Region, where the data collection server is located. Choose a region based, for example, on current legislation. Available values:

  • Region.RU — server on the territory of Russian Federation

  • Region.EU — server on the territory of Europe

@NonNull MyTrackerConfig setRegion(int region)
fun setRegion(region: Int): MyTrackerConfig

Enable/disable debug mode

Enabling and disabling debug mode can be done via MyTracker class static methods. false by default.

@AnyThread
void setDebugMode(boolean debugMode)
@AnyThread
            fun setDebugMode(debugMode: Boolean)

Track users

Set the customUserId parameter to track user statistics, not only device. It is a unique user identifier in the project, that you specify at the time of registration. The identifier should remain unchanged even when user switch devices. The parameter allows you to estimate the size and activity of user base, regardless of the number of user devices. Also you can keep your customer data consistent if a user changes a device.

It is important to set the parameter before tracking events to pass user identifier with every event.

public void setUserInfo()
{
    MyTrackerParams trackerParams = MyTracker.getTrackerParams();

    // Set user id
    trackerParams.setCustomUserId("user_id");

}
fun setUserInfo()
{
    val trackerParams = MyTracker.getTrackerParams()

    // Set user id
    trackerParams.setCustomUserId("user_id")

}

If customUserId was set to the application with an existing registered users, myTracker can't calculate exact Lifetime metrics without registration time. For pre-registered users, Lifetime statistic will be count on the date of the first tracked event with customUserId.

To turn off user tracking, pass an empty value in the customUserId parameter.

Track events

Events can be sent via MyTracker class static methods. Before you call methods, set the customUserId parameter to pass user identifier with every tracked event.

The following methods for event tracking are available:

Registration event. You should call the method right after user registered in the app. Pass the user identifier in the parameter userId.

@AnyThread
void trackRegistrationEvent(@NonNull String userId)
@AnyThread
fun trackRegistrationEvent(userId: String)

userId is a required parameter since SDK version 2.0.8

Login event. You should call the method right after user successfully authorized in the app. Pass the user identifier in the parameter userId.

@AnyThread
void trackLoginEvent(@NonNull String userId)
@AnyThread
fun trackLoginEvent(userId: String)

userId is a required parameter since SDK version 2.0.8

Invite event. Any optional parameters can be passed with event as «key-value» by optional parameter eventParams. Max key or value length — 64 chars.

@AnyThread
void trackInviteEvent()
@AnyThread
void trackInviteEvent(@Nullable Map<String, String> eventParams)
@AnyThread
fun trackInviteEvent()

@AnyThread
fun trackInviteEvent(eventParams: Map<String, String>?)

Level achievement event. Level parameter is optional. Any optional parameters can be passed with event as «key-value» by optional parameter eventParams. Max key or value length — 64 chars.

@AnyThread
void trackLevelEvent()
@AnyThread
void trackLevelEvent(@Nullable Map<String, String> eventParams)
@AnyThread
void trackLevelEvent(int level, @Nullable Map<String,  String> eventParams)
@AnyThread
fun trackEvent(name: String)

@AnyThread
fun trackEvent(name: String, eventParams: Map<String, String>?)

Any user defined event with a custom name. Any optional parameters can be passed with event as «key-value» by optional parameter eventParams. Max name, key or value length — 64 chars.

@AnyThread
void trackEvent(@Nullable String name)
@AnyThread
void trackEvent(@Nullable String name, @Nullable Map<String, String> eventParams)
@AnyThread
fun trackEvent(name: String)

@AnyThread
fun trackEvent(name: String, eventParams: Map<String, String>?)

Example:

Map<String, String> eventCustomParams = new HashMap<>();
eventCustomParams.put("someParamKey1", "someParamValue1");
eventCustomParams.put("someParamKey2", "someParamValue2");
MyTracker.trackCustomEvent("eventName", eventCustomParams);
val eventCustomParams = HashMap<String, String>()
eventCustomParams["someParamKey1"] = "someParamValue1";
eventCustomParams["someParamKey2"] = "someParamValue2";
MyTracker.trackCustomEvent("eventName", eventCustomParams);

Force sending events from local buffer to server and reset buffering timers.

The SDK, which reduces channel load and lowers impact on app performance, collects all data on the device before sending it off to the server and regularly does so in a compressed format. By default, data is sent every 15 minutes. The interval can be changed to anywhere from 1 second to 1 day through the bufferingPeriod property. If the user has quit the app, the events will be sent during next launch. It is extremely important to analyse certain events as soon as possible, especially in the first sessions since installing the app. The flush() method will help.

@AnyThread
void flush()
@AnyThread
fun flush()

Track in app purchases

Play Billing Library

If you use the Play Billing Library, for automatic purchase events tracking you must call the corresponding myTracker method from onPurchasesUpdated method of BillingClient listener.

private BillingClient client;
...
client = BillingClient.newBuilder(context)
                 .setListener(new PurchasesUpdatedListener()
                 {
                    @Override
                    public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases)
                    {
                        MyTracker.onPurchasesUpdated(responseCode, (List) purchases);


                        // Your code for in app purchase handling
                        // ...
                    }
                 })
                 .build();
...
private var client: BillingClient? = null
// ...
client = BillingClient.newBuilder(this)
                .setListener { billingResult, purchases ->
                    MyTracker.onPurchasesUpdated(billingResult.responseCode, purchases as List<Any>?)
                    // ...
                    // Your code for in app purchase handling
                    // ...
                }
                .build()
// ...

In-app Billing API

If you use you own In-App Billing API implementation, for automatic purchase events tracking you must call the corresponding myTracker method from onActivityResult method of activity that started the purchase process.

public static final int PURCHASE_REQUEST_CODE = 1001;
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
   super.onActivityResult(requestCode, resultCode, data);
   if (requestCode == PURCHASE_REQUEST_CODE)
   {
        MyTracker.onActivityResult(resultCode, data);
        // Your code for in app purchase handling
        // ...
   }
}
...
// ...
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
{
    super.onActivityResult(requestCode, resultCode, data)
    if (PURCHASE_REQUEST_CODE == requestCode)
    {
        MyTracker.onActivityResult(resultCode, data)
        // ...
        // Your code for in app purchase handling
        // ...
    }
}
// ...
companion object
{
    const val PURCHASE_REQUEST_CODE = 1001
}

Manual in app purchases tracking

If you would like to track in app purchase events manually, you shoud disable auto tracking by setting autotrackingPurchaseEnabled = false and use myTracker methods:

@AnyThread
void trackPurchaseEvent(@NonNull JSONObject skuDetails,
       @NonNull JSONObject purchaseData,
       @NonNull String dataSignature)
@AnyThread
void trackPurchaseEvent(@NonNull JSONObject skuDetails,
       @NonNull JSONObject purchaseData,
       @NonNull String dataSignature,
       @Nullable Map<String, String> eventParams)
@AnyThread
fun trackPurchaseEvent(skuDetails: JSONObject,
                       purchaseData: JSONObject,
                       dataSignature: String)

@AnyThread
fun trackPurchaseEvent(skuDetails: JSONObject,
                       purchaseData: JSONObject,
                       dataSignature: String,
                       eventParams: Map<String, String>?)

If auto tracking is enabled, this methods calls will be ignored. Required parameters:

  • skuDetails — return value of getSkuDetails() method call according to documentation
  • purchaseData — JSON object in INAPP_PURCHASE_DATA field of getBuyIntent() method return value, according to documentation
  • dataSignature — string from INAPP_DATA_SIGNATURE field of getBuyIntent() method return value

Since data returned by methods getSkuDetails() and getBuyIntent() comes as Bundle with String type fields in it, transformation to JSONObject before send is required.

Any optional parameters can be passed with event as «key-value» by optional parameter eventParams. Max key or value length — 64 chars.

public static final int PURCHASE_REQUEST_CODE = 1001;
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
   super.onActivityResult(requestCode, resultCode, data);
   if (requestCode == PURCHASE_REQUEST_CODE && resultCode == RESULT_OK)
   {
      try
      {
         final String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
         final String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");

         final JSONObject purchaseDataJson = new JSONObject(purchaseData);

         // Receive skuDetails response
         final JSONObject skuDetailsJson = obtainSkuDetailJson(purchaseData);

         MyTracker.trackPurchaseEvent(skuDetailsJson, purchaseDataJson, dataSignature);


        // Your code for in app purchase handling
        // ...
      }
      catch (Exception ignored)
      {
      }
   }
}
...
// ...
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
{
    super.onActivityResult(requestCode, resultCode, data)
    // Checking if the request code is PURCHASE_REQUEST_CODE
    if (PURCHASE_REQUEST_CODE == requestCode && RESULT_OK == resultCode && data != null)
    {
        try
        {
            val dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE") ?: return
            val purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA") ?: return

            //  Receive skuDetails response
            val skuDetailsJson = obtainSkuDetailJson(purchaseData)

            val purchaseDataJson = JSONObject(purchaseData)

            MyTracker.trackPurchaseEvent(skuDetailsJson, purchaseDataJson, dataSignature)
        }
        catch (_: Exception)
        {
        }
    }
}
// ...
companion object
{
    const val PURCHASE_REQUEST_CODE = 1001
}
// ...

S2S tracking

To send data from your server to myTracker (for example, untracked data, offline events, etc.), you need to get special device identifiers — instanceId. The instanceId is a device identifier (UUID v4), that generated at the first app launch and unchanged until a user delete the app (or app data) from device.

The instanceId can get via MyTracker class static method (you shouldn't use it in the main thread).

@WorkerThread
@NonNull String getInstanceId(@NonNull Context context)
@WorkerThread
fun getInstanceId(context: Context): String

It is important to collect instanceId as soon as possible and send identifiers to your server because you need these IDs to work with S2S API.

Deeplinks

Deeplinks allow to pass additional parameters to application on application launch, for example, to open specific application screen.

Deferred deeplinks extend regular deeplinks and allow to pass additional parameters to recently installed application on the first application launch. Similar to regular deeplinks, this parameters could be used to open specific application screen or start an specific activity.

Detailed information on different deeplink types support in myTracker could be found in our documentation Deeplinks settings

To allow myTracker to handle regular deeplinks, in each application activity which support deeplinks in onCreate and onNewIntent methods you must call handleDeeplink method of myTracker.

public class SomeActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate();
        // ...
        String deeplink = MyTracker.handleDeeplink(getIntent());
        if(deeplink != null)
        {
            // Handle deeplink
        }
    }


    @Override
    protected void onNewIntent(Intent intent)
    {
        super.onNewIntent(intent);
        // ...
        String deeplink = MyTracker.handleDeeplink(intent);
        if(deeplink != null)
        {
            // Handle deeplink
        }
    }
}
class SomeActivity : Activity()
{
    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        // ...
        val deeplink = MyTracker.handleDeeplink(intent)
        if (deeplink != null)
        {
            // ...
            // Handle deeplink
            // ...
        }
    }

    override fun onNewIntent(intent: Intent?)
    {
        super.onNewIntent(intent)
        // ...
        val deeplink = MyTracker.handleDeeplink(intent)
        if (deeplink != null)
        {
            // ...
            // Handle deeplink
            // ...
        }
    }
}

Deferred deeplinks

To support deferred deeplinks in your app you need to add a listener which implement the MyTracker.AttributionListener interface. The listener would be called out just once, at first launch of the app if a deferred deeplink is found.

As a parameter to the onReceiveAttribution method, the MyTrackerAttribution attribution object containing the deeplink property would be passed. Check that the property value belongs to your app otherwise a third-party app might open when using Intent transition.

public class YourApplicationClass extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();

        // Setting up the configuration if needed
        MyTrackerParams trackerParams = MyTracker.getTrackerParams();
        MyTrackerParams trackerConfig = MyTracker.getTrackerConfig();
        // ...
        // Setting up params
        // ...


        // Set listener to receive the deferred deeplink
        MyTracker.setAttributionListener(new MyTracker.AttributionListener()
        {

            @Override
            public void onReceiveAttribution(MyTrackerAttribution attribution)
            {
                String deeplink = attribution.deeplink;
                // Processing the deferred deeplink
                // ...
            }
        });

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, this);
    }
}
class YourApplicationClass : Application
{
    override fun onCreate()
    {
        super.onCreate()

        // Setting up the configuration if needed
        val trackerParams = MyTracker.getTrackerParams();
        val trackerConfig = MyTracker.getTrackerConfig();
        // ...
        // НSetting up params
        // ...

        // Set listener to receive the deferred deeplink
        MyTracker.setAttributionListener { myTrackerAttribution ->
            val deeplink = myTrackerAttribution.deeplink
            // ...
            //  Handle the deferred deeplink
            // ...
        }

        // Initialize the tracker
        MyTracker.initTracker(SDK_KEY, this)
    }
}

You may set up a Handler for listener method execution when setting the listener with the setAttributionListener(AttributionListener attributionListener, Handler handler) method. If no Handler is set up when installing the listener then the onReceiveAttribution method would be called in the main application flow.