Deep linking in React Native: Universal Links, App Links and deferred deep links
A practical guide to deep linking in React Native — what Universal Links and App Links need, why the first open after install is the hard part, and how to handle every link in one place.
Deep linking means a URL opens a specific screen in your app instead of the home screen. In React Native you'll deal with three kinds of link, and each needs something different.
The three kinds of link
| Kind | Example | What it needs |
|---|---|---|
| URI scheme | myapp://product/42 |
A scheme registered in the app. Easy, but browsers show warnings and it does nothing if the app isn't installed. |
| Universal Link / App Link | https://link.myshop.com/product/42 |
A verified domain: apple-app-site-association (iOS) and assetlinks.json (Android) hosted on it. |
| Deferred deep link | Same HTTPS link, tapped before install | A service that remembers the link through the store install and hands it to the app on first open. |
Universal Links (iOS)
- In Xcode, open Signing & Capabilities → Associated Domains and add
applinks:link.myshop.com. - Host an
apple-app-site-associationfile on that domain listing your Team ID and bundle ID. - Apple fetches the file through its CDN, so changes can take a while to show up — test on a real device, from Notes or Messages, not by typing the URL into Safari.
App Links (Android)
- Add an intent filter with
android:autoVerify="true"for your domain inAndroidManifest.xml. - Host
/.well-known/assetlinks.jsonwith your package name and the SHA-256 fingerprint of your signing key (Play App Signing has its own key — use that one). - Check verification with
adb shell pm get-app-links your.package.name.
Handling the link in React Native
React Native's Linking API gives you the URL that opened the app, and an event for links that arrive while it's running:
import { Linking } from "react-native";
Linking.getInitialURL().then((url) => url && open(url));
const sub = Linking.addEventListener("url", ({ url }) => open(url));
That covers installed apps. It does not cover the most valuable case: someone taps your referral or product link, doesn't have the app, installs it, and opens it. getInitialURL() returns null on that first open — the link is gone.
Deferred deep links: the first open
To keep the link through the install, a service records the click, sends the user to the store, and on first open matches the install back to that click. With CodeOnAir the same callback handles all three cases:
import DeepLink from "@codeonair/deeplink-react-native";
DeepLink.init(); // reads the App ID from AndroidManifest.xml / Info.plist
useEffect(
() =>
DeepLink.onLink((link) => {
// link.path, link.params, link.isDeferred
navigation.navigate(link.path, link.params);
}),
[],
);
link.isDeferred tells you it came through an install — useful for things like crediting a referral or skipping onboarding.
Testing checklist
- Tap the link with the app installed → the right screen opens.
- Uninstall, tap the link, install, open → the right screen opens on the first launch.
- Tap it on a desktop → the web fallback opens.
- Share it on WhatsApp → the preview shows the right title and image.
CodeOnAir hosts the apple-app-site-association and assetlinks.json files for you and shows the exact Xcode and manifest lines in the dashboard. Request access to try it with 30 days of Pro free.