React Native Deep Linking SDK: The 2026 Guide

React Native Deep Linking SDK: The 2026 Guide

Key takeaways

  • React Native deep linking has three layers: iOS Universal Links, Android App Links, and a JavaScript routing layer on top, which is what makes it more involved than native setup.
  • A deep linking SDK handles the parts React Native's built-in Linking API does not: hosting the AASA and assetlinks.json files, deferred deep linking across the install gap, and attribution.
  • Deferred deep linking is the hard part. React Native's Linking can route a link when the app is installed, but it cannot carry context through a fresh install. That requires an SDK.
  • This guide covers a working setup: native configuration for both platforms, SDK initialization, link handling, and a deferred-linking flow.
  • Start free for link creation on the free tier; deferred deep linking and install attribution are on paid plans from $9/month.

Short answer: To implement deep linking in React Native, configure iOS Universal Links and Android App Links natively, then use a deep linking SDK to host the verification files, handle deferred deep linking through fresh installs, and pass link parameters into your React Navigation routing. React Native's built-in Linking API alone cannot do deferred linking.


Why React Native deep linking needs more than Linking

React Native ships a Linking API that can open the app from a URL and read the initial URL. That covers the simplest case: the app is already installed and you just need to route. It does not cover the cases that actually drive growth:

  • Deferred deep linking. A new user taps a link, does not have the app, installs it, and should land on the linked content with referral context intact. Linking has no memory across the install.
  • Verification file hosting. iOS needs a correctly served apple-app-site-association (AASA) file; Android needs assetlinks.json. Serving and maintaining these is error-prone by hand.
  • Attribution. Tying a click to an install to an in-app event needs infrastructure beyond the OS APIs.

A deep linking SDK fills these gaps.

Step 1: Configure iOS Universal Links

In Xcode, enable the Associated Domains capability and add your branded domain:

applinks:go.yourbrand.com

Your platform hosts the AASA file at https://go.yourbrand.com/.well-known/apple-app-site-association. With Ulinkly, this is generated and hosted automatically once you enter your Bundle ID and Apple Team ID in the project configuration.

Step 2: Configure Android App Links

In AndroidManifest.xml, add an intent filter with android:autoVerify="true":

<intent-filter android:autoVerify="true">
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="https" android:host="go.yourbrand.com" />
</intent-filter>

The matching assetlinks.json is hosted at https://go.yourbrand.com/.well-known/assetlinks.json, again generated for you after you provide the Package Name and SHA-256 fingerprint.

Step 3: Install and initialize the SDK

npx expo install @ulinkly/react-native

@ulinkly/react-native is an Expo native module that bridges the native iOS and Android Ulinkly SDKs, so it works in both Expo and bare React Native projects.

import ULink from '@ulinkly/react-native';

// Always await initialize() before calling any other method.
await ULink.initialize({ apiKey: 'ulk_your_api_key_here', debug: __DEV__ });

Step 4: Handle resolved links

import { useEffect } from 'react';
import ULink from '@ulinkly/react-native';
import { useNavigation } from '@react-navigation/native';

function useDeepLinks() {
  const navigation = useNavigation();

  useEffect(() => {
    // onDynamicLink fires for cold-start, foreground, and deferred-install links.
    const sub = ULink.onDynamicLink((data) => {
      // data.parameters carries your routing payload; data.isDeferred flags a deferred match.
      const screen = data.parameters?.screen;
      if (screen) {
        navigation.navigate(routeFor(screen), data.parameters);
      }
    });
    return () => sub.remove();
  }, [navigation]);
}

Step 5: Handle the deferred case on first launch

On a fresh install, trigger a deferred-link check once after initialization. checkDeferredLink() returns Promise<void> — it does not return the link directly. Instead, the matched click is delivered through the same onDynamicLink listener from Step 4 (with data.isDeferred === true), so your existing navigation logic handles it:

// After initialize(); skip this if you set autoCheckDeferredLink: true in the config.
await ULink.checkDeferredLink();
// The matched deferred link arrives via the onDynamicLink listener registered above.

Testing the four scenarios that break in production

  1. App installed, link tapped from native browser.
  2. App not installed (deferred), then installed and opened.
  3. Link opened inside a social in-app browser (Instagram, TikTok).
  4. Desktop fallback.

Test all four on real devices. The simulator does not reproduce install-gap behavior reliably.

FAQ

Can React Native do deep linking without an SDK?

Partially. The built-in Linking API handles routing when the app is already installed, but it cannot do deferred deep linking through a fresh install or host the required verification files. Those need an SDK.

What is the difference between a deep link and a deferred deep link in React Native?

A deep link routes an existing user to in-app content. A deferred deep link preserves that destination and its parameters through an install, so a brand-new user lands on the right screen the first time they open the app.

Does this work with Expo?

Yes. @ulinkly/react-native is built with the Expo Modules API, so it works in both Expo (with a development build / config plugin) and bare React Native projects. It does not run in Expo Go, because it bridges native iOS and Android code.

How do I handle Universal Links inside Instagram or TikTok?

Those apps use in-app browsers that often block Universal Links. A deep linking platform detects these environments and routes around them rather than failing silently.

Do I need separate setup for iOS and Android?

Yes for the native verification (Associated Domains on iOS, App Links intent filter on Android), but the SDK and your JavaScript link-handling code are shared across both.

Ship it

Create a free Ulinkly account, add your iOS and Android apps, and wire up the listener above. Deferred deep linking and install attribution are available on paid plans from $9/month.

Read More Articles

Explore more guides and insights on deep linking and mobile development.

Back to Blog