Technology·13 min read

How to Implement Deep Linking in Mobile Apps (And Why It Matters)

Deep links are the difference between a user landing on your home screen and landing exactly where they need to be. Here is how to implement them properly.

N

Nate Laquis

Founder & CEO ·

What Deep Linking Is and Why You Need It

Every mobile app has a home screen. Most users never want to land there. They want to land on the specific product they just saw in an email, the friend request waiting for them, the article someone shared on Twitter. Deep linking is how you get them there without friction.

There are three categories you need to understand:

  • Standard deep links: URI scheme-based links (like myapp://product/123) that open a specific screen in your app. They only work if the app is already installed.
  • Universal Links (iOS) and App Links (Android): HTTPS URLs that open directly inside your app when installed, or fall back to the web if not. The modern standard.
  • Deferred deep links: Links that remember where a user was trying to go even through an App Store install. Someone clicks a link, installs your app, and lands on the right screen on first launch. This is the one that moves conversion metrics.

The impact on product metrics is not subtle. Apps that implement deferred deep linking on their install campaigns routinely see 30 to 50 percent higher post-install engagement compared to campaigns that drop users on the home screen. Personalized onboarding flows triggered by a referral link can double day-7 retention. These are not theoretical gains, they show up in your analytics within weeks of implementation.

If your app sends marketing emails, runs paid acquisition, or has any kind of referral program, deep linking is not optional infrastructure. It is the difference between a campaign that performs and one that bleeds money.

Mobile devices showing deep linking navigation flow

URI Schemes: The Original Deep Link

Before Universal Links existed, URI schemes were the only way to deep link into a mobile app. You register a custom scheme like myapp:// in your app's manifest, and any link starting with that scheme will launch your app directly to the right screen.

On iOS, you declare this in your Info.plist under CFBundleURLTypes. On Android, it lives in your AndroidManifest.xml as an intent-filter with your custom scheme. The implementation is straightforward and still widely used today, especially for inter-app communication and development testing.

The problem is that URI schemes have serious limitations you need to understand before relying on them in production:

  • No fallback: If the app is not installed, the link simply fails. The OS may show an error, or nothing happens at all. There is no way to redirect users to the App Store or a web page.
  • No verification: Any app can register any URI scheme. A malicious app could register mybank:// and intercept links meant for your legitimate banking app. This is a real attack vector.
  • iOS shows a confirmation prompt: On iOS, opening a URI scheme link from Safari or a web view triggers a dialog asking the user if they want to open the app. This adds friction and some users dismiss it without understanding what it does.
  • Not indexable: Search engines cannot follow URI scheme links. Your deep-linked content is invisible to Google.

Use URI schemes for internal navigation between your own apps, for testing during development, or for cases where you have full control over the originating context. For anything user-facing in a marketing or growth context, move to Universal Links and App Links instead.

Universal Links and App Links: The Modern Approach

Apple introduced Universal Links in iOS 9. Google launched App Links for Android 6.0 shortly after. Both solve the core problems with URI schemes: they are real HTTPS URLs, they fall back gracefully to the web, and they require domain verification to prevent hijacking.

iOS Universal Links

The mechanism works through a file called apple-app-site-association (AASA). You host this JSON file at https://yourdomain.com/.well-known/apple-app-site-association with no file extension. It specifies which paths on your domain should open in your app versus the browser. Your app's entitlements list the associated domains. When iOS installs your app, it fetches this file from Apple's CDN and stores the mapping.

A minimal AASA file looks like this:

  • applinks key containing your app's team ID and bundle ID
  • paths array specifying which URL patterns trigger the app (e.g., /product/*, /invite/*)

One critical detail: the AASA file is fetched by Apple's servers at install time, not at link-click time. This means changes can take hours or days to propagate. Always test AASA changes against a fresh install, not an existing one.

Android App Links

Android uses a Digital Asset Links JSON file hosted at https://yourdomain.com/.well-known/assetlinks.json. Your AndroidManifest.xml intent filter needs android:autoVerify="true" on the HTTPS scheme entry. Android will verify the association at install time and, once verified, route links directly to your app without the disambiguation dialog that older URI schemes triggered.

Both systems require your HTTPS certificate to be valid and your server to return the file with the correct Content-Type: application/json header. Get either of these wrong and verification silently fails, with no obvious error to the user.

Deferred Deep Linking: Handling the App-Not-Installed Case

Standard deep links break when the app is not installed. The user clicks your link, gets taken to the App Store, downloads the app, and lands on your generic home screen with no memory of where they were trying to go. That is a terrible first impression and a wasted marketing spend.

Deferred deep linking solves this by persisting the destination intent through the install process. Here is how it works in practice:

  • A user clicks a link: https://yourapp.com/product/premium-headphones
  • The link service (Branch, Firebase, your custom implementation) stores the destination and any attribution parameters, keyed to fingerprint data like device type, IP, and user agent
  • The user is redirected to the App Store or Play Store
  • After install and first launch, your app calls the link service's SDK on startup
  • The SDK matches the new install against the stored fingerprint and returns the original destination
  • Your app navigates to the product page or triggers the correct onboarding flow

The fingerprinting approach has privacy implications worth knowing. Apple's App Tracking Transparency (ATT) framework and Android's privacy-first changes have made probabilistic fingerprinting less reliable since 2021. High-confidence deferred linking now depends on SKAdNetwork on iOS or the use of first-party data when possible.

Attribution is the other major benefit here. Deferred deep links let you track which campaign, email, influencer, or QR code drove each install. That data feeds directly into your paid acquisition decisions. Without it, you are optimizing campaigns blind.

Developer implementing deep linking code for mobile application

Implementation with React Native and Expo

If you are building with React Native, react-navigation has first-class deep linking support built in. You define a linking configuration object that maps URL patterns to screen names, pass it to your NavigationContainer, and the library handles incoming URLs automatically on both iOS and Android.

A basic linking config looks like this: you specify a prefixes array containing your HTTPS domain and your URI scheme fallback, then a config object mapping screen names to path patterns. React Navigation parses path parameters automatically and passes them as route params to the target screen.

For handling the URL on cold start versus when the app is already open, React Navigation uses Linking.getInitialURL() for cold starts and listens to Linking.addEventListener('url', ...) for foreground opens. You do not need to wire this manually; the NavigationContainer handles it when you pass the linking config.

If you are using Expo, the expo-linking package wraps React Native's Linking API with additional utilities:

  • Linking.createURL(path) generates correct URLs for both the Expo Go development environment and standalone production builds, without you hardcoding scheme names
  • The Expo Router library (file-based routing) integrates deep linking automatically, deriving your URL structure from your file system layout
  • EAS (Expo Application Services) handles the app.json entitlements and manifest entries for Universal Links and App Links when you configure associatedDomains in your app config

One thing to get right early: define your URL structure before launch. Changing deep link paths after you have shipped them in emails or QR codes is painful. Design your URL hierarchy to be stable, human-readable, and consistent with your web URLs.

Branch.io vs Firebase Dynamic Links vs Custom

You have three realistic options for handling deferred deep linking and attribution in production. Each has meaningful tradeoffs.

Branch.io

Branch is the most feature-complete solution. It handles Universal Links, App Links, deferred deep linking, attribution, and analytics in one SDK. The dashboard is well-designed, the reporting is detailed, and the support is responsive. The catch: pricing scales with monthly active users and can get expensive fast. At 500K MAU, you are looking at $500 to $2,000 per month depending on the plan. Branch makes sense when attribution data is a core business requirement and you need campaign-level reporting out of the box.

Firebase Dynamic Links

Google deprecated Firebase Dynamic Links in August 2025, with shutdown scheduled for August 2026. If you are still using Dynamic Links, migrate now. Do not wait. Options include Branch, Adjust, or a custom solution.

Custom Implementation

Building your own deferred deep linking is feasible if your requirements are simple: you just need to persist a destination through an install, with no complex attribution. The approach uses your own backend to store a short-lived token in a redirect URL. The app calls your API on first launch, looks up the token, and navigates accordingly. This works well and costs nothing beyond your server, but it gives you no fingerprinting, no campaign attribution, and no dashboard. It is the right choice for early-stage products that need the UX behavior without the analytics complexity.

Other providers worth evaluating: Adjust and AppsFlyer are strong in the mobile measurement partner space and include deep linking as part of their attribution suites. Both are priced for growth-stage and enterprise teams rather than early-stage startups.

Deep Linking for Marketing and Growth

A well-implemented deep linking system compounds over time because every marketing channel benefits from it simultaneously.

Email campaigns: Link every CTA in your transactional and marketing emails to a deep link. A password reset email that opens your app's reset screen directly instead of the mobile browser is a meaningfully better experience. A "your cart is waiting" email that drops the user on their cart saves two to three taps. These improvements show up in email-to-conversion rates.

Social media: Instagram, TikTok, and Twitter all support opening apps directly from link-in-bio tools and link stickers. If you run content marketing or influencer campaigns, every piece of content should link to a deferred deep link that attributes the install to that piece of content and lands the user in the right place.

QR codes: Physical-to-digital flows depend entirely on good deep linking. A QR code on product packaging, a restaurant menu, or an event poster should take the user to a specific screen, not your home page. If the app is not installed, it should handle the App Store redirect and then resume where they were.

Referral programs: This is where deferred deep linking pays the biggest dividend. A referral link shared by an existing user should carry the referrer's ID through the install, credit them automatically on first launch, and show the new user a personalized welcome screen. Building this without deferred deep linking requires workarounds that are fragile and hard to measure accurately.

  • Always use unique links per campaign, not one shared link, so you can isolate performance
  • Set expiration windows on deferred link data, typically 24 to 72 hours, to avoid stale matches
  • Pass UTM parameters through your deep links so your analytics platform attributes installs correctly
Global network visualization representing deep link routing

Testing, Debugging, and Common Pitfalls

Deep linking is one of the easier features to implement badly and never notice until a user reports it. Most bugs only surface in production builds on real devices, not in simulators or development environments.

Testing tools you should use:

  • iOS: Use xcrun simctl openurl booted "https://yourdomain.com/product/123" to test Universal Links in the simulator. For device testing, use the Notes app to tap a link, which bypasses Safari's caching behavior.
  • Android: Use adb shell am start -W -a android.intent.action.VIEW -d "https://yourdomain.com/product/123" to test App Links from the command line on a connected device.
  • Apple's validation tool: The App Search API Validation Tool at search.developer.apple.com will fetch and parse your AASA file and show you exactly what Apple sees. Use this before every release that touches your AASA.
  • Branch's link tester: If you are using Branch, their link tester in the dashboard simulates the full resolution flow including deferred linking.

Common pitfalls that will cost you time:

  • Forgetting to add the associated domain entitlement to your app's provisioning profile. The entitlement in app.json or Xcode is not enough on its own.
  • Serving the AASA file with the wrong content type or with a redirect. Apple's CDN follows one redirect but will fail on more. Serve the file directly at the canonical URL.
  • Testing Universal Links by typing the URL in Safari's address bar. Safari does not trigger Universal Links from the address bar. Use a link in a web page, email, or Notes.
  • Not handling the case where the deep link destination no longer exists. A product that was deleted, a post that was removed. Your app should detect this and redirect gracefully, not crash or show a blank screen.
  • Hardcoding scheme names in your React Native code instead of using expo-linking's createURL utility, which breaks the difference between Expo Go and production builds.

Set up a dedicated QA checklist for deep links before every release: test cold start with app not running, test foreground open with app already open, test the no-app-installed fallback URL, and verify attribution parameters are passing through correctly. It takes 20 minutes and saves hours of post-launch debugging.

If you want to get deep linking right the first time, including deferred linking, attribution setup, and marketing integration, Book a free strategy call and we will help you plan the implementation for your specific stack and growth model.

Need help building this?

Our team has launched 50+ products for startups and ambitious brands. Let's talk about your project.

deep linkingmobile app deep linksuniversal linksapp linksdeferred deep linking

Ready to build your product?

Book a free 15-minute strategy call. No pitch, just clarity on your next steps.

Get Started