# Android SDK (Kotlin and Java)

URL: https://traqio.app/docs/sdks/android
Last updated: 2026-10-22

Add Traqio to a native Android app: one Gradle dependency, one init call in Application.onCreate, and the Play Install Referrer does the attribution.

The Traqio Android SDK, `io.khufu.traqio:traqio-android`, attributes installs of a native Android app (Kotlin or Java) with the **Google Play Install Referrer** — the string Google Play hands to an app after install, in which Traqio's tracking link wrote its click id. It also queues and retries your events, records app opens for retention, and resolves deep links. No advertising id and no permission, unless you opt in.

## Requirements

- Android 5.0 (API 21) or later; Java 17 toolchain.
- Installs that go through Google Play: a sideloaded APK has no referrer and is reported organic.

## Set up

### Add the dependency

Kotlin DSL:
```kotlin
// app/build.gradle.kts
dependencies {
    implementation("io.khufu.traqio:traqio-android:0.1.0")
}
```

Groovy:
```groovy
// app/build.gradle
dependencies {
    implementation 'io.khufu.traqio:traqio-android:0.1.0'
}
```

The SDK brings Google's Install Referrer library with it and declares the `<queries>` entry Android 11+ requires to see Google Play — nothing to add to your manifest for attribution.

Until the artifact is on Maven Central, add the AAR we send you, with its one dependency:

```kotlin
// app/build.gradle.kts — the AAR you received, until the package is on Maven Central
dependencies {
    implementation(files("libs/traqio-android-0.1.0.aar"))
    implementation("com.android.installreferrer:installreferrer:2.2")
}
```

A local AAR does not carry its manifest's dependencies the way a Maven artifact does, hence the explicit Install Referrer line.

### Initialise in Application.onCreate

Kotlin:
```kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Traqio.init(this, sdkKey = "YOUR_SDK_KEY", endpoint = "https://api.traqio.app")
    }
}
```

Java:
```java
public class App extends Application {
    @Override public void onCreate() {
        super.onCreate();
        Traqio.init(this, "YOUR_SDK_KEY", "https://api.traqio.app");
    }
}
```

Register the class in the manifest (`android:name=".App"`). Initialising in the `Application` — not in an activity — lets the SDK see the intent of the first activity, which is how a link that cold-starts the app is resolved. Work happens on the SDK's own thread; the call returns at once.

### Track events and set the user id

Kotlin:
```kotlin
Traqio.setUserId(user.id)                 // after sign-in — same id as RevenueCat's app_user_id
Traqio.track("signup")
Traqio.track("purchase", 9.99, "EUR")
```

Java:
```java
Traqio.setUserId(user.getId());
Traqio.track("signup");
Traqio.track("purchase", 9.99, "EUR");
```

Name events with the vocabulary Meta and TikTok optimise on — [Event names](https://traqio.app/docs/concepts/events-and-revenue#names).

### Declare your link domain

```xml
<!-- AndroidManifest.xml, inside the activity that handles links -->
<intent-filter android:autoVerify="true">
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="https" android:host="go.example.com" android:pathPrefix="/c/" />
</intent-filter>
```

With your own tracking domain in place of `go.example.com`, Android opens the app — instead of the browser — for links on that domain, once it has verified the domain's `assetlinks.json`, which Traqio serves from your app's package name and signing-certificate fingerprints. See [Deep linking](https://traqio.app/docs/concepts/deep-linking).

## Receiving deep links

```kotlin
Traqio.onDeepLink { link ->
    link.deepLink?.let { navigateTo(it) }   // "/product/42" or "myapp://product/42"
}

// The install's deferred link, once resolved (null when it came from no link):
Traqio.getDeferredDeepLink { link -> /* … */ }
```

Every resumed activity's `ACTION_VIEW` intent is handed to the SDK automatically, once per intent; only tracking URLs (`https://<host>/c/<code>`) leave the device. A `singleTop` activity keeps its first intent unless you update it:

```kotlin
override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)          // or: Traqio.handleIntent(intent)
}
```

Callbacks run on the main thread.

## Consent

```kotlin
// From your own consent prompt — sharing with ad networks, not measurement.
Traqio.setConsent(granted)

// Or at launch, when the answer is already known:
Traqio.init(this, sdkKey = "YOUR_SDK_KEY", endpoint = "https://api.traqio.app", consent = granted)
```

`false` keeps measurement in your dashboard and stops every forward of this device to Meta, TikTok or any postback. See [Privacy → Consent](https://traqio.app/docs/concepts/privacy#consent).

## Advertising id (opt-in)

Off by default: the SDK sends no GAID. Turn it on only if you buy from networks that attribute by the advertising id — Unity Ads and AppLovin match their click to your install on it, and Unity's install notification needs it. It is never used as the install's identity.

```kotlin
Traqio.init(this, sdkKey = "YOUR_SDK_KEY", endpoint = "https://api.traqio.app", collectAdvertisingId = true)
```

app/build.gradle.kts:
```kotlin
implementation("com.google.android.gms:play-services-ads-identifier:18.3.0")
```

AndroidManifest.xml:
```xml
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
```

- The Traqio SDK declares neither the library nor the permission, so an app that leaves the option off asks for nothing because of Traqio. Without either, no id is sent.
- No id is sent when the user limited ad tracking or deleted their advertising id.
- With the option on, declare the advertising id in Google Play's Data safety form.

## API

| Call | What it does |
| --- | --- |
| init(context, sdkKey, endpoint, userId?, deepLinking = true, consent?, collectAdvertisingId = false) | Start once; reports the install on first launch. |
| track(name, value?, currency?) | Queue an event; sent in batches of 20, retried with backoff up to 5 minutes. |
| setUserId(id) | Attach your user id to everything sent from now on. |
| setConsent(granted) | Persist the user's ad-sharing consent. |
| onDeepLink(listener) | Receive direct and deferred deep links; removeDeepLinkListener to stop. |
| getDeferredDeepLink(callback) | The install's deferred link, or null. |
| handleIntent(intent) · handleUrl(url) | Resolve a URL yourself (automatic for resumed activities). |

## Not in this SDK yet

Compared with the [JavaScript engine](https://traqio.app/docs/sdks/javascript), the native Android SDK does not yet accept a store `transactionId` on purchases, report AdMob ad revenue, or erase a user from inside the app (`forgetMe`). Revenue still reaches Traqio through [RevenueCat](https://traqio.app/docs/integrations/revenuecat), and erasure through the [server-side call](https://traqio.app/docs/concepts/privacy#erasure).

> **Install Referrer reading** The referrer is read once on first launch, with a 5-second timeout. If Google Play does not answer in time, the install is reported without it — organic.

### See also

- [How an Android install is attributed](https://traqio.app/docs/concepts/attribution#android)
- [Tracking links](https://traqio.app/docs/concepts/tracking-links)

## Frequently asked questions

**Does the Traqio Android SDK need the GAID or a permission?**
No. It reads the Google Play Install Referrer through Google's Install Referrer library, which needs no permission, and identifies the install with a random id it generates and stores in the app's SharedPreferences. It reads the advertising id only if you turn on collectAdvertisingId — and then your app adds Google's ads-identifier library and the AD_ID permission, not the SDK.

**What is the minimum Android version?**
Android 5.0 (API 21). The SDK is compiled against API 34 and targets Java 17 bytecode.

**How is an Android install attributed?**
A Traqio tracking link sends the user to Google Play with Traqio's click id in the referrer parameter. Google Play hands that string to the app after install through the Install Referrer API; the SDK sends it with the install, and the server matches the click id to the recorded click. The match is exact, not statistical.
