React Native Deep Linking

A deep link is a web-style address that opens a specific screen inside an app. A friend shares a product link, a user taps it in a message, and the app opens directly on that product page. Notification taps, email buttons, and marketing campaigns all rely on deep links to drop people exactly where they need to go.

The Normal Path Versus a Deep Link

Without deep link                With deep link
─────────────────────            ───────────────────────────────
Open app                         Tap: myapp://product/42
Find Shop tab                              │
Search for item                            ▼
Open product 42                  App opens on Product 42 directly

Two Kinds of Links

Type               Example                          Behavior
──────────────────────────────────────────────────────────────────
Custom scheme      myapp://product/42               Opens app if installed
Universal / App    https://example.com/product/42   Opens app if installed,
Link                                                 opens website otherwise

Custom schemes are simple to set up and ideal for testing. Universal links on iOS and App Links on Android use normal web addresses, which look professional and fall back to a website when the app is missing.

Step 1: Register a Scheme

Choose a unique scheme name in app.json.

{
  "expo": {
    "scheme": "myapp"
  }
}

Step 2: Map Links to Screens

React Navigation reads a linking configuration that connects address paths to screen names.

import { NavigationContainer } from '@react-navigation/native';
import * as Linking from 'expo-linking';

const prefix = Linking.createURL('/');

const linking = {
  prefixes: [prefix, 'https://example.com'],
  config: {
    screens: {
      Home: 'home',
      Product: 'product/:id',
      Profile: 'user/:username',
      Settings: 'settings',
    },
  },
};

export default function App() {
  return (
    <NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
      {/* navigators */}
    </NavigationContainer>
  );
}
myapp://product/42
         │      │
         │      └── :id = 42  → passed to the screen as a param
         └───────── "product" → Product screen

Step 3: Read the Parameter

function ProductScreen({ route }) {
  const { id } = route.params;
  return <Text>Showing product {id}</Text>;
}

Treat every incoming value as untrusted text. Validate the id before using it in a request, since anyone can craft a link.

Nested Navigators

Describe the full path through tabs and stacks.

config: {
  screens: {
    MainTabs: {
      screens: {
        HomeTab: 'home',
        ShopTab: {
          screens: {
            Product: 'product/:id',
          },
        },
      },
    },
  },
}

Test Links During Development

Fire a link from the terminal while an emulator runs.

npx uri-scheme open "myapp://product/42" --android
npx uri-scheme open "myapp://product/42" --ios

Handle Links Manually

Read the launching link or listen for links that arrive while the app runs.

import * as Linking from 'expo-linking';

useEffect(() => {
  Linking.getInitialURL().then((url) => {
    if (url) console.log('Launched with', url);
  });

  const sub = Linking.addEventListener('url', ({ url }) => {
    const parsed = Linking.parse(url);
    console.log(parsed.path, parsed.queryParams);
  });

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

Universal Links and App Links

A web address opens the app only when your website proves that you own both. Publish a small verification file on your domain.

iOS      https://example.com/.well-known/apple-app-site-association
Android  https://example.com/.well-known/assetlinks.json

Add matching entries to the app configuration: associated domains for iOS and intent filters for Android. The verification files list the app identifiers that may open your links.

Links from Notifications

A push notification can carry a link in its data. When the user taps it, the app opens the matching screen.

{
  "title": "Order shipped",
  "body": "Track your package",
  "data": { "url": "myapp://orders/981" }
}

Sharing a Link

import { Share } from 'react-native';

Share.share({
  message: 'Check out this item: https://example.com/product/42',
});

Safety Checklist

  • Validate and sanitize every parameter
  • Require sign-in before showing private screens, then continue to the target after login
  • Avoid performing actions such as purchases directly from a link
  • Provide a graceful screen for unknown or broken paths

Summary

Deep links open exact screens from outside the app. Register a scheme, map paths to screens in the navigation linking configuration, and read parameters from the route. Use custom schemes for testing and universal or app links for production sharing, and validate every incoming value.