Building a Referral system: Play Install Referrer Library in Android

Building a Referral system: Play Install Referrer Library in Android

Pre-requisites:

  1. A unique referral code generation mechanism for every user(should be done in the backend).

  2. Testing the feature can be done in the developer release of your app.

  3. Applying and checking the referral code validation should be done with your backend API request. (Not shown here)

Implementation:

Sender:

This perspective is of the user who already has installed your app and now going to refer their friend using their unique referral code & link.

  1. Get your unique referral code from your backend. Eg. Code: qwertyuiop

  2. Generate a valid Play Store link of your app in the release build and share show an option to share. Eg. https://play.google.com/store/apps/details?id={PACKAGE_NAME}&referrer=utm_source%3Drefer%26utm_content%qwertyuiop

  3. Understanding “utm_source” & “utm_content”.

  4. There can be multiple ways a user can come to your app on the play store, that can we a Facebook ad, Instagram ad, or any other thing. In our case, it is a friend referral link. So that means the source of reaching the app(utm_source) is a referral. So you can add here the query param as “utm_source=refer”(can be any string value) and if there is any content attached with the link(the referral code) can be added like “utm_content=qwertyuiop”.

  5. You can create the referral link for the user like this:

https://play.google.com/store/apps/details?id= + appId + "&referrer=utm_source%3Drefer%26utm_content%3D${code}"

Get your appId from your app build.gradle.


1.Now, that you have already shared a link to your friend.

2. Your friend should click on the link navigate to the play store and can download your app.

3. Once the friend downloads the app we should fetch the referral code using the Play referral library and save it to later apply in profile or any other screen you wants.


Receiver:

The friend who just downloaded the app from your referral link.

  1. Fetch the code in the MainActivity:
private lateinit var referrerClient: InstallReferrerClient
//Call this in onCreate()
private fun initReferralTracking() {
    referrerClient = InstallReferrerClient.newBuilder(this).build()
    referrerClient.startConnection(object : InstallReferrerStateListener {

        override fun onInstallReferrerSetupFinished(responseCode: Int) {
            when (responseCode) {
                InstallReferrerClient.InstallReferrerResponse.OK -> {
                    // Connection established.
                    obtainReferrerDetails()
                }

                InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE -> {
                    // Connection couldn't be established.
                }

                InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED -> {
                    // API not available on the current Play Store app.
                }
            }
        }

        override fun onInstallReferrerServiceDisconnected() {
            // Try to restart the connection on the next request to
            // Google Play by calling the startConnection() method.
        }
    })
}

2. In “InstallReferrerClient.InstallReferrerResponse.OK”, we can get the referral details.

private fun obtainReferrerDetails() {
    val response: ReferrerDetails = referrerClient.installReferrer
    Log.d(TAG, "response - $response")
    val referrerUrl: String = response.installReferrer
    Log.d(TAG, "referrerUrl - $referrerUrl")//referrerUrl - utm_source=google-play&utm_medium=organic //it's default value only

    if (referrerUrl.isNotEmpty()) {
        val referrerParts = referrerUrl.split("&")//split with &
        Log.d(TAG, "referrerParts - $referrerParts")//divided in 2 parts utm_source,utm_content

        val utmSource = referrerParts.find {
            it.contains("utm_source")
        }?.split("=")?.get(1)//get the value of utm_source
        Log.d(TAG, "utmSource - $utmSource")

        if (utmSource != null && utmSource == "refer") {
            val utmContent = referrerParts.find {
                it.contains("utm_content")
            }?.split("=")?.get(1)//get the value of utm_content
            Log.d(TAG, "utmContent - $utmContent")

            if (utmContent != null) {
                val refCode = utmContent//save apply the code anywhere
            }
        }
    }
    referrerClient.endConnection()//end the connection after checking
}

3. Wohoo!! Whatever we did will work as expected and we’ll get the referral code via utm_content once your friend downloads the app(or you can build the app from Android studio and only open it using play store).

But…… there is a major issue now.

We are checking for the referral code everytime when the MainActivity starts, that is a unnecessary performance hit. We can avoid it slightly using our Datastore.

The idea was to store a Boolean key in the Proto Datastore named ‘isReferralChecked’, that will help us only run this whole thing only first app launch.

4. Create a proto Datastore following this article.

5. Fetch the Boolean key in your ViewModel/repo like this..

val isReferralChecked = prefManager.userData
    .map {
        UiState.Success(it.isReferralChecked)//Using UiState wrapper to confirm the data is present
    }
    .stateIn(
        scope = viewModelScope,
        started = SharingStarted.Eagerly,
        initialValue = UiState.Loading,//As it might take small instant to load the data
    )

6. Create a check in MainActivity and check for referral only after that..

lifecycleScope.launch {//in onCreate
    mainViewModel.isReferralChecked.collect {
        if (it is UiState.Success && !it.data) {//means it wass not cheked before
            initReferralTracking()
        }
    }
}

7. Mark this Boolean as true after checking the referral..

private fun obtainReferrerDetails() {
    val response: ReferrerDetails = referrerClient.installReferrer
        Log.d(TAG, "response - $response")
        val referrerUrl: String = response.installReferrer
        Log.d(TAG, "referrerUrl - $referrerUrl")

        if (referrerUrl.isNotEmpty()) {
            ...
            if (utmContent != null) {
                mainViewModel.setReferCode(utmContent)//See Point 8
            }
        }

    mainViewModel.setReferralChecked()//isReferralChecked=true
    referrerClient.endConnection()
}

8. OPTIONALLY, store the referral code in proto Datastore to easily access it in later screens.

9. Apply the referral code and update your server anywhere.

10. Update both the users about the successful referral.

That’s it!

Leave a comment if you are facing any issues or have any improvements.

I hope you found this helpful. If yes, then do FOLLOW ‘Sagar Malhotra’ for more Android-related content.