Skip to content

Deep Links

Trace delivers deep links to your app in two scenarios:

  1. Direct deep links — user clicks a Trace short link while the app is installed. The link opens the app directly.
  2. Deferred deep links — user clicks a link, installs the app, then opens it for the first time. Trace delivers the deep link payload after attribution.

Both arrive through the same listener.

TraceAndroid.setDeepLinkListener { deepLink ->
val path = deepLink.path // "/product/123"
val params = deepLink.params // {"color": "blue"}
val deferred = deepLink.isDeferred // true if from install attribution
navigateTo(path, params)
}

For Compose apps, use the deep link mapper to convert paths into typed route objects:

val mapper = rememberDeepLinkMapper {
link("/product/{id}") { params ->
ProductRoute(id = params.require("id"))
}
link("/invite/{code}") { params ->
InviteRoute(code = params.require("code"))
}
link("/settings") {
SettingsRoute
}
}

Then wire it into your navigation:

TraceProvider {
val decorator = rememberTraceEntryDecorator(
backStack = backStack,
routeMapper = mapper
)
NavDisplay(
backStack = backStack,
entryDecorators = listOf(decorator)
)
}

When a deep link arrives with path /product/abc, the mapper calls your lambda and pushes ProductRoute(id = "abc") onto the back stack.

Use {name} in the path pattern to capture segments:

link("/product/{id}") { params ->
// params.require("id") → "abc"
}
link("/category/{cat}/item/{item}") { params ->
// params.require("cat") → "electronics"
// params.require("item") → "phone-123"
}

Query parameters from deepLinkParams are also available:

// Link created with: deepLinkPath="/product/123", deepLinkParams={"color": "blue"}
link("/product/{id}") { params ->
val id = params.require("id") // "123"
val color = params["color"] // "blue"
ProductRoute(id, color)
}
MethodReturn typeBehavior
params["key"]String?Returns null if missing
params.require("key")StringThrows if missing
params.int("key")Int?Parses to Int, null if missing or invalid
params.long("key")Long?Parses to Long
params.boolean("key")Boolean?Parses to Boolean

Deferred deep links often arrive before the user has signed in. Use an auth gate to hold the deep link until the user is authenticated:

val decorator = rememberTraceEntryDecorator(
backStack = backStack,
routeMapper = mapper,
authGate = { isLoggedIn } // deep link waits until this returns true
)

The flow:

  1. User clicks campaign link → installs app → opens app
  2. SDK receives deferred deep link for /invite/abc
  3. authGate returns false (user not logged in yet) → deep link is parked
  4. User signs up or logs in → authGate returns true
  5. Deep link is delivered → InviteRoute(code = "abc") pushed to back stack

When creating short links via the API, specify the deep link data:

Terminal window
curl -X POST https://api.traceclick.io/v1/links \
-H "X-Api-Key: tr_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"deepLinkPath": "/product/123",
"deepLinkParams": {"color": "blue", "ref": "email"},
"campaignId": "summer_sale",
"fallbackUrl": "https://yourapp.com/product/123"
}'

When this link drives an install, the SDK delivers:

path = "/product/123"
params = {"color": "blue", "ref": "email"}
isDeferred = true