Blog Link Management Deep Linking for Expo & …
Link Management 12 min read

Deep Linking for Expo & React Native with HopLinks — No SDK Required

O

owner

May 14, 2026

Deep Linking for Expo & React Native with HopLinks — No SDK Required

Deep linking for Expo —
no SDK, no bloat

Firebase Dynamic Links is gone. Most replacements force you to install a heavy SDK, configure native files for hours, and debug link handlers for days. HopLinks uses the native deep linking protocols already built into iOS and Android — so your Expo app gets smart, deferred deep links with zero proprietary dependencies.

🔗
Dynamic links

Device-aware routing — app, store, or web fallback.

Deferred deep links

Remembers the destination across the install flow.

🛡️
No proprietary SDK

Built on Universal Links (iOS) and App Links (Android).

Auto-hosted verification

HopLinks hosts your AASA and assetlinks.json files.

How HopLinks works

Every HopLink is a device-aware smart URL. When tapped, it runs through four stages:

1

Click

User taps your link on any channel — email, social, QR code, ad.

2

Install (if needed)

App not installed? HopLinks redirects to the App Store or Play Store. The intended destination is preserved for step 4.

3

Match

HopLinks identifies the user on first app launch via its deferred linking engine.

4

Route

The user lands on exactly the right screen — even after a fresh install from the store.

"Instead of adding a third-party SDK, HopLinks leverages Universal Links and App Links — the native protocols built directly into iOS and Android."

On iOS this means an apple-app-site-association file at /.well-known/. On Android it's an assetlinks.json containing your SHA-256 fingerprints. HopLinks generates and hosts both files automatically once you register your app details in the dashboard.

Expo integration — 8 steps

1

Install expo-linking

Use npx expo install — not plain npm — so Expo picks the version that matches your SDK.

Terminal
npx expo install expo-linking

The package is added to package.json with the correct SDK version constraint automatically.

2

Configure app.json

Set your custom URL scheme and register the HopLinks verified domains for both platforms.

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" } ] } ] } } }
Important: "autoVerify": true tells Android to fetch and verify assetlinks.json. Without it, App Links silently fall back to the browser. Always restart the Expo dev server after editing scheme or intentFilters.
3

Configure React Navigation

Create a linking object mapping URL paths to screen names, and pass it to NavigationContainer.

App.tsx
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 navigators */} </NavigationContainer> ); }
4

Read parameters in screens

React Navigation injects URL path segments as route params automatically. Use useRoute() to access them.

ExploreScreen.tsx
import { useRoute } from '@react-navigation/native'; export default function ExploreScreen() { const route = useRoute(); const productId = route.params?.id; return ( <View> {productId && <Text>Product: {productId}</Text>} </View> ); }
You don't need to call Linking.getInitialURL() manually here — React Navigation handles URL parsing and param injection automatically.
5

Verify domain ownership (automatic)

In the HopLinks dashboard, go to App Settings and enter:

  • Android: Package Name and SHA-256 Fingerprint
  • iOS: Team ID and Bundle ID

HopLinks then automatically generates and hosts both verification files:

  • Android: /.well-known/assetlinks.json
  • iOS: /.well-known/apple-app-site-association
You never touch these files manually. HopLinks handles generation and serving on your behalf.
6

Test the integration

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

Expo Go — adb (Android emulator/device)
adb shell am start -W -a android.intent.action.VIEW \ -d "exp://127.0.0.1:8081/--/product/id123"
Native build — uri-scheme CLI
# Custom scheme npx uri-scheme open "myapp://product/id123" --android # Verified App Link (https) npx uri-scheme open "https://hoplinks.in/product/id123" --android
Cannot test https:// links in Expo Go. The OS blocks them because Expo Go's certificate doesn't match your assetlinks.json. Always test myapp:// routing first, then move to https:// links in a native build.
7

Configure the HopLinks dashboard

For each link, set the In-App Deep Link field to the custom scheme URI for the target screen.

Target screenIn-App Deep Link valueWhat opens
Homemyapp://homeHome tab
Exploremyapp://product/promo-123Explore with id=promo-123
Notificationsmyapp://notificationsNotifications screen
Profilemyapp://profileProfile screen
App installed → OS intercepts the intent, React Navigation routes to the correct screen. App not installed → HopLinks redirects to the App Store or Play Store.
8

Handle deferred deep linking

Without this step, users who install via your link always land on Home instead of the screen they clicked. Add getInitialURL() to your linking config:

App.tsx — add getInitialURL
const linking = { prefixes: [prefix, 'myapp://', 'https://www.hpln.in', 'https://hoplinks.in'], // Catches the URL that launched the app on cold start async getInitialURL() { const url = await Linking.getInitialURL(); if (url != null) return url; return null; }, config: { screens: { Home: 'home', Explore: 'product/:id', Notifications: 'notifications', Profile: 'profile', }, }, };
Verify end-to-end: tap a HopLink on a device without the app → install from the store → confirm the app opens the correct screen on first launch.

Implementation checklist

  • app.json: scheme set
  • app.json: associatedDomains added for iOS (www.hpln.in + hoplinks.in)
  • app.json: intentFilters with autoVerify: true for Android
  • App.tsx: linking config with correct prefixes and screen paths
  • App.tsx: getInitialURL() added for deferred deep links
  • HopLinks dashboard: Bundle ID + SHA-256 fingerprint registered
  • Tested myapp:// scheme routing with uri-scheme CLI
  • Tested https:// App Link in a native build
  • Deferred link flow verified end-to-end

React Native CLI — key differences

Using bare React Native CLI instead of Expo managed workflow? The app.json config doesn't apply — you modify native files directly.

AspectExpo ManagedReact Native CLI
Configurationapp.json only ✓AndroidManifest.xml, Info.plist, AppDelegate.mm
URL Schemeexp:// in Expo GoCustom (e.g. myapp://)
Universal LinksHandled automatically ✓Manual autoVerify + AASA
Native bridgeBuilt-in ✓Import RCTLinkingManager manually

A complete React Native CLI example is in the HopLinks Codelab on GitHub. HopLinks also has integration guides for Flutter, Android Kotlin/Java, and iOS Swift — see the full developer docs.

HopLinks vs other solutions

FeatureHopLinksBranch / AppsFlyerFirebase DL
Proprietary SDK requiredNo ✓YesYes (deprecated)
Expo managed workflowFull support ✓LimitedRequires bare
Deferred deep linksYes ✓Yes ✓Deprecated
Auto-hosted AASA / assetlinksYes ✓Self-hostedSelf-hosted
Privacy-first analyticsYes ✓FingerprintingNo
Setup time~15 min ✓Hours–daysN/A (gone)
Free tierYes ✓LimitedNo

Troubleshooting

Android — links open the browser instead of the app

Check that autoVerify: true is in intentFilters. Without it, Android never verifies ownership. Verification can take up to 20 seconds after app installation.

iOS — Universal Links not triggering

Confirm your Team ID and Bundle ID in the HopLinks dashboard exactly match what's configured in Xcode. iOS downloads the AASA file at install time — a mismatch silently breaks the link.

Links don't trigger when pasted into the browser address bar

This is by design. Universal Links and App Links only trigger when tapped from another app — Notes, WhatsApp, Mail, etc. Pasting into a browser address bar always opens the web fallback.

Frequently asked questions

What is a deferred deep link and why does it matter?
Standard deep links fail silently if the app isn't installed. A deferred deep link preserves the intended destination across the install flow — after the user installs and opens the app for the first time, they land on the right screen instead of Home. This is step 8 in this guide, and it's the step most tutorials skip.
Does HopLinks require any SDK in my Expo app?
No. The only package you install is expo-linking, which is a first-party Expo library. HopLinks operates as a hosted redirect service — there is nothing proprietary running inside your app.
What domains do I register in app.json?
Register both applinks:www.hpln.in and applinks:hoplinks.in. HopLinks automatically hosts the required apple-app-site-association and assetlinks.json files on these domains after you add your app details in the dashboard.
Is HopLinks a Firebase Dynamic Links replacement?
Yes. HopLinks is built explicitly as a modern alternative to Firebase Dynamic Links, which Google shut down. It provides the same smart routing, deferred deep linking, and analytics — without Firebase or any proprietary SDK.
Does HopLinks work with Flutter, Kotlin, and Swift?
Yes. HopLinks has integration guides for Flutter (using the app_links package), Android Kotlin, Android Java, and iOS Swift using SceneDelegate. See hoplinks.in/docs for full instructions.

Start linking smarter today

Free tier available. No credit card required.

Create free account Full Expo docs

Tags

deep linking expo react native deep linking expo universal links app links android deferred deep linking firebase dynamic links alternative hoplinks expo integration expo-linking setup sdk free deep linking