A link can open a specific React Native screen in two different situations, and each needs different tools. If the app is already installed, the operating system can route a verified HTTPS URL into it, and React Navigation can map that path to a screen. If the person taps the link before installing, a second requirement appears: the original destination has to survive the install and be restored on first launch. Platform link routing does not establish that by itself, so the handoff has to be designed as its own layer. Firebase Dynamic Links, which older guides often relied on for that handoff, shut down on August 25, 2025.
Three behaviors that are easy to conflate
n
- n
- Installed app, link tapped: the operating system delivers a verified HTTPS URL to the app, and React Navigation maps the path to a screen.
- App not installed, link tapped: Apple’s documentation says that “If the person hasn’t installed your app, the system opens the URL in their default web browser, allowing your website to handle it.” What happens next is the website’s job.
- Link tapped before install, app opened for the first time: none of the routing steps above carries the original path across the install. Restoring it requires a handoff that you design or buy.
n
n
n
n
How the flow is layered
n
- n
- Domain and app association. Your website publishes a file that names the app, and the app declares the domains it accepts. The operating system uses both to decide which links open the app.
- URL delivery. The operating system hands the URL to the React Native process either as the launch URL (cold start) or as a runtime event (app already open).
- Navigation mapping. React Navigation matches the path against a route table and converts it into navigation state.
- Deferred install handoff. Needed only when a destination must survive installation. You build or buy this layer.
n
n
n
n
n
Layers one through three are provided by the platforms and libraries. Layer four is an application decision, and the rest of this guide treats it that way.
As an Amazon Associate I earn from qualifying purchases.
n
Step 1: Associate your domain with both apps
n
iOS: Associated Domains and the association file
n
- n
- In Xcode, open the app target, go to Signing & Capabilities, choose + Capability, and add Associated Domains.
- Add an entry such as
applinks:app.example.com, using the exact host you will serve. - Publish a JSON file at
/.well-known/apple-app-site-associationon that host. It must be served over HTTPS without redirects.
n
n
n
n
{n "applinks": {n "details": [n {n "appIDs": ["ABCDE12345.com.example.app"],n "components": [n { "/": "/products/*" },n { "/": "/orders/*" }n ]n }n ]n }n}
n
After you install a build with that entitlement, tap a link from Notes or Messages. The app should open at the mapped path. Apple documents that a link tapped inside Safari on the same domain can stay in the browser, so do not rely on in-page taps alone. Give your web pages an explicit “Open in app” button that uses the same link, and consider a Smart App Banner, configured with the apple-itunes-app meta tag, on pages where the app should be offered in the browser.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
n
Android: intent filters and Digital Asset Links
n
Android Developers describes the feature in its “About App Links” documentation: “Android App Links is a special deep linking capability in Android 6 and later that allows your verified website URLs to immediately open corresponding content in your Android app, without requiring the user to select your app from a disambiguation dialog.” Verification has two parts. First, declare an intent filter with autoVerify in android/app/src/main/AndroidManifest.xml. Keep your existing LAUNCHER filter in the same activity.
n
<activityn android:name='.MainActivity'n android:launchMode='singleTask'n android:exported='true'>n <intent-filter android:autoVerify='true'>n <action android:name='android.intent.action.VIEW' />n <category android:name='android.intent.category.DEFAULT' />n <category android:name='android.intent.category.BROWSABLE' />n <data android:scheme='https' android:host='app.example.com' />n </intent-filter>n</activity>
n
React Native’s documentation recommends singleTask for MainActivity when an incoming intent must reach an activity that is already running. Second, publish /.well-known/assetlinks.json on the same host, naming your package and the SHA-256 fingerprint of your release signing certificate:
#1 Best Overall
n
[n {n "relation": ["delegate_permission/common.handle_all_urls"],n "target": {n "namespace": "android_app",n "package_name": "com.example.app",n "sha256_cert_fingerprints": ["<SHA-256 fingerprint of your release signing certificate>"]n }n }n]
n
To check verification on Android 12 or later, run adb shell pm get-app-links com.example.app. The output lists each host with a verification state, and app.example.com should read as verified. Association checks depend on the signing key and the team identifier, so run them with a build signed the way you will ship it.
n
Android’s developer documentation also describes Dynamic App Links, which from Android 15 add on-device behavior refinement on devices with Google services. That concerns how verified links are handled on a device that already has the app. It does not carry a click through an install.
n
Step 2: Receive the URL in React Native
n
React Native’s documentation uses “deep link” for Android and “Universal Link” for iOS, and both mean an HTTPS URL that opens your app. Use standard HTTPS URLs for any link meant to work outside the app. A custom scheme such as myapp:// can open the app, but it does not provide the web fallback: if the app is missing, there is no web page to load.
Rank #2
n
The React Native Linking API exposes both entry points directly:
n
import { useEffect } from 'react';nimport { Linking } from 'react-native';nnexport function useIncomingUrl(onUrl) {n useEffect(() => {n let active = true;n Linking.getInitialURL().then((url) => {n if (active && url) onUrl(url);n });n const subscription = Linking.addEventListener('url', ({ url }) => onUrl(url));n return () => {n active = false;n subscription.remove();n };n }, [onUrl]);n}
n
Memoize the handler with useCallback, or the listener is re-created on every render. If you pass a linking prop to React Navigation (Step 3), it reads the initial URL and listens for events for you. Use a hook like this one only for logic that must run beside navigation, such as redeeming a handoff token.
n
Step 3: Map validated paths to screens
n
React Navigation’s linking configuration works as the route table. Its prefixes must match the host exactly, and only paths listed under screens map to a screen.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsRank #3
n
import { NavigationContainer } from '@react-navigation/native';nnconst linking = {n prefixes: ['https://app.example.com'],n config: {n screens: {n Home: '',n Product: 'products/:id',n Order: 'orders/:orderId',n NotFound: '*',n },n },n};nnexport default function App() {n return <NavigationContainer linking={linking}>{/* navigators */}</NavigationContainer>;n}
n
A path that is not listed falls through to NotFound. A path match proves only the shape of the URL, so constrain values inside the screen as well:
n
const ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;nnexport function isValidId(value) {n return typeof value === 'string' && ID_PATTERN.test(value);n}
n
If a value fails the check, show NotFound or Home instead of calling an API with it.
n
Deferred recovery is a separate layer
n
Ask one question first: if someone taps the link before installing and opens the app for the first time, must they land on the original destination? If not, the platform routing in Steps 1 through 3 is enough. If so, choose one of the approaches below. The platform mechanisms do not establish this behavior on their own, so do not assume it.
Rank #4
n
| Approach | Installed-app routing | Click before install restored on first launch | What you own |
|---|---|---|---|
| Platform links only | Yes, through Universal Links and App Links into React Navigation | Not established by the platform link mechanisms; do not assume it | Association files and the route table |
| Your own handoff | Yes | Yes, if you build the token store and redemption. Android can pass a store referrer; iOS needs a different signal (see below) | Token store, redemption endpoint, expiry rules, web fallback page |
| Managed deep-linking service | Vendor-dependent; verify with the vendor | Vendor-specific; current official platform documentation does not establish it, so verify per platform | Vendor contract, SDK upgrades, domain setup, data terms |
n
Option 1: Accept the default first screen
n
Skip the handoff when any landing screen is acceptable, such as a general promotion. Ship a web page at the link that explains the app and offers a store button. The first launch then opens your normal home screen. This is the simplest option and the one with nothing to lose if the handoff fails.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →n
Option 2: Build your own handoff
n
- n
- On the web page behind the link, validate the requested path against the same route table the app uses. If the app is not present, create a server-side record containing the destination and a random, single-use token. Keep personal data out of the token.
- Send the user to the store with the token attached as the store referrer. On Android, the Google Play Install Referrer API returns that referrer string to the app after installation.
- On first launch, read the token. On Android, read it from the install referrer. On iOS, use the method you choose (see below).
- Redeem the token with your backend. The backend returns the destination only if the token is unexpired and unredeemed, and then marks it redeemed.
- Navigate through the same validated route table, then apply your normal sign-in and permission checks.
n
n
n
n
n
n
iOS has no install referrer equivalent to the Play Store mechanism. The iOS handoff therefore depends on a visible method: a short code the user enters, or a clipboard value the app reads with the user’s awareness, since recent iOS versions notify users when an app reads the clipboard. Probabilistic matching is the other route, but it relies on signals that Apple’s App Tracking Transparency rules limit. Each choice trades friction, reliability, and privacy review against the others.
n
Option 3: Use a managed deep-linking service
n
Managed services exist for this job, and they can cover attribution and platform differences that you would otherwise build yourself. Current official platform documentation does not establish which providers handle deferred install recovery on each platform, or their SDK behavior, pricing, or partner terms. An older React Navigation reference names Branch as an example external incoming-link service. That reference does not show current feature parity. Evaluate any vendor against this checklist:
n
- n
- A documented deferred-recovery mechanism for iOS and a separate one for Android.
- React Native SDK version support, Expo compatibility, and whether the SDK requires native code or a config plugin.
- Use of your own domain, and a migration path for links you already publish.
- Control over store and browser fallback behavior.
- The scope of analytics and attribution, and where data is processed and how long it is retained.
- Reliability commitments, price tiers, and any link or event limits.
- Current support and partner terms, read at the time you buy.
n
n
n
n
n
n
n
n
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Migrating away from Firebase Dynamic Links
n
Firebase’s Dynamic Links deprecation FAQ, checked on 7 October 2026, states: “On August 25th, 2025, Firebase Dynamic Links will shut down.” It also says that served links, including custom domains and page.link links, stop working and cannot be newly created. Links from earlier campaigns therefore no longer resolve. Firebase also says the page.link domains are not available after shutdown, so do not plan around moving them.
n
- n
- Inventory every Firebase link: emails, ads, QR codes, social posts, printed material, documentation, and any app or web code that builds or parses them.
- For each one, choose the destination path on a domain you control, and publish the iOS and Android association files for that domain.
- Add a web page at each replacement URL that works without the app. It should show a store button and describe the destination in plain language. This page is the web fallback.
- Test each replacement link through the scenarios in the testing section below.
- Remove the Firebase Dynamic Links SDK calls and dependency from the app once the replacements pass.
n
n
n
n
n
n
Treat inbound URLs as untrusted input
n
- n
- Allowlist routes. The route table decides which paths exist. Everything else goes to
NotFound. - Validate every parameter for type, length, and format before it reaches a request, a query, or a screen.
- Keep destructive actions out of links. Deletions, purchases, and changes to an email address or password should open a confirmation screen inside the app, not run from the URL.
- Authenticate and authorize after navigation. A deep link is a request to navigate, not proof that the user may see the target content.
- Keep secrets out of URLs. Session tokens, reset codes, and personal data in a URL can end up in logs, browser history, and referrer headers.
- Test in more than one browser. Safari, Chrome, and in-app browsers handle links differently, and the browser can keep a same-domain link on the web (Step 1).
n
n
n
n
n
n
n
Apple’s guidance on universal links specifically warns developers to validate malformed URLs and to avoid exposing sensitive information or triggering risky actions from a link.
Recommended Free Tools
n
Test each path separately
n
Run each scenario on a real device, with a build signed the way you will ship it. The expected results below follow the platform documentation cited in this guide; they describe what the platforms are documented to do, not outcomes from a test run.
Quick Recap
n
| Scenario | Steps | Expected behavior | Failure to look for |
|---|---|---|---|
| Installed, app terminated (cold start) | Force-quit the app, then tap an HTTPS link in Notes or Messages | The app launches and shows the mapped screen | Default screen shown; initial URL not read, or prefix mismatch |
| Installed, app already open (warm) | Leave the app in the background, then tap a link | The running app receives the URL and navigates; on Android, singleTask prevents a second copy of MainActivity |
A second app instance, or duplicated screens on the stack |
| Installed, same-domain link in Safari | Tap a link on your own website in Safari | The link can remain in Safari, as Apple documents for same-domain links | Users stuck on the web page; check the “Open in app” button |
| App absent | Uninstall the app, then tap a link | The website opens in the default browser (Apple documents this for iOS) | Missing page, or no store button on the fallback page |
| Malformed or unknown path | Try a path such as /products/abc!, an unknown path, and an encoded control character |
No crash; NotFound or Home appears and no action runs |
Crash, blank screen, or an action triggered by the path |
| Post-install route (only if deferred handoff is in scope) | Tap the link without the app, install from the store, then open the app for the first time | The destination is restored only if the handoff is implemented and the token is valid | Default screen shown; expired or missing token |
n
First checks when links misbehave
n
- n
- Link opens the browser instead of the app. On iOS, confirm the association file loads directly over HTTPS without redirects and that the entitlement names the same host. On Android, confirm
pm get-app-linksreports the host as verified. - App opens to the wrong screen. Compare the prefixes exactly with the URL host, and check the path pattern against the URL.
- Works when the app is open but not after a cold start. Confirm the initial URL is read on mount, not only in the event listener.
n
n
n
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




