Blog Link Management How to Add Deep Links …
Link Management 19 min read

How to Add Deep Links to Your React Native App with HopLinks (2026 Guide)

O

owner

May 11, 2026

How to Add Deep Links to Your React Native App with HopLinks (2026 Guide)
HopLinks · Developer Guide May 2026 · React Native Integration
React Native · Expo · Deep Linking

How to Add Deep Links to Your React Native App with HopLinks

A complete, step-by-step guide to integrating HopLinks deferred deep links into React Native — both CLI and Expo. Covers native platform setup, React Navigation config, deferred link handling, and end-to-end testing. No proprietary SDK required.

What This Guide Covers

Firebase Dynamic Links is gone. If you're migrating your React Native app to HopLinks — or starting fresh — this guide walks you through the complete integration. We cover both the React Native CLI path and the Expo path (Expo SDK 54+), including deferred deep linking for new installs.

Prerequisites
React Native CLI project or Expo SDK 54+ project · React Navigation v6+ · A free HopLinks account · Android Studio / Xcode for native builds · ADB installed for Android testing

How HopLinks Deep Linking Works

HopLinks works entirely through native OS protocols — Universal Links (AASA) on iOS and Android App Links (Digital Asset Links) on Android. There is no proprietary SDK to install in your app. HopLinks automatically hosts the verification files on your behalf based on what you enter in the dashboard.

The deferred deep linking flow works in four stages:

  1. Click — user taps a HopLink on any platform.
  2. Install — if the app isn't installed, they're redirected to the App Store or Google Play.
  3. Match — on first app launch, HopLinks identifies the user via device fingerprinting and matches them to the original click.
  4. Route — the app opens directly to the intended destination, not the generic home screen.

"Standard deep links fail if the app isn't installed. Deferred Deep Links 'remember' the destination during the installation process, ensuring the user lands exactly where they intended after their first launch."

HopLinks Developer Guide
1

Dashboard Configuration

Before touching any code, register your app in the HopLinks dashboard. This is what activates the AASA and assetlinks.json endpoints that iOS and Android will verify.

  1. Log into your HopLinks console and go to App Settings.
  2. Create a new app configuration.
  3. For Android: enter your Package Name and SHA-256 fingerprint.
  4. For iOS: enter your Apple Team ID and Bundle Identifier.

Once saved, HopLinks automatically generates and serves the following files — you don't host anything yourself:

  • /.well-known/assetlinks.json — for Android App Link verification
  • /.well-known/apple-app-site-association — for iOS Universal Link verification
2

Native Platform Setup

Both iOS and Android need to know which domain your app is authorized to handle. The HopLinks domain to use is www.hpln.in (or your custom domain if configured).

Android — AndroidManifest.xml

Add the following intent filter to your main activity in AndroidManifest.xml:

XML AndroidManifest.xml
<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="www.hpln.in" />
</intent-filter>
⚠ Important The android:autoVerify="true" attribute is critical. Without it, Android will not fetch your assetlinks.json file, and deep links will silently fall back to opening in the browser instead of the app.

iOS — Xcode Associated Domains

In Xcode, navigate to your target → Signing & Capabilities → add the Associated Domains capability. Then add:

XCODE Associated Domains
applinks:www.hpln.in
ℹ Note iOS downloads the apple-app-site-association file at app install time. If your Team ID or Bundle ID in the HopLinks dashboard doesn't exactly match your Xcode settings, Universal Links will silently fail.
3

React Native CLI Integration

If you're using the React Native CLI (not Expo), the built-in Linking module handles incoming deep links. No extra package needed.

JSX App.js — React Native CLI
import React, { useEffect, useState } from 'react';
import { Linking, Text, View } from 'react-native';

const App = () => {
  const [initialUrl, setInitialUrl] = useState(null);

  useEffect(() => {
    // 1. App opened from cold start (was not running)
    const getUrlAsync = async () => {
      const url = await Linking.getInitialURL();
      if (url) handleDeepLink(url);
    };
    getUrlAsync();

    // 2. App was already open in background
    const subscription = Linking.addEventListener('url', (event) => {
      handleDeepLink(event.url);
    });

    return () => { subscription.remove(); };
  }, []);

  const handleDeepLink = (url) => {
    setInitialUrl(url);
    if (url.includes('/product/')) {
      const id = url.split('/').pop();
      console.log('Navigate to product ID:', id);
      // navigate('Explore', { id })
    }
  };

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Opened from: {initialUrl}</Text>
    </View>
  );
};

export default App;
4

Expo Integration (8 Steps)

Expo requires a few more configuration steps because the native build is managed by Expo's toolchain. Follow all 8 steps in order.

Step 4.1 — Install expo-linking

Always use npx expo install — not plain npm install — so Expo selects the version that matches your SDK.

BASH Terminal
npx expo install expo-linking

Step 4.2 — Configure app.json

Open app.json and add URL scheme, iOS associated domains, and Android intent filters:

JSON app.json
{
  "expo": {
    "scheme": "myapp",
    "ios": {
      "bundleIdentifier": "com.example.myapp",
      "associatedDomains": [
        "applinks:www.hpln.in",
        "applinks:hoplinks.in"
      ]
    },
    "android": {
      "package": "com.example.myapp",
      "intentFilters": [
        {
          "action": "VIEW",
          "autoVerify": true,
          "data": [
            { "scheme": "https", "host": "www.hpln.in" },
            { "scheme": "https", "host": "hoplinks.in" }
          ]
        }
      ]
    }
  }
}
⚠ Warning Always restart the Expo dev server after editing scheme or intentFilters. These changes are not hot-reloaded.

Step 4.3 — Configure React Navigation

Create a linking object that maps URL paths to screens, and pass it to NavigationContainer:

JSX App.js — React Navigation linking config
import * as Linking from 'expo-linking';
import { NavigationContainer } from '@react-navigation/native';

// Base prefix for Expo Go development URLs
const prefix = Linking.createURL('/');

const linking = {
  prefixes: [
    prefix,
    'myapp://',
    'https://www.hpln.in',
    'https://hoplinks.in',
  ],
  config: {
    screens: {
      Home:          'home',
      Explore:       'product/:id',   // :id is a dynamic param
      Notifications: 'notifications',
      Profile:       'profile',
    },
  },
};

export default function App() {
  return (
    <NavigationContainer linking={linking}>
      {/* Your navigator here */}
    </NavigationContainer>
  );
}

URL to Screen Mapping Reference

Screen Path Pattern Example URL
Home home myapp://home
Explore product/:id myapp://product/id123
Notifications notifications myapp://notifications
Profile profile myapp://profile

Step 4.4 — Read Parameters in Screens

React Navigation automatically injects URL segments as route params. Use the useRoute hook to access them:

JSX ExploreScreen.js
import { useRoute } from '@react-navigation/native';
import { View, Text } from 'react-native';

export default function ExploreScreen() {
  const route = useRoute();
  const deepLinkId = route.params?.id; // from :id in the URL pattern

  return (
    <View>
      {deepLinkId && (
        <Text>You opened product: {deepLinkId}</Text>
      )}
    </View>
  );
}
ℹ Note You do not need to call Linking.getInitialURL() manually when using React Navigation's linking config. React Navigation handles the initial URL automatically.

Step 4.5 — Domain Verification (Automatic)

This step requires no code. HopLinks automatically generates and serves both verification files based on your App Settings in the dashboard. Simply ensure your Package Name, SHA-256 fingerprint (Android), Team ID, and Bundle ID (iOS) are correctly entered.

  • Android: /.well-known/assetlinks.json — served automatically
  • iOS: /.well-known/apple-app-site-association — served automatically

Step 4.6 — Testing the Integration

Testing approach depends on whether you're running Expo Go or a native build.

Testing in Expo Go — use ADB

BASH Terminal — Expo Go (Android emulator)
adb shell am start -W -a android.intent.action.VIEW \
  -d "exp://127.0.0.1:8081/--/product/id123"
⚠ Important You cannot test https:// Universal Links inside Expo Go. The OS blocks them because Expo Go's certificate does not match your assetlinks.json. Use the Expo Go test URL format above.

Testing Native Builds — use uri-scheme CLI

BASH Terminal — native build
# Test the custom URI scheme first
npx uri-scheme open "myapp://product/id123" --android

# Once scheme works, test verified App Link
npx uri-scheme open "https://hoplinks.in/product/id123" --android
✔ Tip Always test myapp:// custom scheme routing before testing https:// App Links. This isolates navigation issues from domain verification issues.

Step 4.7 — Configure HopLinks Dashboard Links

Each HopLinks short link needs an In-App Deep Link value that maps to a screen in your app. In the dashboard, after setting the standard destination URL (web fallback), scroll to the "Deep Link Intent" section and set the value:

Target Screen In-App Deep Link value What it opens
Home Screen myapp://home Opens the Home tab
Explore (product) myapp://product/promo-123 Opens Explore with id=promo-123
Notifications myapp://notifications Opens Notifications screen
Profile Screen myapp://profile Opens the Profile screen

How HopLinks uses these values at runtime:

  • App installed: the phone intercepts the link and React Navigation routes to the correct screen.
  • App not installed: the custom scheme fails silently; HopLinks redirects the user to the App Store or Google Play.

Step 4.8 — Handle Deferred Deep Linking

This is the critical step for preserving intent across installs. Without it, users who click a HopLink, install the app, and open it for the first time will land on the generic Home screen — not the content they originally clicked.

Add a getInitialURL() function to your linking config:

JSX App.js — deferred deep link handling
const linking = {
  prefixes: [prefix, 'myapp://', 'https://www.hpln.in', 'https://hoplinks.in'],

  // This catches the URL that originally launched the app
  async getInitialURL() {
    // Check if opened via a standard OS deep link
    const url = await Linking.getInitialURL();
    if (url != null) return url;

    // Optional: call HopLinks API for deferred link data
    // const deferredUrl = await Hoplinks.getDeferredLink();
    // if (deferredUrl) return deferredUrl;

    return null;
  },

  config: {
    screens: {
      Home:          'home',
      Explore:       'product/:id',
      Notifications: 'notifications',
      Profile:       'profile',
    },
  },
};

To verify the complete deferred flow: click a HopLinks URL on a device that does not have your app installed → install from the store → confirm the app opens the correct screen on first launch.

Quick Reference — Do's & Don'ts

✔ Do

  • Ensure assetlinks.json package_name exactly matches app.json
  • Restart the Expo dev server after changing scheme or intentFilters
  • Use human-readable URL paths (e.g. hoplinks.in/explore/design)
  • Test myapp:// scheme routing before testing https:// links
  • Test on real physical devices for final verification

✘ Don't

  • Test https:// links in Expo Go — the OS blocks them
  • Add a .json extension to the apple-app-site-association file
  • Forget to update SHA-256 fingerprint when switching to production builds
  • Serve assetlinks.json with HTML content-type
  • Paste Universal Link URLs into the browser address bar — they won't trigger

Troubleshooting

Android — Links opening in browser instead of the app

  • Confirm android:autoVerify="true" is present in the intent filter.
  • Android can take up to 20 seconds after install to fetch and verify assetlinks.json. Try uninstalling and reinstalling the app before retesting.
  • Check that the SHA-256 fingerprint in the HopLinks dashboard matches your current build (debug and release fingerprints are different).

iOS — Universal Links not triggering

  • Confirm your Apple Team ID and Bundle ID in the HopLinks dashboard exactly match your Xcode settings — even a single character difference breaks verification.
  • Universal Links only trigger from a "click" in an external app (Notes, Mail, WhatsApp). Pasting the URL into Safari's address bar will not trigger them.
  • iOS fetches the AASA file at app install time, not at runtime. Reinstall the app after any changes.

Expo Go — https:// links not working

This is expected behavior. Expo Go cannot verify your AASA or assetlinks.json because its certificate doesn't match your app. Switch to a development build (npx expo run:android or npx expo run:ios) to test https:// links.

✦ Working Example

A complete working Expo demo project is available on GitHub: github.com/monkastro/Hoplinks_Codelab/tree/main/ExpoDemo. Clone and run it to see the full integration in action before applying it to your own project.

Frequently Asked Questions

Do I need to install any SDK or native module in my React Native app?

No. HopLinks works entirely through native OS protocols — Universal Links on iOS and Android App Links. The only package required for Expo is expo-linking, which is already part of the Expo ecosystem. For React Native CLI, the built-in Linking module is sufficient. No third-party SDK is added to your app binary.

Does HopLinks support Expo Go for testing?

Partially. You can test custom URI scheme links (myapp://) in Expo Go using ADB. However, you cannot test https:// Universal Links or App Links in Expo Go because the OS blocks them — Expo Go's certificate won't match your assetlinks.json. For https:// testing, use a development build via npx expo run:android or npx expo run:ios.

Do I need to host the AASA or assetlinks.json files myself?

No. HopLinks automatically generates and hosts both files based on the app details you enter in the dashboard (Package Name, SHA-256 fingerprint, Team ID, Bundle ID). You don't set up or manage any server-side files.

What happens if the user doesn't have the app installed when they click a HopLink?

HopLinks redirects the user to the App Store (iOS) or Google Play (Android). If you have deferred deep linking configured via getInitialURL() in your linking config, the user will be routed to the correct in-app destination on first launch after install. Without this step, they'll land on your app's default home screen.

My Android deep links are opening in the browser instead of the app. What's wrong?

The most common causes are: (1) android:autoVerify="true" is missing from the intent filter, (2) the SHA-256 fingerprint in the HopLinks dashboard doesn't match your current build — debug and release fingerprints are different, or (3) Android hasn't finished verifying the assetlinks.json yet — it can take up to 20 seconds after install. Uninstall and reinstall the app and wait before testing again.

Does this work with React Navigation v6?

Yes. The linking config pattern shown in this guide is specifically designed for React Navigation v6's NavigationContainer. The getInitialURL() function and config.screens object are both standard React Navigation v6 API.

Ready to Set Up HopLinks?

Create your free account, configure your app, and have your first deep link working in under 5 minutes. No credit card. No SDK bloat.

Create Free Account → Full Docs →

Source: HopLinks Developer Guide · Expo Demo Repository · Create Free Account

Keywords: HopLinks React Native, Expo deep linking 2026, deferred deep linking React Native, Universal Links Expo, Android App Links React Native, expo-linking setup, Firebase Dynamic Links alternative React Native, React Navigation deep link config

Tags

react-native expo deep-linking deferred-deep-linking hoplinks universal-links android-app-links firebase-alternative react-navigation mobile-development