# Usage

Detour delivers links to your app through the launching intent. `DetourDelegate` attaches to the Activity lifecycle, resolves the incoming link, whether deferred, App Link, or custom scheme, and returns a `LinkResult` to navigate with. Apps that only need deferred links can skip the delegate and call `Detour.getDeferredLink()` directly.

## Delegate setup

`DetourDelegate` is the recommended integration for classic Android apps. It wraps the coroutine calls to `Detour.processLink(...)` and returns `LinkResult` in a callback.

```kotlin
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.swmansion.detour.Detour
import com.swmansion.detour.DetourConfig
import com.swmansion.detour.DetourDelegate
import com.swmansion.detour.models.LinkProcessingMode
import com.swmansion.detour.models.LinkResult

class MainActivity : AppCompatActivity() {
    private val detourDelegate = DetourDelegate(
        lifecycleOwner = this,
        config = DetourConfig(
            apiKey = BuildConfig.DETOUR_API_KEY,
            appId = BuildConfig.DETOUR_APP_ID,
            linkProcessingMode = LinkProcessingMode.ALL,
        ),
        onLinkResult = { result -> handleLinkResult(result) }
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Detour.initialize(this, detourDelegate.config)
        detourDelegate.onCreate(intent)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        detourDelegate.onNewIntent(intent)
    }

    private fun handleLinkResult(result: LinkResult) {
        // handle result and navigate
    }
}
```

`onCreate(intent)` processes the intent that created a new activity instance.
`onNewIntent(intent)` processes a link delivered to an existing instance, for
example when the activity uses `singleTop` or `singleTask`. Keep the
`setIntent(intent)` call so the activity's current intent stays in sync.

:::caution[Initialize once]
Call `Detour.initialize(...)` exactly once per process. A second call logs a warning and returns without re-configuring the SDK.
:::

For complete, runnable integrations, see [Examples](https://detour.swmansion.com/docs/sdk/android/examples).

## Handle resolved links

`processLink()` and `getDeferredLink()` return one of four results:

- `LinkResult.Success` — carries `url`, `route`, `pathname`, `params`, and `type`
- `LinkResult.NotFirstLaunch` — the deferred flow was already consumed in this install or session
- `LinkResult.NoLink` — no matching link
- `LinkResult.Error` — a runtime or integration error

Typical routing pattern:

```kotlin
when (result) {
    is LinkResult.Success -> navigateToRoute(result.route, result.params)
    is LinkResult.NotFirstLaunch -> Unit
    is LinkResult.NoLink -> Unit
    is LinkResult.Error -> Log.e("Detour", "Link error", result.exception)
}
```

## Link processing modes

`DetourConfig.linkProcessingMode` controls which link sources the SDK handles:

| Value | Deferred | App Links (`http/https`) | Custom scheme |
| --- | --- | --- | --- |
| `ALL` (default) | Yes | Yes | Yes |
| `WEB_ONLY` | Yes | Yes | No |
| `DEFERRED_ONLY` | Yes | No | No |

Use `DEFERRED_ONLY` when your navigation stack already handles App Link and scheme intents, and Detour should only resolve first-install deferred links.

## Click limits

Before it delivers an App Link or Universal Link, the SDK checks the click against your plan's limit. Within the limit, links resolve normally.

### Over the limit

The link is **not** delivered. `processLink()` returns `LinkResult.NoLink`, and so does the `DetourDelegate` callback.

The SDK logs `[Detour:CLICK_LIMIT_ERROR]` in logcat with `clicksInPeriod` and `effectiveLimit`.

### Other link types

This flow applies only to App Links and Universal Links.

- **Deferred and short links** — the same plan limits apply on the backend, but the SDK raises no click-limit error. An over-limit link fails to resolve: `getDeferredLink()` returns `LinkResult.NoLink` and `resolveShortLink()` returns `null`.
- **Custom scheme links** — resolved on device, never limit-checked.

:::note[Fail-open by design]
If the limit check cannot complete because of a network or backend error, the SDK delivers the link, so a temporary outage does not block navigation. Limits are enforced only on an explicit "denied" response.
:::

For per-plan limits, pay-as-you-go overage, and how to raise them, see [Billing & Payments](https://detour.swmansion.com/docs/platform/fundamentals/billing).

## Deferred-only flow

In `DEFERRED_ONLY` mode you can skip `DetourDelegate` and call `Detour.getDeferredLink()` directly:

```kotlin
Detour.initialize(
    this,
    DetourConfig(
        apiKey = BuildConfig.DETOUR_API_KEY,
        appId = BuildConfig.DETOUR_APP_ID,
        linkProcessingMode = LinkProcessingMode.DEFERRED_ONLY,
    )
)

lifecycleScope.launch {
    when (val result = Detour.getDeferredLink()) {
        is LinkResult.Success -> navigateToRoute(result.route, result.params)
        else -> Unit
    }
}
```

See the `example-deferred-only` app in [Examples](https://detour.swmansion.com/docs/sdk/android/examples).

## Analytics

`Detour.initialize(...)` turns analytics on. With the SDK initialized, it logs one event by itself: `app_open`, a retention event sent once per session on cold start. App Link and Universal Link opens are not client events. The backend records them through the click endpoint (see [Click limits](#click-limits)).

Everything else you log yourself, through `DetourAnalytics`.

```kotlin
import com.swmansion.detour.analytics.DetourAnalytics
import com.swmansion.detour.analytics.DetourEventNames

DetourAnalytics.logEvent(
    DetourEventNames.Purchase,
    mapOf("item" to "subscription_premium", "currency" to "USD"),
)

DetourAnalytics.logRetention("home_screen_opened")
```

:::note[SDK version header]
Every request the SDK sends carries an `X-SDK: android/<version>` header, used for diagnostics and SDK-usage analysis. It needs no configuration.
:::

## Related pages

- [Examples](https://detour.swmansion.com/docs/sdk/android/examples)
- [API Reference](https://detour.swmansion.com/docs/sdk/android/api-reference)
- [Custom Storage](https://detour.swmansion.com/docs/sdk/android/custom-storage)
- [Testing & Troubleshooting](https://detour.swmansion.com/docs/sdk/android/testing)