Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.linkrunner.io/llms.txt

Use this file to discover all available pages before exploring further.

Deep links allow users to navigate directly to specific content within your app by clicking on a URL. This guide walks you through the complete setup — from creating your verification config files and saving them in Linkrunner, to making the necessary code changes in your app. There are two primary approaches to deep linking:
  1. HTTP/HTTPS Deep Links: URLs with http:// or https:// protocols that can open your app when clicked. Requires domain verification.
  2. Custom URI Schemes: URLs with a custom protocol like myapp:// that are registered to your app. No verification needed.

HTTP/HTTPS Deep Linking

HTTP/HTTPS deep links (including App Links on Android and Universal Links on iOS) require you to prove domain ownership before they work reliably. The setup has four parts:
  1. Create your verification config files
  2. Save them in Linkrunner
  3. Update native configuration (Android & iOS)
  4. Configure your app’s navigation

Step 1: Create Verification Config Files

Create a file named assetlinks.json with the following content:
[
    {
        "relation": ["delegate_permission/common.handle_all_urls"],
        "target": {
            "namespace": "android_app",
            "package_name": "your.package.name",
            "sha256_cert_fingerprints": ["SHA-256:XX:XX:XX:..."]
        }
    }
]
Replace:
  • your.package.name with your actual Android package name
  • SHA-256:XX:XX:XX:... with your app’s SHA-256 fingerprint

Get your app’s SHA-256 fingerprint

For debug builds:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
For release builds:
keytool -list -v -keystore your_release_keystore.keystore -alias your_key_alias
Look for the “SHA-256 Certificate fingerprint” line in the output.
Debug and release builds are signed with different keystores, so they produce different SHA-256 fingerprints. App Links verification will only succeed for the build whose fingerprint is currently saved in Linkrunner.Before testing or shipping a release build, either:
  • Update the sha256_cert_fingerprints value in Linkrunner to your release keystore’s fingerprint, or
  • List both fingerprints in the array so debug and release builds both verify:
"sha256_cert_fingerprints": [
    "SHA-256:DEBUG:FINGERPRINT:...",
    "SHA-256:RELEASE:FINGERPRINT:..."
]
If you use Google Play App Signing, get the release fingerprint from Play Console → Setup → App integrity, not your local upload keystore.

Step 2: Save Verification Config in Linkrunner

Linkrunner hosts your verification files automatically so you don’t have to manage server configuration yourself.
  1. Log in to your Linkrunner dashboard
  2. Go to Project Settings from the navigation menu
  3. In the Domain Verification section:
    • Paste your apple-app-site-association JSON in the iOS (Only JSON allowed) text area
    • Paste your assetlinks.json content in the Android (Only JSON allowed) text area
  4. Click Save
Linkrunner will automatically host these files at:
  • iOS: https://your-domain.io/.well-known/apple-app-site-association
  • Android: https://your-domain.io/.well-known/assetlinks.json

Step 3: Update Native Configuration

These changes are the same whether you’re using React Native or Flutter.
Open android/app/src/main/AndroidManifest.xml 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" />
  <!-- Your domain and subdomains -->
  <data android:scheme="https" android:host="example.com" />
  <data android:scheme="https" android:host="app.example.com" />
  <data android:scheme="https" android:host="store.example.com" />
</intent-filter>

Step 4: Configure Navigation

React Native uses React Navigation for handling deep links.
// 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",
                    },
                },
                "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

Custom URI schemes use a custom protocol like myapp:// and don’t require domain verification. They’re useful for backward compatibility or simpler setups.

Native Configuration

Open android/app/src/main/AndroidManifest.xml and add 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" />
  <data android:scheme="myapp" />
</intent-filter>

Use adb to test:
# 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

Troubleshooting

  • App doesn’t open automatically: Ensure your assetlinks.json is correctly formatted, the SHA-256 fingerprint matches your signing key, and the file is accessible via HTTPS.
  • Verification warnings: Look for “IntentFilterIntentSvc” messages in logcat for details on verification failures.