Deferred deep linking in React Native and Expo, without Firebase
React Native's Linking API only sees links when the app is already installed. Here is how a link survives an install on Android and iOS, what you would have to build yourself, and how to set it up in a bare React Native or Expo app.
· DL2App · 6 min read
Someone taps an invite link, doesn't have your app, installs it from the store and opens it. With an ordinary deep link they land on your home screen and the invite is gone. Deferred deep linking is what carries the link through the install, so the first launch opens the invite.
Firebase Dynamic Links used to do this for a lot of React Native apps, and it shut down in August 2025. React Native itself has never done it. This post explains why, how it works underneath, and what it takes to add it.
Why Linking can't do it
React Native's Linking.getInitialURL() returns the URL that launched the app. After an install there is no such URL: the person opened the app from the home screen, not from a link. The link they tapped was handled by a web page before the app existed on the phone, so something has to remember it and hand it over later.
That something has two halves:
- A server that sees the tap before the store opens, and keeps a short-lived record of it.
- Code in the app that asks, on first launch, "did this install come from a tap?" and gets the link back.
How the second half finds the right tap is different on each platform.
Android: the Play Install Referrer
Google Play can carry a string through an install. If the store link includes a referrer parameter, the installed app can read it on first launch with the Play Install Referrer API.
So on Android the flow is exact:
- The link server records the tap and gives it an ID.
- It sends the person to
https://play.google.com/store/apps/details?id=com.yourapp&referrer=tap_id%3Dabc123. - On first launch the app reads
tap_id=abc123from the referrer and asks the server for that tap's link.
This only works for installs from Google Play. Sideloaded builds and other stores don't pass the referrer.
iOS: no referrer, so you match
The App Store passes nothing through an install. There is no Apple API that tells an app which link led to it. The options are:
- Clipboard hand-off. The page before the store copies a token, and the app reads it on first launch. Since iOS 16 reading the clipboard shows a system prompt, so the reliable way is a paste button the person taps. It's exact, but it adds a step.
- Matching the first launch to a recent tap. The server compares the app's first request with recent taps: the network address, operating-system version, screen size, language and time zone, and how long ago the tap was. It's invisible to the person, but it's a probability, not a certainty.
Matching has limits you should plan for. It works best on the same network. It degrades when the address changes between the tap and the first launch (VPNs, iCloud Private Relay, switching from Wi-Fi to mobile data), and it gets ambiguous on shared networks, where several people tap the same campaign from one office or campus. Anyone who quotes you a fixed iOS match rate is guessing about your audience.
A good matcher prefers no match to a wrong one. Opening someone else's invite is worse than opening the home screen.
Building it yourself
If you want to own the whole thing, you need:
- A web endpoint for your links that records each tap (ID, time, platform, the signals above) and redirects to the right store.
- The
apple-app-site-associationandassetlinks.jsonfiles on that domain, so the same links open the app directly when it is installed. - On Android, a native module or package that reads the Play Install Referrer on first launch.
- On iOS, either a paste button and clipboard read, or a matching endpoint and the scoring rules behind it.
- A "first launch" flag in the app, so you ask once and deliver the link once.
- A way to handle people who restart the app during onboarding, before they reach the screen the link is for.
It's a few weeks of work to do well, mostly on iOS matching and edge cases, and the server has to stay up for as long as your links are out there.
Using a link service
The other route is a service that runs the server half and ships an SDK for the app half. With DL2App the React Native SDK is a plain native module: it works in a bare React Native app (0.74 or newer) and in Expo (SDK 51 or newer, with a development build, not Expo Go).
Expo:
npx expo install @dl2app/react-native
Add the config plugin to app.json. It writes the associated domains on iOS and the verified intent filters on Android for you:
{
"expo": {
"plugins": [
["@dl2app/react-native", { "subdomain": "myapp", "domains": ["go.myapp.com"] }]
]
}
}
Then rebuild the native app (npx expo prebuild --clean, or a new EAS build).
React Native without Expo:
npm install @dl2app/react-native
cd ios && pod install
Autolinking registers the module. Add your link hosts to Associated Domains in Xcode and to an autoVerify intent filter in AndroidManifest.xml, and pass incoming links to React Native in your AppDelegate, because the React Native template doesn't do that for you. The React Native setup guide has the exact code.
In both, one listener handles every link:
import DL2 from "@dl2app/react-native";
// Once, as early as possible, outside any component.
DL2.configure({
publishableKey: "pk_live_xxx",
linkDomains: ["myapp.dl2.app", "myapp-alt.dl2.app", "go.myapp.com"],
});
// Direct links (app installed) and the deferred link after an install.
const unsubscribe = DL2.onLink((event) => {
navigation.navigate(event.path, event.data);
});
A deferred link arrives in the same listener with source: "deferred", exactly once per install. On Android it is matched through the Play Install Referrer. On iOS it is matched to a recent tap, and you can opt in to the clipboard hand-off if you'd rather have an exact match with a paste button. If you use Expo Router, also add app/+native-intent.ts so the router doesn't try to route the short link itself.
Test it the way people will use it
- Delete the app first. A deferred link is only delivered on the first launch of an install.
- Android: the Install Referrer only comes from Google Play, so tap the link and install from the Play Store (an internal or closed testing track works). A build installed from Android Studio has no referrer.
- iOS: tap the link in Safari or Messages, install (TestFlight works), and open the app on the same network you tapped from.
- Try the shapes that fail: a link from inside Instagram, a tap on Wi-Fi with the install on mobile data, a restart halfway through onboarding.
- If the link carries something the person must not lose, such as an invite or referral code, also give them a way to type it in. Treat the deferred link as a shortcut, not the only path.
If a link doesn't open an installed app at all, that's a different problem: start with Universal Links not opening your app or Android App Links not opening your app. Our free link checker shows what each platform is sent for any link.
Questions people ask
Does React Native support deferred deep linking?
Not on its own. Linking only sees links that open an already installed app. Carrying a link through an install needs a server that records the tap and code that asks for it on first launch, which is what a deep link service or SDK adds.
Does deferred deep linking work in Expo Go? No. It needs native code and your app's own associated domains, so use a development build or an EAS build.
Is deferred deep linking exact on iOS? Only with a clipboard hand-off, where the person taps a paste button. Without it, the first launch is matched to a recent tap, which works best on the same network and can miss across VPNs or network changes.
What replaced Firebase Dynamic Links for React Native? Google didn't ship a direct replacement. Apps moved to a link service with a React Native SDK, or built the server and first-launch check themselves. Our Firebase Dynamic Links comparison covers what changed and how to move existing links.
Start with one link
The free plan has no time limit and needs no card. Create a project, add your app, and send yourself the link.