Deep Linking Platforms Compared: Routing and Fallbacks
Every deep-linking platform sits on the same three OS primitives: Universal Links on iOS, App Links on Android, and legacy custom URI schemes for the edge cases. Where they actually split is in production — what happens when the app isn't installed, and how the deferred match survives iOS 15's iCloud Private Relay masking the IP address the old trick relied on. That split defines the whole category. Clipboard-deterministic matching on iOS, IP-based probabilistic matching (mostly broken now), and Android's signed Install Referrer, which never needed a device ID in the first place.
Why every "feature grid" comparison is lying to you
Open any vendor page and you'll see the same row of green checkmarks. "Supports deferred deep linking." "Configurable fallbacks." "Full-funnel analytics." Every one of those is technically true and practically useless, because a checkmark tells you a code path exists. It doesn't tell you whether that path fires when a user taps your link from inside TikTok's in-app browser on an iPhone with Private Relay switched on.
Three axes actually break in the field, and none of them show up cleanly on a grid. First, fallback behavior when the app is absent — does the user land on your mobile web page or get dumped into the App Store? Second, the deferred match method on iOS: clipboard, fingerprint, or hybrid. Third, analytics granularity, which shifts depending on whether the user is a fresh deferred install or a warm returning device.
I'll walk each of these on-device, then hand you a test rubric I run before signing anything. One recurring theme to internalize now: the postback confirming all of this happened will arrive whenever it feels like it. Sometimes minutes later. Sometimes after you've already given up and gone to lunch. Instrument for reconciliation, not real-time faith.
The plumbing all these platforms share
Here's the shared substrate, because knowing it tells you what's genuinely vendor-specific versus what's just the OS doing OS things.
A deep link is a URL that, when tapped, opens a specific screen inside an app rather than a browser. A deferred deep link carries that destination through an install — user taps, app isn't there, user installs, and on first launch the app routes them where they meant to go.
Walk the click on iOS. A user taps a Universal Link. iOS checks whether an installed app claims that domain via its Associated Domains entitlement and the apple-app-site-association file. If the app is present, iOS hands it the URL directly and the browser never opens. If the app is absent — or if the association check fails for any of a dozen finicky reasons — the link resolves as a plain web URL and loads in Safari or whatever webview the user happens to be sitting in.
That last part is where the docs go quiet. Apple's documentation doesn't spell out what happens when the tap originates inside an in-app browser like Instagram's or TikTok's, and testing shows those webviews frequently don't honor Universal Links at all. They treat the URL as web content and render your fallback page instead of opening the app, even when the app is installed. So the same link behaves differently depending on which app the user tapped it from. That's not a vendor's fault. That's the platform. But it's exactly the kind of thing a feature grid will never tell you.
Android runs a parallel flow with App Links verified against assetlinks.json, plus the Install Referrer as its deferred backbone, which I'll cover in full below. Legacy URI schemes (myapp://) still exist as a last-resort fallback, but they can't defer and any app can claim them, so treat them as duct tape, not infrastructure.
The iOS deferred-match problem: Private Relay broke the old trick
For years, deferred deep linking on iOS ran on a quiet hack. When a user tapped a link, the platform logged their IP and a rough device fingerprint. After they installed and opened the app, it grabbed the IP again on first launch and matched the two inside a short window. Probabilistic, imperfect, but good enough at scale.
Then iOS 15 shipped iCloud Private Relay, which masks the Safari-originating IP for iCloud+ subscribers. The IP the platform saw at click time no longer matched the IP it saw at launch, because Apple was routing that traffic through relay servers. The match rate for that population fell off a cliff, and the probabilistic model started returning garbage for a growing slice of iPhone users.
The industry's deterministic answer was the clipboard. Branch's NativeLink, per Branch's own documentation, "copies deep link context to the device clipboard before install and reads it when the app first opens, entirely on-device." No IP, no fingerprint — the destination rides across the install in the pasteboard itself. Branch states this yields 100% deferred match accuracy, surfaced to your app as +match_guaranteed=true, versus post-iOS-14 probabilistic matching that "usually fails unless the user opts into IDFA." Dub takes a hybrid line: per Dub's docs, deterministic clipboard matching when a link is present in the clipboard, falling back to probabilistic IP matching when there's no clipboard link or the user declines the paste.
That "match guaranteed" claim is real. But you're buying it with a system dialog. Per the OWASP Mobile Application Security guidance, since iOS 14 the system notifies the user when an app reads pasteboard content written by another app, and since iOS 16 it prompts with an explicit paste confirmation dialog on access. So your brand-new user, three seconds into their first session, sees "AppName pasted from Safari" — a prompt most people have never consciously noticed, and some will find alarming. Deterministic routing, yes. Free, no. Any vendor selling you clipboard matching without mentioning that dialog is hiding the price tag.
Android's cleaner story: the Install Referrer backbone
Android never needed the clipboard, because Google Play hands you a signed answer.
The Google Play Install Referrer API returns the referrer URL you attached to the store link, plus both client- and server-side click and install-begin timestamps, delivered straight from Play on first launch. That's deterministic attribution with no device identifier involved. The referrer travels through the install natively, signed by Play, and the timestamps let you sanity-check the click-to-install window. Every MMP leans on this, and it's why Android deferred deep linking rarely produces the match-rate drama iOS does.
Two production gotchas hide in Google's own documentation. The referral data persists for 90 days and won't change unless the app is reinstalled — fine. But Google is explicit that you should "invoke the API only once during the first execution after install." Call it repeatedly and you're making pointless API calls. Worse, some teams wire the fetch into a code path that doesn't reliably run on that critical first launch, then wonder why deferred routing is empty. Fetch once, early, store the result, and move on.
Where links actually die: fallback behavior in production
This is the section that separates people who've shipped from people who've read the marketing page.
Fallback is not a checkbox. It's a configuration surface, and the default is almost always "send app-less users to the store." Adjust's documentation puts it plainly: a deep link fallback "overrides the default behavior of redirecting users to the app store when they don't have your app installed," letting you route them to a mobile website instead. And critically, "using a redirect does not affect deferred deep link behavior." So you can catch the app-absent user on the web without sacrificing the deferred route after they eventually install. That's the behavior you want, and it takes deliberate setup.
Now the silent failure. Per Adjust's deep-link FAQ, if the app isn't installed and the URL is incorrectly structured, "the browser may drop the adjust_t parameter" — the click identifier the platform needs to know where the click came from. Without it, Adjust returns a 404, "which usually means the deep link failed to open the app, so the user was redirected to the store as a fallback." Read that again. A misencoded URL doesn't throw a loud error. It quietly loses the one parameter that makes attribution work, and the user gets dumped to a generic store page with no destination and no source. You won't see it in a dashboard as an error. You'll see it as a mysterious dip in deferred conversions that nobody can explain.
That's the whole argument for testing fallback per-vendor rather than trusting the grid. The happy path works everywhere. The unhappy path is where the money leaks.
The 6-state test matrix (run this before you sign a contract)
Here's the rubric I actually use. Every deep link lives in a small set of states, and the only honest way to compare vendors is to fire the same link through all of them and record what happens. Six states cover the ground that breaks.
The axes: cold start versus warm start, app-present versus app-absent, and originating browser — Safari versus an in-app webview like Instagram or TikTok. You don't need all combinations. You need the ones that expose the failure modes above.
| # | State | What you're testing | Expected | What testing often shows |
|---|---|---|---|---|
| 1 | App present, Safari, warm | Baseline Universal Link | Opens app to exact screen | Usually clean |
| 2 | App present, in-app browser (TikTok/IG), warm | Webview honoring UL | Opens app | Webview renders fallback web page instead — app never opens |
| 3 | App absent, Safari, cold | Deferred match + fallback | Store or web fallback, then deferred route on launch | Works if fallback configured; clipboard prompt fires on iOS 16+ |
| 4 | App absent, in-app browser, cold | Deferred through webview | Deferred route after install | Clipboard write may not survive; match downgrades to probabilistic |
| 5 | App absent, Private Relay on, cold | The iOS 15+ break | Deterministic match | Probabilistic-only vendors miss; clipboard vendors hold |
| 6 | Malformed link, app absent | Silent param drop | Graceful fallback | Click param dropped, 404, user dumped to store (per Adjust's own FAQ) |
Run these six against any vendor's live SDK, not their demo. State 2 catches the in-app-browser gap the OS docs stay silent on. State 5 is the Private Relay litmus test — it's where clipboard-deterministic vendors earn their keep and probabilistic ones fall apart. State 6 is the malformed-URL landmine. Deliberately break your own link and confirm the fallback degrades gracefully instead of silently.
This grid is the spine of the whole comparison. Score vendors on what states 2 through 6 actually do on a real device, and the marketing checkmarks stop mattering.
Analytics granularity depends on user state
Dashboard depth is not a fixed vendor property. It changes based on who the user is at the moment of measurement, and this trips up nearly every comparison I've seen.
The cleanest example comes from AppsFlyer's Unified Deep Linking. Per AppsFlyer's developer docs, for new users the UDL method returns only the deferred-routing parameters — deep_link_value and deep_link_sub1 through deep_link_sub10. Try to read anything else on that first deferred launch — media_source, campaign, af_sub1-5 — and those parameters come back null. The routing data is there. The campaign attribution isn't, at least not through that method at that moment.
That's not a bug, it's the deferred contract. But it means if you evaluate a dashboard using a warm returning device that already has full attribution cached, you'll see a rich, populated view and conclude the granularity is excellent. Then you ship, watch a real first-touch new install come through, and half your fields are empty. Test your dashboard against a genuine fresh install, not the device that's been running your app for three weeks.
The capability matrix
Here's the pack scored honestly. Cells I can't source, I mark as unstated rather than guess.
| Platform | Link types | App-absent fallback | iOS deferred match | Android referrer | Self-host | Pricing model |
|---|---|---|---|---|---|---|
| Branch | UL / App Links / URI | Store default, override supported | Clipboard-deterministic (NativeLink, match_guaranteed=true) |
Yes | No | Usage/MAU tiers |
| Adjust | UL / App Links / URI | Configurable web override, deferred preserved | Unstated in pack | Yes | No | MMP contract |
| AppsFlyer OneLink | UL / App Links / URI | Store default, override supported | Unstated in pack | Yes | No | MMP contract |
| Dub | UL / App Links / URI | Configurable | Hybrid clipboard + IP | Yes | Open-source option | Per-plan |
| Kixo | UL / App Links / URI (via kixo.cc) | Unstated in pack | Unstated in pack | Deferred deep links supported; referrer specifics unstated | Unstated in pack | Per-project FREE / GROWTH / ENTERPRISE, MAU-bracketed |
The maturity caveats matter. Where the pack doesn't publish a match method for Adjust and OneLink, I'm not inferring one from their reputation. And Kixo's row is thin on purpose — I'll explain why below rather than pretending I know things I don't.
How to read the Kixo row honestly
Kixo is a B2B, AI-native product and marketing analytics platform, and mobile attribution with deferred deep links via kixo.cc short links is one capability inside a broader product — session replay, funnels, retention, cohorts, campaign tooling, and its actual differentiator, a chat-first interface where you ask questions in plain language and get AI-generated charts and dashboards with a visible reasoning trail.
For a deep-linking comparison, here's the honest boundary: the fact sheet confirms deferred deep links via kixo.cc, but it does not publish an iOS deferred-match method. So I genuinely can't tell you whether Kixo's match is clipboard-deterministic, probabilistic, or hybrid — and I'm not going to invent one. That's not a knock. It's a gap in what's published, and it's exactly what State 5 of the matrix exists to resolve. If you're evaluating Kixo for an iOS-heavy app worried about Private Relay, run it through the same six states you'd run Branch through, and watch what happens under Private Relay specifically. Same scrutiny, same rubric, no free pass.
What I'd actually pick, and when
There's no winner, only fits.
If you're building an iOS-heavy consumer app and a meaningful share of your users are on iCloud+, you need clipboard-deterministic matching. Private Relay will quietly erode probabilistic attribution, and a vendor like Branch that writes to the pasteboard before install is the answer — as long as you've made peace with the iOS 16 paste dialog and briefed your team on why users see it.
If you're Android-first, relax a little. The Install Referrer gives you deterministic attribution without a device ID out of the box, so you need far less vendor magic. Wire the fetch to run exactly once on first launch, respect the 90-day persistence, and most of your deferred routing just works.
If you want attribution living inside your product analytics instead of a separate MMP silo, the all-in-one platforms are worth a look — Kixo among them, with the match-method caveat I flagged still standing. Consolidation has real value when your growth and product teams are asking the same questions of the same data.
Whichever you pick, the postback confirming the install still arrives when it feels like it. Build your pipeline to reconcile late-arriving events against your source of truth rather than trusting the real-time number on the dashboard, and you'll sleep better than the version of me who once refreshed a console for twenty minutes waiting for a postback that showed up during my sandwich.
Quick FAQ
Does deferred deep linking still work on iOS 15+?
Yes, but not the old way. IP-based probabilistic matching broke when iCloud Private Relay started masking Safari IPs. Clipboard-deterministic methods like Branch's NativeLink work around it by carrying the destination through the install on the pasteboard, which Branch reports delivers match_guaranteed=true.
Will my users see a paste prompt? On clipboard-based deferred matching, likely yes. Per OWASP's mobile security guidance, iOS 16 and later show an explicit paste confirmation dialog when an app reads pasteboard content written by another app. It's the visible cost of deterministic matching.
Why did my deep link dump the user to the store?
Usually a malformed URL. Per Adjust's FAQ, an incorrectly structured link can cause the browser to drop the click parameter (adjust_t in Adjust's case), which produces a 404 and sends the app-less user to the store as a silent fallback. Test with a deliberately broken link and confirm graceful degradation.
Can I override the store fallback to a web page? Yes, on platforms that expose it. Adjust's docs confirm a configurable fallback redirects app-less users to a mobile website instead of the store, and doing so "does not affect deferred deep link behavior" — so the deferred route still fires after they install.