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

# Android Deep Links

> Handle deferred deep links for first-launch routing and attribution

<Info>
  **Supported on:** Android SDK `1.0.33+`
</Info>

The deep links module handles deferred deep links — routing users to the correct screen on first launch after installing from a link. This enables attribution tracking, referral programs, and contextual first-launch experiences.

## Deferred Deep Links

A deferred deep link works across the install boundary:

1. User clicks a link on the web (e.g., `https://yourapp.com/workout/123?ref=instagram`)
2. User is redirected to the Play Store and installs your app
3. On first launch, the SDK resolves the original link and returns the destination

```kotlin theme={null}
AppDNA.checkDeferredDeepLink { deepLink ->
    if (deepLink != null) {
        // deepLink.screen = "/workout/123"
        // deepLink.params = mapOf("ref" to "instagram")
        navigate(deepLink.screen, deepLink.params)
    }
}
```

<Info>
  `checkDeferredDeepLink` is a static method on `AppDNA`. It should be called once on first launch, typically after `configure()` completes. The SDK uses the Google Install Referrer API plus AppDNA's visitor-context resolution. It returns `null` if no deferred link is found or if the app was not installed from a link.
</Info>

## Deferred Deep Link Check

`checkDeferredDeepLink` is a top-level method on `AppDNA`, not part of the deep links module:

```kotlin theme={null}
AppDNA.checkDeferredDeepLink { deepLink ->
    if (deepLink != null) {
        navigate(deepLink.screen, deepLink.params)
    }
}
```

## Module Access

```kotlin theme={null}
val deepLinks = AppDNA.deepLinks
```

### Module Methods

| Method        | Signature                                        | Description                                              |
| ------------- | ------------------------------------------------ | -------------------------------------------------------- |
| `setDelegate` | `setDelegate(delegate: AppDNADeepLinkDelegate?)` | Set a delegate for deep link callbacks                   |
| `handleURL`   | `handleURL(url: String)`                         | Pass an incoming deep link URL to the SDK for processing |

## DeferredDeepLink

| Property    | Type                  | Description                                      |
| ----------- | --------------------- | ------------------------------------------------ |
| `screen`    | `String`              | Target screen path (e.g., `"/workout/123"`)      |
| `params`    | `Map<String, String>` | Additional parameters (e.g., referrer, campaign) |
| `visitorId` | `String`              | The visitor identifier from the originating link |

## AppDNADeepLinkDelegate

Register a delegate for deep link events:

```kotlin theme={null}
interface AppDNADeepLinkDelegate {
    fun onDeepLinkReceived(url: String, params: Map<String, String>)
}
```

### Example Implementation

```kotlin theme={null}
import ai.appdna.sdk.AppDNA
import ai.appdna.sdk.AppDNADeepLinkDelegate
import android.net.Uri

class LinkHandler : AppDNADeepLinkDelegate {

    override fun onDeepLinkReceived(url: String, params: Map<String, String>) {
        // Route based on the incoming URL
        val path = Uri.parse(url).path ?: "/"
        route(path, params)
    }

    private fun route(screen: String, params: Map<String, String>) {
        when {
            screen.startsWith("/workout/") -> {
                val id = screen.removePrefix("/workout/")
                showWorkout(id)
            }
            screen == "/referral" -> showReferralWelcome(params["ref"])
            else -> showHome()
        }
    }

    private fun showWorkout(id: String) { /* ... */ }
    private fun showReferralWelcome(referrer: String?) { /* ... */ }
    private fun showHome() { /* ... */ }
}

AppDNA.deepLinks.setDelegate(LinkHandler())
```

## Platform Setup

### App Links

To support App Links on Android:

1. Add intent filters to your `AndroidManifest.xml`:

```xml theme={null}
<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.com" />
</intent-filter>
```

2. Host a Digital Asset Links file at `https://yourapp.com/.well-known/assetlinks.json`.

### Handling in Activity

Pass the incoming intent's data URL to the SDK:

```kotlin theme={null}
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    intent?.dataString?.let { AppDNA.deepLinks.handleURL(it) }
}

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    intent.dataString?.let { AppDNA.deepLinks.handleURL(it) }
}
```

## Auto-Tracked Events

| Event                         | Trigger                                          |
| ----------------------------- | ------------------------------------------------ |
| `deep_link_handled`           | A deep link URL is processed                     |
| `deferred_deep_link_resolved` | A deferred deep link is resolved on first launch |

## Full Example

```kotlin theme={null}
import ai.appdna.sdk.AppDNA
import ai.appdna.sdk.AppDNADeepLinkDelegate
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity(), AppDNADeepLinkDelegate {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        AppDNA.deepLinks.setDelegate(this)

        // Check for deferred deep link on first launch
        AppDNA.checkDeferredDeepLink { deepLink ->
            if (deepLink != null) {
                // User installed from a link — route to the target screen
                route(deepLink.screen, deepLink.params)

                // Track the visitor as a user trait
                AppDNA.identify(
                    userId = currentUserId,
                    traits = mapOf("visitor_id" to deepLink.visitorId),
                )
            } else {
                // Normal install — show default onboarding
                showOnboarding()
            }
        }

        intent?.dataString?.let { AppDNA.deepLinks.handleURL(it) }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        intent.dataString?.let { AppDNA.deepLinks.handleURL(it) }
    }

    // AppDNADeepLinkDelegate

    override fun onDeepLinkReceived(url: String, params: Map<String, String>) {
        val path = Uri.parse(url).path ?: "/"
        route(path, params)
    }

    private val currentUserId: String get() = "user-123"
    private fun route(screen: String, params: Map<String, String>) { /* ... */ }
    private fun showOnboarding() { /* ... */ }
}
```

<Note>
  Deep link routes are configured in the Console under **Engagement > Deep Links**. The SDK resolves deferred links by checking the Google Install Referrer plus AppDNA's stored visitor context on first launch.
</Note>
