Skip to content
CodeOnAir
← All posts

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.

CodeOnAir team20 October 20262 min read

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)

  1. In Xcode, open Signing & Capabilities → Associated Domains and add applinks:link.myshop.com.
  2. Host an apple-app-site-association file on that domain listing your Team ID and bundle ID.
  3. 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)

  1. Add an intent filter with android:autoVerify="true" for your domain in AndroidManifest.xml.
  2. Host /.well-known/assetlinks.json with your package name and the SHA-256 fingerprint of your signing key (Play App Signing has its own key — use that one).
  3. 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.

Your first AppLink in five minutes.

Create an app, pick a subdomain, and share a link that opens your app. Try Pro free for 30 days — no card needed.