Skip to content

Android SDK

Add the Trace SDK to your module-level build.gradle.kts:

dependencies {
implementation("io.traceclick:sdk:<version>")
}

Initialize Trace in your Application class. This must happen before any activity launches.

class MyApp : Application() {
override fun onCreate() {
super.onCreate()
TraceAndroid.initialize(
application = this,
config = TraceConfig(
apiKey = "tr_live_xxxxxxxxxxxx",
hashSalt = "your_64_char_hex_salt",
region = Region.US // or Region.EU
)
)
}
}

The SDK automatically performs attribution on first launch — no additional call needed.

For simple apps, set a deep link listener to receive attributed links:

TraceAndroid.setDeepLinkListener { deepLink ->
// deepLink.path — e.g. "/product/123"
// deepLink.params — e.g. {"color": "blue"}
// deepLink.isDeferred — true if delivered via install attribution
navigateTo(deepLink.path, deepLink.params)
}

In your launcher activity, forward intents so the SDK can process direct deep links:

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
TraceAndroid.handleIntent(intent)
setContent { App() }
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
TraceAndroid.handleIntent(intent)
}
}

For Compose apps using Navigation3, Trace provides a deep link mapper and entry decorator:

@Composable
fun App() {
val backStack = rememberMutableBackStack(HomeRoute)
// Define how deep link paths map to your routes
val mapper = rememberDeepLinkMapper {
link("/product/{id}") { params ->
ProductRoute(id = params.require("id"))
}
link("/invite/{code}") { params ->
InviteRoute(code = params.require("code"))
}
link("/settings") { SettingsRoute }
}
TraceProvider {
val decorator = rememberTraceEntryDecorator(
backStack = backStack,
routeMapper = mapper,
// Optional: delay deferred deep links until user is logged in
authGate = { isLoggedIn }
)
NavDisplay(
backStack = backStack,
entryDecorators = listOf(decorator)
)
}
}

The params object in your route mapper provides typed accessors:

link("/product/{id}") { params ->
val id = params.require("id") // throws if missing
val color = params["color"] // nullable String
val page = params.int("page") // Int?
val premium = params.boolean("premium") // Boolean?
ProductRoute(id, color, page, premium)
}

To react to the attribution result directly (e.g. for analytics):

TraceAndroid.setAttributionListener { result ->
when (result) {
is AttributionResult.Attributed -> {
analytics.track("install_attributed", mapOf(
"method" to result.method,
"campaign" to result.campaignId
))
}
is AttributionResult.Organic -> {
analytics.track("install_organic")
}
is AttributionResult.Error -> {
log.warn("Attribution failed: ${result.message}")
}
}
}

Track post-install events to measure campaign effectiveness:

TraceAndroid.trackEvent(
name = "purchase_completed",
properties = mapOf(
"value" to "49.99",
"currency" to "USD",
"product_id" to "SKU_123"
)
)

See Event Tracking for best practices.

To support direct deep links (not just deferred), add your Trace domain to AndroidManifest.xml:

<activity android:name=".MainActivity">
<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="yourapp.traceclick.io"
android:pathPrefix="/l/" />
</intent-filter>
</activity>