Product support

Get help in the plugin support forum.


Note: This plugin is no longer maintained. All features are provided as is.

A plugin for tracking app installs based on campaigns. Get information on new installs via referral. It is event-driven so you can handle campaign activations using custom-made or third-party plugins to perform your own business logic if needed.


This plugin extends features of the Android Installs plugin and adds an additional column to connect a campaign with each user install. Each time a user installs the app through a campaign referral, their install is connected to it. Otherwise, it is set as default which means install without referral.


  1. Once the plugin is installed, create a campaign. Once created you will see a slug appear. Copy that.
  2. Use Google Play URL builder to create a URL which you will use for your campaign.
  3. Set the source field as Campaign Source with the slug of your campaign from the campaign plugin. You can fill the rest with values based on your choice. Eg. Ad Network: Custom, Package Name: com.acme.android.
  4. Now you can use the generated URL to share to your target audience (or via ad network). Once the app is installed it will make a request to your server and add the details to this campaign plugin (For this to work, see documentation for client side integration code).
  5. (Optional) I don’t like the long Google Play Store URL with all the parameters so I wrote a URL shortening plugin to translate URLs to smaller slug based URL and that too with an additional short URL domain name. I will publish that in the future but you can even use a free shortening service such as Google URL Shortener, bitly, etc.

(NOT) Coming Soon

  • Dashboard widgets to give campaign analytics to see how many hits per campaign and see which campaigns are giving more user activations.

Android Campaigns Plugin

OctoberCMS plugin that enables tracking Android App installs via campaign referrals.

The plugin is a backend component to track user installs from the Android frontend i.e. your Android application. It consists of a list controller to view the activations, a campaign controller to create new campaigns and exposes a REST API node to allow end-user device to communicate with this plugin.


Campaign - It is a marketing program where your Android application is shared to end user thro’ a third party source or medium such as facebook, newspaper advertisement, etc.

Activation - This is used to represent an install that came via a marketing campaign. The difference between an install and an activation (campaign-based install) is that there are several parameters in the play store URL so that one can track where the user came from. This isn’t the general word used to describe campaign installs and in reality the word activation is used to represent any user install but I have defined Activation as campaign-based installs across all my Android targeted plugins for OctoberCMS.

Campaign Fields

The following data is presently collected from the user device when he installs via a campaign referral:

Source - The original referrer i.e. name of campaign such as new york times ad, daily planet ad, facebook ad,marketing mails etc.

Medium - Marketing medium such as television commercial, newspaper advertisement, website, email, etc.

Terms - Paid keywords. Eg. running+shoes

Content - Additional data to differentiate activations. For example, if I set source is user referral a fixed code can be used to identify exactly the user who referred by dynamically generating it. Eg. admin-person, acme-user, etc.


android.campaign.newActivation - This event is generated every time a new user activation happens. android.campaign.invalidSourceActivation - This event is generated every time a new user activation happens but the backend does not have a campaign associated with it.

API Responses

The API generates a JSON response with the following fields:

result - success or error based on whether the install data gets added successfully or not.

reason - If result is error, then this data contains the error message. The value duplicate means that the entry already exists. The value invalid_source means that a user activation happened but the source field is unknown since no such campaign was added in the backend. An event is also generated so that you may handle this case. For example, I generate an email to myself with the referral URL so that I know what source the user came from.

Client Side Integration

Register a broadcast listener in your app’s AndroidManifest.xml as:

        <action android:name="com.android.vending.INSTALL_REFERRER"/>

And then create a file InstallReceiver.java with the code:

public class InstallReceiver extends BroadcastReceiver {

    public void onReceive(final Context context, final Intent intent) {
        InstallUtils.pushInstall(context, BuildConfig.SERVER_LOCATION);

        // Push referrer after 10 seconds delay
        new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... params) {
                try {
                } catch(InterruptedException ex) {
                    // Do nothing
                } finally {
                    pushInstallReferrer(context, intent);
                return null;
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);

    public void pushInstallReferrer(Context context, Intent intent) {
        final Bundle extras = intent.getExtras();
        final String referrer;
        try {

            referrer = URLDecoder.decode(extras.getString("referrer"), "UTF-8");
            OkHttpClient client = new OkHttpClient();
            RequestBody formBody = new FormEncodingBuilder()
                    .add("device_id", Secure.getString(context.getContentResolver(), Secure.ANDROID_ID))
                    .add("referrer", referrer)
            Request request = new Request.Builder()
                    .url(BuildConfig.SERVER_LOCATION + "/android_campaign.json")
            client.newCall(request).enqueue(new Callback() {
                public void onFailure(Request request, IOException e) {

                public void onResponse(Response response) throws IOException {
                    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

        } catch (Throwable e) {
            // Could not decode


And make sure your build config contains SERVER_LOCATION String variable set (without a / in the end). And that it. Enjoy!


Improved code with better abstraction and extensibility.

Apr 03, 2016


Created table android_campaign_campaigns

Mar 18, 2016


Initialize plugin.

Mar 18, 2016