Blog›Engineering
Engineering

Deferred deep link landing on the home screen? Five places the payload gets lost

The link works and the SDK is set up, yet new installs open on the home screen. Five places a deferred deep link loses its payload, and how to find which.

AAAhsan AliWrites about deep linking & attributionSep 27, 2026·5 min read
Diagram: the expected first open on the intended screen versus an actual first open on the home screen, with five checkpoints to trace the payload.

You built deferred deep linking and tested it. The campaign link opened the app on the right screen. You shipped it.

Then a user writes in: they tapped your referral link, installed the app, and landed on the home screen. The product they expected never appeared.

It's one of the nastiest failures in mobile, because everything looks right. The link works, the SDK is configured, the routing code exists — and something between the click and the first screen swallowed the destination.

“Deferred deep linking isn't one mechanism. It's a chain, and the payload can be lost at any link in it. The useful question isn't whether it works — it's which step broke.”

Neither Apple nor Google carries your link's context through an install. Deferred deep linking is built on top of the operating system, by a service that sees both the click and the first open:

  1. 1The click is recorded. The user taps a smart link; the service records the click and the link's destination and payload, then sends the user to the right store.
  2. 2The install happens. The user installs from the App Store or Google Play. The original URL doesn't come with it.
  3. 3The first open is matched. The SDK reports the first launch, and the service matches it to the click.
  4. 4The payload is delivered. The SDK hands the destination and custom data to your app, and your router opens the screen.

Step 3 is where the platforms differ. On Android, the Google Play Install Referrer usually carries a token through the store, so the match is deterministic. iOS has no equivalent, so LinkTrail carries a click token on the clipboard, which the SDK recovers on first launch. Where neither is available, LinkTrail can fall back to probabilistic matching — off by default, consent-gated, and comparing only the IP address and platform. The methodology page documents exactly what's compared.

The symptom is the same wherever the chain breaks: the app opens on its default screen. The cause is different each time.

The SDK delivers the link through a callback. If your app builds its navigation after that callback fires, or ignores links until onboarding finishes, the destination arrives with nowhere to go.

Symptom: it works sometimes, or only in debug builds, where startup is slower.

Diagnosis: log inside your onLink handler and at the point your navigation becomes ready. Check which comes first.

Fix: configure the SDK at the earliest point of launch — your App initialiser or AppDelegate on iOS, Application.onCreate() on Android — and register onLink before anything that navigates. If the link can arrive before your router exists, hold it and route once the router is ready. In Flutter, subscribe to LinkTrail.onLink before calling configure.

// At launch, before any navigation code runs
try LinkTrail.configure(apiKey: "lt_live_...")
LinkTrail.shared?.onLink { link, source in
    router.route(to: link.path, customData: link.customData)
}

2. The click never reaches the app

The service can only match what it can connect. On iOS, LinkTrail reads the click token only when the user taps a paste control — the default clickTokenSource — so if your first-launch screen doesn't render one, there's nothing to match. On Android, the Install Referrer only exists for installs that came through Google Play, so a build pushed with adb install arrives without one.

Symptom: deferred links work on one platform and not the other, or never in local testing.

Fix: on iOS, render the paste control on your first-launch screen and set autoTrackInstall: false, or choose .automatic and accept the system's paste alert — the iOS SDK docs cover both. On Android, test the deferred path through a Play testing track.

Consent gating is on by default. On Android it is deny-by-default: a fresh install is held until your app calls setConsent(true) or setConsent(false), and only then does the deferred link route — granting attributes it, denying routes it without recording anything. A build with no consent prompt wired up waits forever and looks broken. On iOS, links route immediately and attribution waits for consent.

Fix: call setConsent once your consent prompt is answered, on every path through onboarding — including the one where the user dismisses it.

4. The match window has passed — or the probabilistic match can't be made

Matching is time-bounded. LinkTrail's default click window is seven days, configurable per workspace; an install after that is reported as organic, and the first open gets no payload. That's expected behaviour, but it matters for campaigns where people take days to install.

When an install is matched probabilistically rather than by a token, the IP address has to line up between the click and the first open. A switch from mobile data to Wi-Fi, or a click that went through iCloud Private Relay, can break it. That's a structural limit of probabilistic matching, which is why the deterministic paths above come first.

Fix: check the install's match type in the match audit log (Growth and above). If it says none, look at the window and the deterministic path for that platform before tuning anything else.

5. Sign-in throws the payload away

This one is subtle. The SDK delivers the destination correctly, the app receives it — and then requires the user to sign in or finish onboarding before navigating anywhere. By the time they're done, the destination is gone.

Symptom: onLink fires with the right destination, but the user still lands on the home screen after signing up.

Fix: store the destination the moment it arrives, and route to it once sign-in completes:

LinkTrail.shared?.onLink { link, source in
    // Keep the destination until the user can actually get there
    UserDefaults.standard.set(link.path, forKey: "pendingDeepLinkPath")
    if session.isSignedIn { router.routeToPendingLink() }
}

// After sign-in or onboarding completes:
func routeToPendingLink() {
    guard let path = UserDefaults.standard.string(forKey: "pendingDeepLinkPath") else { return }
    UserDefaults.standard.removeObject(forKey: "pendingDeepLinkPath")
    router.route(to: path)
}

The same pattern works on Android with SharedPreferences. Store only the path and the parts of the payload you need — not tokens or anything you wouldn't want in a log.

A checklist before you file a bug

CheckWhat to verifyWhere
Callback orderonLink is registered before anything navigatesSDK and app logs
Click tokenPaste control rendered on iOS; Play install on AndroidFirst-launch screen, test track
ConsentsetConsent is called on every onboarding pathYour consent flow
Match typeThe install shows deterministic, not noneMatch audit log (Growth+)
Payload persistenceThe destination survives sign-inonLink logging

The test that isolates it: on a clean install, tap the link and install straight away. If that works but production doesn't, look at the match window and the click path. If it fails too, it's callback order, consent or routing. The pre-release testing checklist covers the clean-install routine, and resetForTesting saves the reinstall between runs.

The chain is only as strong as its weakest step. Knowing which step broke is faster than guessing.

AA

Ahsan Ali

Writes about deep linking & attribution

Ahsan Ali works with the teams integrating LinkTrail's iOS, Android, React Native, and Flutter SDKs, which is where most of what he writes here starts: deferred deep linking, install attribution after ATT, and the parts of the mobile growth stack the category tends to leave vague.

Tagged#Deferred deep linking#Debugging#iOS#Android

Questions about this post

Why does my deferred deep link open the home screen?

Something between the click and the first screen dropped the payload: the app routed before the link arrived, the click couldn't be matched to the install, the consent decision was never made, the install came after the match window, or sign-in discarded the destination. Logging onLink tells you which side of the chain failed.

Why do deferred deep links work on Android but not on iOS?

Android usually matches through the Play Install Referrer, which comes through Google Play automatically. iOS has no equivalent, so LinkTrail recovers a click token from the clipboard — by default only when the user taps a paste control. If that control isn't rendered, deferred installs on iOS arrive unmatched.

How long does a deferred deep link stay valid?

As long as the attribution window. LinkTrail's default click window is seven days, configurable per workspace. An install after that is treated as organic, so the first open gets no payload.