Deeplinkly

Glossary/Implementation artifacts

Link Fallback Chain

Definition

A link fallback chain is the ordered set of destinations a single link resolves to — the app, the app store, or a web page — depending on the user's platform and whether the app is installed.

One URL goes into an ad, an email and a QR code, and it has to do something sensible for a user on iOS with the app, a user on Android without it, and a user on a desktop browser. The chain is the routing logic that decides that. Get it right and every audience lands somewhere useful; get it wrong and a large share of your traffic hits an App Store page for the wrong platform, or a blank screen.

The decision table

Every branch of the chain is a combination of platform, install state and context. There are fewer of them than it feels like.

Where one link should land, by platform and install state.
PlatformApp installedDestinationMechanism
iOSYesThe app, on the right screenUniversal Link
iOSNoApp Store, then the right screen after installWeb page → App Store → deferred deep link
AndroidYesThe app, on the right screenApp Link
AndroidNoPlay Store, then the right screen after installWeb → Play with a referrer → Play Install Referrer
Desktopn/aThe web page, or a QR code to continue on mobilePlain HTTP
In-app browserYesThe app, if the webview can be escapedintent:// on Android; interstitial on iOS
Unsupported / botn/aThe web pagePlain HTTP

The store is not the last hop

Sending an uninstalled user to the store and stopping there loses the content they clicked. The chain only pays off if the app, on first launch, recovers what the link pointed at — the Play Install Referrer on Android, a matched deferred link on iOS. Without that step, a fallback chain is a redirect to a home screen.

Where the decision has to be made

It has to happen on the server, in the redirect. Client-side detection is the approach every guide from 2015 describes, and it does not survive current browsers.

Client-side detection versus a server-side chain.
Client-side timerServer-side redirect
How it worksOpen the scheme, setTimeout to the storeInspect the request, respond with a 302
Blocked by modern browsersYes — scheme navigation needs a gestureNo
Survives an in-app browserRarelyUsually
Shows an error dialog when the app is missingOftenNever
Can attribute the clickOnly after the page loadsAt the redirect, before anything renders
Works with a Universal LinkConflicts with itComplements it
What a correct chain looks like on the wire
# iOS: the link is a plain HTTPS URL. If the app is installed the
# OS intercepts before any request is made; otherwise a 302 to the store.
curl -sSIL -A "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)" \
  https://links.example.com/p/abc123

# Android: same URL, different Location
curl -sSIL -A "Mozilla/5.0 (Linux; Android 14)" \
  https://links.example.com/p/abc123

# Desktop: the web page, 200, no store redirect
curl -sSIL -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" \
  https://links.example.com/p/abc123

Run those three and read the Location headers. Any user agent that lands on the wrong platform's store, or on a store when it should have loaded the page, is a branch of the chain that is wrong for real traffic too.

The Android escape hatch

Android has a URL form that expresses the whole chain in one string: try this app, and if it is not there, load this web page. It is the only reliable way out of an in-app browser.

intent:// with a built-in fallback
<a href="intent://products/42#Intent;
    scheme=https;
    package=com.example.shop;
    S.browser_fallback_url=https%3A%2F%2Fexample.com%2Fproducts%2F42;
  end">
  Open in the app
</a>

<!-- Newlines shown for readability; write it on one line.
     S.browser_fallback_url must be percent-encoded. -->

iOS has no equivalent

There is no iOS URL form that says "app if present, web if not" — that is what a Universal Link is, and it is why iOS chains rely on the association working rather than on the URL. Where an iOS webview blocks Universal Links, the only remaining option is an interstitial page asking the user to open in Safari.

Preserving context across the store

The hard part of the chain is the segment that crosses an install, because nothing about the original URL is carried by the store automatically. Each platform gives you exactly one channel.

What survives the trip through each store.
PlatformChannelSurvivesLimits
Androidreferrer parameter on the Play URL, read via the Install Referrer APIDeterministic, exactPlay installs only; read within the API's retention window
iOSA match performed by your attribution provider on first launchProbabilistic in the general caseTime-limited; no device identifier is involved
iOS App ClipThe invocation URL, carried into the full app via a shared containerDeterministicOnly when the user came through an App Clip
BothA code the user types or a QR the user rescansDeterministicRequires the user to do something
The Android half, spelled out
# The store URL a fallback chain should redirect an uninstalled
# Android user to. Everything after referrer= is yours to define.
https://play.google.com/store/apps/details\
?id=com.example.shop\
&referrer=utm_source%3Demail%26utm_campaign%3Dspring%26deep_link_value%3D%2Fproducts%2F42

# Confirm the app reads it back on first launch
adb shell setprop debug.deeplink.referrer "deep_link_value=/products/42"

The referrer value has a length limit and is a single opaque string, so keep it to a compact encoding of the route plus campaign fields rather than a full URL. When it comes back empty, the causes are in deferred-deep-link-not-working.

UTM builder

Build the tagged campaign URL that sits at the front of the chain, with consistent utm_source, utm_medium and utm_campaign values. Consistent tagging is what makes the store-referrer segment readable later, since that string is the only context that survives an install on Android.

Open the utm builder

Frequently asked questions

What is a link fallback chain?
It is the ordered routing logic behind a single link: open the app if it is installed, send the user to the correct app store if it is not, and load a web page for anyone on a platform with no app. A complete chain also recovers the original destination after an install, so a user who had to install first still lands on the content they clicked.
Should fallback logic run on the client or the server?
On the server, as a redirect. Current browsers block navigation to a custom scheme without a direct user gesture, and the old technique of opening a scheme and racing a setTimeout to the store fails or shows an error dialog on most devices. A server-side redirect inspects the request and returns the right destination before anything renders.
How do I send an Android user to the Play Store with the link intact?
Redirect to the Play Store URL with a referrer query parameter containing your campaign and destination fields, percent-encoded. Google Play passes that string to the app, which reads it on first launch through the Install Referrer API. It is deterministic and exact, which makes it the most reliable segment of any fallback chain on either platform.
What is S.browser_fallback_url?
It is a parameter inside an Android intent:// URL that names a web page to load when the target app is not installed. It lets a single link express the whole fallback decision in one string, and it is the most reliable way to open an app from inside an in-app browser such as Instagram or TikTok, where standard App Links are frequently intercepted.
Why do users end up on the wrong app store?
Because platform detection is running on a user agent the chain does not recognise, or not running at all. In-app browsers, tablets and desktop browsers all report user agents that naive matching misclassifies. Test the chain with curl against several user agent strings and read the Location header for each, rather than testing only on your own phone.

Related terms

  • Universal LinkA Universal Link is a standard HTTPS URL that opens an iOS app directly when that app is installed and the domain has authorised it, and loads the equivalent web page when it is not.
  • Android App LinkAn Android App Link is an HTTPS URL that opens an Android app directly, without a chooser dialog, because the system has verified through a file on the domain that the app is authorised to handle it.
  • Custom URI SchemeA custom URI scheme is a non-standard URL protocol, such as myapp://, that an app registers with the operating system so that URLs beginning with it open that app.
  • Deferred deep link not workingA deferred deep link fails when the signal meant to carry the pre-install destination across the app store — an install referrer, a stored token, or a server-side match — is absent, expired, or never read on first launch.
  • Deep links in in-app browsersAn in-app browser is an embedded webview inside another app that renders links without handing them to the operating system, which prevents Universal Links and App Links from ever reaching the app that claims the domain.