Deep links allow users to navigate directly to specific content within your app by clicking on a URL. There are two primary approaches to deep linking:

  1. HTTP/HTTPS Deep Links (including subdomains): URLs with http:// or https:// protocols that can open your app when clicked.
  2. Custom URI Schemes: URLs with a custom protocol like myapp:// that are registered to your app.

This guide covers how to implement both methods for React Native and Flutter applications, and how they can be used together for a comprehensive deep linking strategy.

HTTP/HTTPS Deep Linking with Subdomains

When using subdomains for deep linking, you can create a structured approach to handle different sections or features of your app.

React Native uses React Navigation for handling navigation and deep linking.

Step 1: Configure your app to handle HTTP/HTTPS links

First, you need to modify your Android and iOS configurations to handle subdomain links.

Open your android/app/src/main/AndroidManifest.xml file and add the following inside the <activity> section:

<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" />
  <!-- For your main domain -->
  <data android:scheme="https" android:host="example.com" />
  <!-- For your subdomain -->
  <data android:scheme="https" android:host="app.example.com" />
  <!-- Add other subdomains as needed -->
  <data android:scheme="https" android:host="store.example.com" />
</intent-filter>

Step 2: Configure React Navigation

In your navigation configuration:

// App.js or your navigation configuration file
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import LinkRunner from "@linkrunner/react-native";

const Stack = createStackNavigator();

function App() {
    const linking = {
        prefixes: ["https://example.com", "https://app.example.com", "https://store.example.com"],
        config: {
            screens: {
                Home: "",
                Profile: "profile/:id",
                Store: {
                    path: "store/:category?",
                    parse: {
                        category: (category) => category || "all",
                    },
                },
                // For subdomain-specific routing
                "app.example.com": {
                    screens: {
                        AppSpecificScreen: ":id",
                    },
                },
                "store.example.com": {
                    screens: {
                        StoreSpecificScreen: ":id",
                    },
                },
            },
        },
    };

    return (
        <NavigationContainer linking={linking}>
            <Stack.Navigator>{/* Your screens */}</Stack.Navigator>
        </NavigationContainer>
    );
}

export default App;

Custom URI Schemes for Deep Linking

Custom URI schemes provide an alternative method for deep linking, allowing your app to handle URLs with a custom protocol like myapp://. While HTTP/HTTPS deep links are generally recommended for production apps, custom URI schemes can be useful in specific scenarios or for backward compatibility.

Step 1: Configure your app to handle custom URI schemes

Open your android/app/src/main/AndroidManifest.xml file and add the following inside the <activity> section:

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <!-- Your custom URI scheme -->
  <data android:scheme="myapp" />
</intent-filter>

Use adb for Android testing:

# Test HTTP/HTTPS deep links
adb shell am start -a android.intent.action.VIEW -d "https://app.example.com/profile/123" your.package.name

# Test custom URI scheme
adb shell am start -a android.intent.action.VIEW -d "myapp://profile/123" your.package.name