> ## 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.

# iOS Deep Links

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

<Info>
  **Supported on:** iOS SDK `1.0.61+`
</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 App Store and installs your app
3. On first launch, the SDK resolves the original link and returns the destination

```swift theme={null}
AppDNA.checkDeferredDeepLink { deepLink in
    guard let deepLink = deepLink else { return }
    // deepLink.screen = "/workout/123"
    // deepLink.params = ["ref": "instagram"]
    navigate(to: deepLink.screen, params: deepLink.params)
}
```

<Info>
  `checkDeferredDeepLink` is a static method on `AppDNA`. It should be called once on first launch, typically after `configure()` completes. The SDK returns `nil` 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 static method, not part of the deep links module:

```swift theme={null}
AppDNA.checkDeferredDeepLink { deepLink in
    guard let deepLink = deepLink else { return }
    navigate(to: deepLink.screen, params: deepLink.params)
}
```

## Module Access

```swift theme={null}
let deepLinks = AppDNA.deepLinks
```

### Module Methods

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

## DeferredDeepLink

| Property    | Type               | Description                                      |
| ----------- | ------------------ | ------------------------------------------------ |
| `screen`    | `String`           | Target screen path (e.g., `"/workout/123"`)      |
| `params`    | `[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:

```swift theme={null}
protocol AppDNADeepLinkDelegate: AnyObject {
    func onDeepLinkReceived(url: URL, params: [String: String])
}
```

### Example Implementation

```swift theme={null}
class LinkHandler: AppDNADeepLinkDelegate {
    func onDeepLinkReceived(url: URL, params: [String: String]) {
        // Route based on the incoming URL
        route(to: url.path, params: params)
    }

    private func route(to screen: String, params: [String: String]) {
        switch screen {
        case let s where s.hasPrefix("/workout/"):
            let id = String(s.dropFirst("/workout/".count))
            showWorkout(id: id)
        case "/referral":
            showReferralWelcome(referrer: params["ref"])
        default:
            showHome()
        }
    }
}

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

## Platform Setup

### Universal Links

To support Universal Links on iOS, configure your app:

1. Enable **Associated Domains** in your target's **Signing & Capabilities**.
2. Add your domain: `applinks:yourapp.com`
3. Host an `apple-app-site-association` file on your domain.

### Handling in AppDelegate or SceneDelegate

Pass incoming URLs to the SDK:

```swift theme={null}
// SceneDelegate
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    if let url = userActivity.webpageURL {
        AppDNA.deepLinks.handleURL(url)
    }
}

// Or in SceneDelegate for URL schemes
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    if let url = URLContexts.first?.url {
        AppDNA.deepLinks.handleURL(url)
    }
}
```

## Auto-Tracked Events

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

## Full Example

```swift theme={null}
import AppDNASDK

class AppCoordinator: AppDNADeepLinkDelegate {
    init() {
        AppDNA.deepLinks.setDelegate(self)
    }

    func handleFirstLaunch() {
        // Check for deferred deep link on first launch
        AppDNA.checkDeferredDeepLink { [weak self] deepLink in
            if let deepLink = deepLink {
                // User installed from a link -- route to the target screen
                self?.route(to: deepLink.screen, params: deepLink.params)

                // Track the visitor as a user trait
                AppDNA.identify(
                    userId: currentUserId,
                    traits: ["visitor_id": deepLink.visitorId]
                )
            } else {
                // Normal install -- show default onboarding
                self?.showOnboarding()
            }
        }
    }

    // MARK: - AppDNADeepLinkDelegate

    func onDeepLinkReceived(url: URL, params: [String: String]) {
        route(to: url.path, params: params)
    }

    private func route(to screen: String, params: [String: String]) {
        // Route to the correct screen based on the path
    }
}
```

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