Configure Deeplinks (SDK part)

Overview

Deferred Deeplinking lets you attribute users who install and open the app after clicking an Apphud deep link. The SDK supports two attribution flows:

  • Direct deeplinking — the app is opened from a Universal Link / App Link or custom scheme, and the SDK sends the opened URL to Apphud.
  • Deferred deeplinking — the app requests attribution for the current installation after the first launch, even when the app was installed before the link could be opened directly.

Use this guide after the Apphud SDK is installed and initialized. See Initialization and Identification if you have not initialized the SDK yet.

📘

Platform setup required

Apphud receives the attribution result through the SDK, but your app must still be configured to open links on each platform:

  • iOS: configure Universal Links using Apple's guide: Supporting universal links in your app
  • Android: configure Android App Links using Google's guide: Android App Links

Requirements

  • Use an Apphud SDK version that includes Deferred Deeplinking support.
  • Configure Universal Links on iOS and/or Android App Links on Android for your domain.
  • Register a deeplink handler in Apphud SDK to receive attribution results.
  • Forward incoming links to Apphud SDK from your app lifecycle callbacks.
  • Request deferred attribution after SDK initialization, typically once on the first launch after install.
🚧

Important

The deeplink handler may be called multiple times during the app lifecycle: for direct link opens and for deferred attribution requests. If Apphud does not find a match, the handler receives an empty attribution dictionary/map.

Attribution Result

The deeplink handler receives:

  • attribution — attribution data returned by Apphud. It is empty when no match is found.
  • kind — attribution kind:
    • direct / DIRECT: the user opened an actual deep link.
    • deferred / DEFERRED: attribution was resolved for the current installation.
  • url / uri — the original link for direct deeplinking, or nil / null for deferred deeplinking.

iOS

1. Configure Universal Links

Configure Associated Domains in Xcode and host the apple-app-site-association file for your link domain. Follow Apple's official guide: Supporting universal links in your app.

2. Add a deeplink handler during initialization

import ApphudSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        Apphud.start(apiKey: "YOUR_API_KEY", deeplinkHandler: { attribution, kind, url in
            switch kind {
            case .direct:
                print("Direct deeplink attribution", url?.absoluteString ?? "", attribution)
            case .deferred:
                print("Deferred deeplink attribution", attribution)
            }

            // Use attribution values here, for example to route the user,
            // unlock onboarding content, or store campaign parameters.
        })

        // Handles direct links that launched the app.
        Apphud.handleLaunchOptions(launchOptions: launchOptions)

        return true
    }
}

You can also set or replace the handler after initialization:

Apphud.setDeeplinkHandler { attribution, kind, url in
    print("Deeplink attribution", kind, url?.absoluteString ?? "", attribution)
}

3. Forward direct deep links to Apphud

For custom scheme links or links delivered through application(_:open:options:):

func application(
    _ app: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
    Apphud.handleOpen(url: url)
    return true
}

For Universal Links:

func application(
    _ application: UIApplication,
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
    Apphud.continueUserActivity(userActivity)
    return true
}

4. Request deferred attribution

Call this after Apphud SDK initialization, typically once on the first launch after install:

if isFirstLaunchAfterInstall {
    Apphud.requestDeferredDeeplinkAttribution()
}

The result is delivered to the same deeplinkHandler with kind == .deferred and url == nil.

📘

Note

Deferred attribution uses a temporary hidden web view to resolve the visitor identifier. Direct Universal Link attribution should still be configured and forwarded separately as shown above.

Android

1. Configure Android App Links

Add an ACTION_VIEW intent filter to the Activity that should receive your links and host the Digital Asset Links file for your domain. Follow Google's official guide: Android App Links.

Example AndroidManifest.xml:

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTop">

    <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="example.com"
            android:pathPrefix="/deeplink" />
    </intent-filter>
</activity>

Replace example.com and /deeplink with your actual link domain and path.

2. Add a deeplink handler during initialization

import android.app.Application
import android.util.Log
import com.apphud.sdk.Apphud
import com.apphud.sdk.ApphudDeeplinkAttributionKind

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        Apphud.start(
            context = this,
            apiKey = "YOUR_API_KEY",
            deeplinkHandler = { attribution, kind, uri ->
                when (kind) {
                    ApphudDeeplinkAttributionKind.DIRECT -> {
                        Log.d("Apphud", "Direct deeplink: uri=$uri attribution=$attribution")
                    }
                    ApphudDeeplinkAttributionKind.DEFERRED -> {
                        Log.d("Apphud", "Deferred deeplink: attribution=$attribution")
                    }
                }

                // Use attribution values here, for example to route the user,
                // unlock onboarding content, or store campaign parameters.
            },
        )
    }
}

You can also set or replace the handler after initialization:

Apphud.setDeeplinkHandler { attribution, kind, uri ->
    Log.d("Apphud", "Deeplink attribution: kind=$kind uri=$uri attribution=$attribution")
}

3. Forward direct deep links to Apphud

Forward the Activity intent from both onCreate and onNewIntent:

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.apphud.sdk.Apphud

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

        Apphud.handleIntent(intent)
    }

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

        Apphud.handleIntent(intent)
    }
}

Apphud.handleIntent(intent) processes only ACTION_VIEW intents with a link URI. You can also pass a URI directly:

Apphud.handleUri(uri)

4. Request deferred attribution

Call this from a visible Activity after Apphud SDK initialization, typically once on the first launch after install:

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

        Apphud.handleIntent(intent)

        if (isFirstLaunchAfterInstall()) {
            Apphud.requestDeferredDeeplinkAttribution(this)
        }
    }
}

The result is delivered to the same deeplinkHandler with kind == ApphudDeeplinkAttributionKind.DEFERRED and uri == null.

📘

Note

Deferred attribution on Android uses a temporary 1x1 WebView attached to the provided Activity to resolve the visitor identifier. Call it from a started, visible Activity rather than from Application.onCreate().

Testing

  1. Install a build with the Apphud SDK version that supports Deferred Deeplinking.
  2. Verify that Universal Links / App Links open the app directly.
  3. Open a direct link and confirm that the handler receives direct / DIRECT attribution with the original URL.
  4. For deferred deeplinking, click the link before installing the app, install and open the app, then call the deferred attribution request once after initialization.
  5. Confirm that the handler receives deferred / DEFERRED attribution. If there is no match, the attribution payload will be empty.

Troubleshooting

  • If direct links do not open the app, verify Universal Links / App Links configuration first:
    • iOS: Bundle Identifier, Associated Domains entitlement must match with apple-app-site-association on record.
    • Android: intent filter, package name, signing certificate fingerprint must match with assetlinks.json
  • Make sure Apphud SDK is initialized before requesting deferred attribution.
  • Make sure incoming links are forwarded to Apphud from all relevant lifecycle callbacks.
  • Do not assume the handler is called only once; handle both direct and deferred results idempotently.
  • An empty attribution payload means Apphud did not find a matching attribution for that request.