Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android App A wants to track Google Play referral data for Android App B installation

Let's say I have an Android App A that is installed in the user's device and I have an AppWidget with my App where we let other Android developers publish their App promotion ads on a Cost Per Install basis. So we need to track if App B is being installed on the user's device through App A's referral.

Let's also assume Android App B has its advertisement running on Android App A's widget and the link through which we redirect App A's users to App B's user to Google Play is with all referrer data. The URL looks like this (as recommended here -

https://play.google.com/store/apps/details?id=com.joelapenna.foursquared&referrer=utm_source%3Dtooyoou%26utm_medium%3Dbanner%26utm_term%3Dfoursquare%26utm_content%3Dfoursquare-tooyoou%26utm_campaign%3Dfoursquare-android)

If you hit the above link in your browser or make a QR code out of it and launch it it will take you to App B in Google Play with the required referral data. Now when App B is installed on the user's device and launched for the first time the Broadcast that App A expects to receive is com.android.vending.INSTALL_REFERRER. If the broadcast is received and the utm_source is App A then record and process the transaction. This is all we aim to do.

Here is App A's AndroidManifest.xml code snippet.

<application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:debuggable="true" >
        <activity
            android:name=".LocateMeActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
       <receiver android:name="com.locateme.android.ReferralReceiver" android:exported="true">
      <intent-filter>
        <action android:name="com.android.vending.INSTALL_REFERRER" />
      </intent-filter>
    </receiver> 
    </application>

Permissions added -

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

Here is the Broadcast Receiver class ReferralReceiver.java that is supposed to process the broadcast.

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;

public class ReferralReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        // Workaround for Android security issue: http://code.google.com/p/android/issues/detail?id=16006
        try
        {
            final Bundle extras = intent.getExtras();
            if (extras != null) {
                extras.containsKey(null);
            }
        }
        catch (final Exception e) {
            return;
        }

        Map<String, String> referralParams = new HashMap<String, String>();

        // Return if this is not the right intent.
        if (! intent.getAction().equals("com.android.vending.INSTALL_REFERRER")) { //$NON-NLS-1$
            return;
        }

        String referrer = intent.getStringExtra("referrer"); //$NON-NLS-1$
        if( referrer == null || referrer.length() == 0) {
            return;
        }

        try
        {    // Remove any url encoding
            referrer = URLDecoder.decode(referrer, "x-www-form-urlencoded"); //$NON-NLS-1$
        }
        catch (UnsupportedEncodingException e) { return; }

        // Parse the query string, extracting the relevant data
        String[] params = referrer.split("&"); // $NON-NLS-1$
        for (String param : params)
        {
            String[] pair = param.split("="); // $NON-NLS-1$
            referralParams.put(pair[0], pair[1]);
        }

        ReferralReceiver.storeReferralParams(context, referralParams);
    }

    private final static String[] EXPECTED_PARAMETERS = {
        "utm_source",
        "utm_medium",
        "utm_term",
        "utm_content",
        "utm_campaign"
    };

    private final static String PREFS_FILE_NAME = "ReferralParamsFile";

    public static void storeReferralParams(Context context, Map<String, String> params)
    {
        SharedPreferences storage = context.getSharedPreferences(ReferralReceiver.PREFS_FILE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = storage.edit();

        for(String key : ReferralReceiver.EXPECTED_PARAMETERS)
        {
            String value = params.get(key);
            if(value != null)
            {
                editor.putString(key, value);
            }
        }

        editor.commit();
    }


    public static Map<String, String> retrieveReferralParams(Context context)
    {
        HashMap<String, String> params = new HashMap<String, String>();
        SharedPreferences storage = context.getSharedPreferences(ReferralReceiver.PREFS_FILE_NAME, Context.MODE_PRIVATE);

        for(String key : ReferralReceiver.EXPECTED_PARAMETERS)
        {
            String value = storage.getString(key, null);
            if(value != null)
            {
                params.put(key, value);
            }
        }
        return params;
    }
}

The Debugging device is on Android OS 2.3.4

Through a simple TextView and Button in the main activity of the App I try to display the referral data captured by the receiver. Here is the call and display -

referraltext.setText(ReferralReceiver.retrieveReferralParams(this.getApplicationContext()).toString());

When I launch App B's referral link shown above, go to Google Play, install it and open it for the first time logcat doesn't show the broadcast com.android.vending.INSTALL_REFERRER at all and hence the referral data when displayed shows an empty string.

At the same time when I use adb command below the same broadcast receiver works like a charm and displays the referral data.

am broadcast -a com.android.vending.INSTALL_REFERRER -n com.locateme.android/.ReferralReceiver --es "referrer" "utm_source=tooyoou&utm_medium=banner&utm_term=foursquare&utm_content=foursquare-tooyoou&utm_campaign=foursquare-android"

So does that mean the Google Play does not broadcast the referrer data and the expected intent at all?

Or does it mean that it broadcasts the intent only for App B that is being installed?

Or am I doing something wrong?

Is this possible to achieve without App B having to insert our tracking SDK or code in their App just to advertise with us.

Thanks so much in advance for your help.

Additional Info - We are not using the Google Analytics SDK so we are using our custom Broadcast Receiver rather than Google's BR

The code above works like a charm. I just followed Lucas' advice below in the answer marked correct and replaced x-www-form-urlencoded to UTF-8. Why I didn't do this at first is because of what a mobile analytics company called Localytics posted here - http://www.localytics.com/docs/android-market-campaign-analytics/ Their code has the same issue. So basically what I have right now is that the above piece of code in an Android App that I published in Google Play and then downloaded the App from Google Play from my Android device running ICS, opened it and clicked on Retrieve Referral and it worked.Try it for free, here is the link - https://play.google.com/store/apps/details?id=com.locateme.android&referrer=utm_source%3Dtooyoou%26utm_medium%3Dbanner%26utm_term%3Dappdownload%26utm_content%3Dimage%26utm_campaign%3Dtooyooupromo

Another very important thing that I want to reiterate is that the google play campaign referral tracking this way will not work if you are installing an app remotely on your device using google play from the web. I have tested it and it is an open defect with Google.

like image 887
Aakash Avatar asked Jun 11 '12 19:06

Aakash


People also ask

What is Google Play install referrer?

What is an install referrer? An install referrer, otherwise known as a Google install referrer, is an identifier unique to Android devices which enables marketers to attribute ad activity to media sources for Google Play Store apps (also supported for some other stores, such as the Huawei Store).

Is Play install referrer API permission safe?

The Google Play Referrer is a standard and highly reliable and accurate method to attribute conversions through Google Play (but not Android out of store). It enables the attribution provider to send attribution parameters to the store, which then passes them back to the source when the app is downloaded.

What does install referrer API mean?

An Install Referrer is an Android-specific ad tracking identifier. Like Device IDs and Device Fingerprinting, an install referrer is a unique string that's sent to the Play Store when a user clicks on an ad.


1 Answers

the source code above is not correct.

the line

referrer = URLDecoder.decode(referrer, "x-www-form-urlencoded");

should be

referrer = URLDecoder.decode(referrer, "UTF-8");

the android documentation is not clear about this, but if you use x-www-form-urlencoded it will throw an unsupported encoding exception....

like image 76
Lucas Avatar answered Sep 23 '22 05:09

Lucas