> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appeeky.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Android SDK (Kotlin)

> Add Appeeky Analytics to a native Android app with Gradle

The Kotlin SDK records installs, sessions, screens and your own events, and links each install to the RevenueCat or Superwall customer. It sends the same data as the [React Native SDK](https://docs.appeeky.com/docs/analytics-sdk-reference.md), so the dashboard, attribution and revenue work the same way.

* No advertising id. The install id is a random UUID stored in the app.
* Events are queued on the device and sent in batches. They survive offline periods and app restarts.
* Reads the Google Play Install Referrer on the first launch, so installs from a smart link are attributed exactly and can open a deferred deep link.
* Android 6.0 (API 23) or later. Kotlin coroutines and the AndroidX process lifecycle, no HTTP or JSON library.

The source is on GitHub: [appeeky/analytics-android](https://github.com/appeeky/analytics-android).

***

## Setup

**1. Turn on Analytics for the app**

In Appeeky, open the app under **My Apps → Attribution** and click **Turn on attribution**. Copy the publishable key (`apk_pub_…`). See the [Quickstart](https://docs.appeeky.com/docs/analytics-quickstart.md) for the API call.

**2. Add the dependency**

The SDK is published through JitPack:

```kotlin theme={"theme":{"light":"github-light","dark":"github-dark"}}
// settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven("https://jitpack.io")
    }
}

// app/build.gradle.kts
dependencies {
    implementation("com.github.appeeky:analytics-android:0.1.0")
}
```

It brings `kotlinx-coroutines-android`, `androidx.lifecycle:lifecycle-process` and the Play Install Referrer library, and adds the `INTERNET` permission.

**3. Configure the SDK in your Application**

```kotlin theme={"theme":{"light":"github-light","dark":"github-dark"}}
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Appeeky.configure(this, "apk_pub_...", debug = BuildConfig.DEBUG)
    }
}
```

The SDK sends to `https://ingest.appeeky.com/v1/ingest`. For a self-hosted server, pass `endpoint = "https://analytics.example.com/v1/ingest"`.

When `configure` runs in `Application.onCreate()`, the SDK reads the launch Intent of the first Activity itself, so campaign links (`?aky_c=spring`, `utm_*`) are attributed.

**4. Link the install to RevenueCat or Superwall**

```kotlin theme={"theme":{"light":"github-light","dark":"github-dark"}}
Purchases.configure(PurchasesConfiguration.Builder(this, "goog_...").build())
Appeeky.identify(Purchases.sharedInstance.appUserID)

// After Purchases.sharedInstance.logIn(id) succeeds:
Appeeky.identify(id)

// On logout:
Appeeky.identify(null)
```

With [Superwall](https://docs.appeeky.com/docs/analytics-superwall.md), pass the same user id you give `Superwall.instance.identify(userId)`.

**5. Track screens**

With Jetpack Navigation:

```kotlin theme={"theme":{"light":"github-light","dark":"github-dark"}}
navController.addOnDestinationChangedListener { _, destination, _ ->
    destination.route?.let { Appeeky.screen(it) }
}
```

***

## Methods

| Method | What it does |
| - | - |
| `Appeeky.configure(context, key, endpoint, debug, options)` | Starts the SDK. Later calls are ignored. |
| `Appeeky.identify(userId)` | Links the install to a RevenueCat or Superwall user id. `null` on logout. |
| `Appeeky.screen(name, props)` | Records a screen view. |
| `Appeeky.track(name, props, value)` | Records a custom event, with optional properties and a number. |
| `Appeeky.handleDeepLink(intent)` | Passes the launch Intent (or a `Uri`) when you configure the SDK later than `Application.onCreate()`. |
| `Appeeky.getDeferredDeepLink()` | The smart link's in-app destination on the first launch, once. A suspend function, or pass a callback. |
| `Appeeky.adRevenue(valueUsd, network, adUnit, format)` | Reports a paid ad impression in USD. |
| `Appeeky.flush()` | Sends queued events now (suspend). |
| `Appeeky.installId` | This install's random id, `null` until the SDK has loaded its state. |

```kotlin theme={"theme":{"light":"github-light","dark":"github-dark"}}
Appeeky.screen("Paywall", mapOf("variant" to "b"))
Appeeky.track("onboarding_completed", mapOf("step" to 3))
Appeeky.track("export", mapOf("format" to "pdf"), value = 1.0)
```

Event names may use letters, digits, `_`, `.`, `:` and `-`, up to 64 characters. An event with another name is dropped on the device and logged when `debug = true`. Property values are strings (up to 512 characters), numbers, booleans or `null`.

### Ad revenue

```kotlin theme={"theme":{"light":"github-light","dark":"github-dark"}}
rewardedAd.onPaidEventListener = OnPaidEventListener { value ->
    if (value.currencyCode == "USD") {
        Appeeky.adRevenue(value.valueMicros / 1_000_000.0, network = "admob", adUnit = "rewarded_home", format = "rewarded")
    }
}
```

### Options

```kotlin theme={"theme":{"light":"github-light","dark":"github-dark"}}
Appeeky.configure(this, "apk_pub_...", options = AppeekyOptions(sessionTimeoutMs = 15 * 60 * 1000L))
```

| Option | Default | Effect |
| - | - | - |
| `endpoint` | Appeeky hosted | A self-hosted server's ingest URL, ending in `/v1/ingest` |
| `debug` | `false` | Log rejected batches, dropped events and network errors to Logcat (tag `AppeekyAnalytics`) |
| `options.flushIntervalMs` | `10000` | How often queued events are sent while the app is open |
| `options.flushAt` | `20` | Send as soon as this many events are queued |
| `options.maxQueueSize` | `1000` | Oldest events are dropped beyond this |
| `options.sessionTimeoutMs` | `1800000` | Time in the background before a new session starts |
| `options.disabled` | `false` | Collect and send nothing, for example after an opt-out |

***

## Automatic Events

| Event | When |
| - | - |
| `first_open` | First launch after install |
| `session_start` | Launch, or returning after `sessionTimeoutMs` in the background |
| `app_background` | Going to the background, with `foreground_ms` |
| `identify` / `reset` | `identify(id)` / `identify(null)` |
| `ad_revenue` | `adRevenue(...)` |

Foreground and background come from `ProcessLifecycleOwner`, so they follow the whole app, not single Activities.

***

## Smart Links and the Install Referrer

On Android a [smart link](https://docs.appeeky.com/docs/analytics-smart-links.md) sends the visitor to Google Play with the campaign, the link and the click in the install referrer. On the first launch the SDK reads the referrer once and sends it with the first batch:

* A referrer with `aky_l` is attributed to that smart link.
* `utm_*` without it counts as a Play referrer campaign.
* `utm_source=google-play&utm_medium=organic` is organic.

If the link has an in-app destination, open it on the first launch:

```kotlin theme={"theme":{"light":"github-light","dark":"github-dark"}}
lifecycleScope.launch {
    Appeeky.getDeferredDeepLink()?.let { destination ->
        startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(destination)))
    }
}
```

Installs from outside Google Play have no referrer.

***

## Delivery and Storage

* Up to 100 events per request.
* No network, HTTP 429 or 5xx: the batch stays queued and is retried with backoff (5 s, doubling, up to 5 minutes). Event ids stay the same, so a retry is not counted twice.
* Other 4xx responses drop the batch.
* The install id, session state and queue are kept in the app's no-backup directory. Auto Backup never copies them, so a restored or new device counts as a new install.
* The SDK uses no reflection and ships its own consumer rules, so R8 / ProGuard needs nothing extra.

***

## Privacy

The SDK sends the install id, app version and build, Android version, device model, locale, the install referrer and launch URL of the first launch, and the events you track. It never reads the advertising id, Android id or other device identifiers. In the Play Console's Data safety form, declare **App activity → App interactions**, and **Financial info → Purchase history** if you use RevenueCat or Superwall, as collected, not shared and not used for advertising. See [Privacy](https://docs.appeeky.com/docs/analytics-privacy.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.