Skip to main content
← Back to blog
Felix Cameron··7 min read

How to Track App Installs in Your Android App (Kotlin)

Add install and revenue tracking to your Android app with Kotlin in under 10 minutes. See which links drive real installs — no GAID, no special permissions.

Why You Need Install Tracking Per Link

You're sending out links to your mobile app everywhere – in YouTube descriptions, Reddit threads, email newsletters, and influencer deals. You're seeing the download numbers in Google Play, but you don't know which link caused which download. It's a shot in the dark.

This is where Instally makes the difference. We assign a unique tracking ID to each link. When that click converts to a download, you know that's the specific install it brought in, and when that user converts to paid, you can trace it back. No need to guess. No need for complicated workarounds. If you share a single link across iOS and Android, see how one link routes to both stores. For the full cross-channel picture, see the guide on tracking app installs with links.

In this post, we'll walk through how to integrate the Instally Android SDK in Kotlin. At the end of this guide, you will have installed app tracking and (optional) revenue tracking setup and ready to go.

Prerequisites

RequirementDetails
Instally accountFree tier works. Sign up here
Android Studio Hedgehog+Kotlin 1.9 or later
Min SDKAPI 23 (Android 6.0)
Target SDKAPI 34+ recommended
Google Play app listingA package name registered with Instally
10 minutesSeriously

Step 1: Add the SDK

Add the Instally SDK dependency in your module-level build.gradle.kts:

Kotlin example:

dependencies {
    implementation("io.instally:instally-android-sdk:1.0.0")
}

Add this to your project-level build.gradle.kts if it's not there already:

repositories {
    mavenCentral()
    google()
}

Sync the project. All required native dependencies are pulled in automatically.

Step 2: Configure the SDK at App Start

You need to initialize Instally somewhere in your app, ideally as early as possible so it can record the install referrer before its validity period expires. This can usually be done in your Application class.

Kotlin example:

import io.instally.Instally

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Instally.configure(this, apiKey = "your_api_key_here")
    }
}

Then you need to update your AndroidManifest.xml to point to that Application class:

<application
    android:name=".MyApplication"
    ...
>

You can find your API key in the Instally Dashboard on Settings > API Keys.

Step 3: Track the Install

Once configured, call trackInstall. The SDK takes care of any deduplication, so you can safely call trackInstall on every app launch.

Kotlin example:

import io.instally.Instally

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        Instally.trackInstall { result ->
            result.onSuccess { installData ->
                Log.d("Instally", "Install tracked. Source: ${installData.linkSlug ?: "organic"}")
            }
            result.onFailure { error ->
                Log.e("Instally", "Install tracking failed", error)
            }
        }

        setContent {
            MyAppTheme {
                MainScreen()
            }
        }
    }
}

Or, using coroutines:

Kotlin example:

import io.instally.Instally
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        lifecycleScope.launch {
            try {
                val installData = Instally.trackInstall()
                Log.d("Instally", "Source: ${installData.linkSlug ?: "organic"}")
            } catch (e: Exception) {
                Log.e("Instally", "Tracking failed", e)
            }
        }
    }
}

The installData includes the link slug you matched against, country, device type, and the Instally user ID (for your revenue tracking). If the install did not come from an Instally link, linkSlug will be null.

What to expect from attribution accuracy

Android attribution is highly reliable for apps installed through Google Play. No GAID is used, no special permissions are required from the user, and no consent dialog is shown.

For sideloaded APKs or installs outside Google Play, attribution falls back to a best-effort match. For the iOS flow, see our iOS integration guide.

Step 4: Track revenue (optional)

Knowing which links lead to installs is helpful, knowing which links lead to revenue is game-changing. Instally supports revenue tracking through RevenueCat webhooks, Stripe webhooks, or direct client-side reporting. For full walkthroughs, see the RevenueCat or Stripe integration guides.

Option A: RevenueCat webhook (recommended)

No SDK code changes required beyond the user ID syncing. In your RevenueCat dashboard, setup your webhook:

    • Go to Integrations > Webhooks.
    • Add the following webhook endpoint URL: https://api.instally.io/webhooks/revenuecat.
    • Add header X-Instally-Api-Key with your API key.
    • Enable the following events: INITIAL_PURCHASE, RENEWAL, PRODUCT_CHANGE.
Then sync user IDs with the SDK:

Kotlin example:

Instally.trackInstall { result ->
    result.onSuccess { installData ->
        Purchases.sharedInstance.logIn(installData.installyUserId) { _, _ -> }
    }
}

Option B: Stripe webhook

If you use Stripe for payments, say directly from your server, add an Instally endpoint to your Stripe account:

    • Go to Developers > Webhooks.
    • Add the following endpoint URL: https://api.instally.io/webhooks/stripe.
    • Enable the following events: checkout.session.completed, invoice.paid.
    • Add your API key as metadata on the customer, or session.

Option C: Client-side revenue reporting

Or with any other payment provider, you can report directly from the app:

Kotlin example:

Instally.trackRevenue(
    amount = 9.99,
    currency = "USD",
    productId = "pro_monthly",
    transactionId = purchase.orderId
)

Step 5: ProGuard / R8 rules

If you use code shrinking (most production apps do), you will need to allowlist the SDK in your proguard-rules.pro:

-keep class io.instally.** { *; }
-keep class com.android.installreferrer.** { *; }

The SDK comes with consumer ProGuard rules that should do this automatically, but we always recommend being explicit.

Step 6: Verify in the dashboard

Ship a build with the SDK integrated, then:

    • Create a test link in the Instally dashboard
    • Open the link on your test device
    • Install from Google Play (or from an internal testing track)
    • Open the app
    • Check the dashboard -- the click and install should be visible within a few seconds, attributed to your test link
If the install registers as "organic", please verify that you called configure before trackInstall and that you installed the app via Google Play (not a direct APK install).

Full integration example

A minimal Jetpack Compose app with install and revenue attribution:

Kotlin

import android.app.Application
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.lifecycle.lifecycleScope
import io.instally.Instally
import com.revenuecat.purchases.Purchases
import kotlinx.coroutines.launch

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Instally.configure(this, apiKey = "ik_live_abc123")
        Purchases.configure(
            PurchasesConfiguration.Builder(this, "goog_xyz789").build()
        )
    }
}

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        var source by mutableStateOf("loading...")

        lifecycleScope.launch {
            try {
                val install = Instally.trackInstall()
                source = install.linkSlug ?: "organic"

                // Sync the Instally user ID with RevenueCat
                Purchases.sharedInstance.logIn(install.installyUserId) { _, _ -> }
            } catch (e: Exception) {
                source = "error"
                Log.e("Instally", "Tracking failed", e)
            }
        }

        setContent {
            Text("Install source: $source")
        }
    }
}

FAQ

Do I need any special permissions?

No. The SDK does not require manifest permissions beyond INTERNET, and users do not need to grant consent for attribution to work.

What happens if the user installed via a direct APK install (not Google Play)?

Attribution accuracy is highest for apps installed through Google Play. Direct APK or sideloaded installs fall back to a best-effort match with lower accuracy.

Can I track installs from preinstall campaigns?

Yes, if the app opens and the device is on the internet, the trackInstall function will execute. There is no click to associate an install with if the app was preinstalled, so the install will be counted as organic unless you're using your own custom referrer.

How fast does an install show up on the dashboard?

Typically within 5-10 seconds of the app opening. We transmit the attribution event to the server when trackInstall is executed, which is immediately when the app starts.

What's the minimum Android version required?

API 23 (Android 6.0). The SDK requires API 23 features to work.

Does Instally support other platforms?

Yes, we have SDKs for Swift, Flutter, and React Native, in addition to Kotlin. See docs for our docs on all supported platforms.

---

Install attribution on Android is highly reliable. It requires 2 lines of code and lets you know which installs come from which links. No guesswork, no app permissions. View pricing to get started today.

Ready / v1.0

Stop guessing. Start shipping.

Track clicks, installs, and revenue from every link. Set up in five minutes.

Get started free