Back to Blog
Mobile App

What Is Deep Linking and How to Set It Up in Apps

What is deep linking and how do you set up Universal Links and Android App Links? Custom URL schemes, deferred deep links, verification files, React Native configuration and the most common mistakes.

Deep LinkMobil UygulamaUniversal LinksAndroid App LinksReact Native

A deep link is a link that takes the user not to an app’s home screen but straight to a specific piece of content, such as a product page, an order or a password reset screen. Today the right approach is to connect your website’s normal HTTPS addresses to the app: Universal Links on iOS and App Links on Android. If the app is installed, the link opens the matching screen in the app; if not, the same address opens on your website. For this to work, you need a verification setting both in the app and on your domain; if either is missing, the link silently falls back to the browser.

Types of deep links: custom scheme, verified link, deferred link

  • Custom URL scheme (myapp://product/42): the easiest to set up but not verified; another app can register the same scheme, and if the app is not installed the link goes nowhere.
  • Verified link (https://yourdomain.com/product/42): Universal Links on iOS, App Links on Android. You prove to the operating system that you own the domain, and without the app the page opens on the web.
  • Deferred deep link: if the user has not installed the app yet, the goal is to take them to the same content when they install it from the store and open it for the first time. The operating system does not provide this on its own; it needs separate infrastructure.

Custom schemes are not abandoned entirely; they are still useful for in-app routing and some third-party callbacks. But every link shared in email, SMS, social media or ads should be a verified HTTPS address. This is also a security issue: if a password reset or sign-in link is sent with a custom scheme, a malicious app that registers the same scheme can intercept it. We cover the security side in more detail in our article on mobile app security.

iOS: how to set up Universal Links

Universal Links are a two-sided match. On the app side, the Associated Domains capability is enabled and lists the domains the app claims. On the server side, a JSON file called apple-app-site-association is placed in the .well-known folder at the root of your domain; it states which app may open which paths. The file must be served over HTTPS, without redirects and with the correct content type. Apple reads the file through its own cache rather than on every request, so it is normal for a change not to take effect immediately; testing requires a fresh install.

{
  "applinks": {
    "details": [
      {
        "appIDs": ["TEAMID.com.company.app"],
        "components": [
          { "/": "/urun/*" },
          { "/": "/siparis/*" },
          { "/": "/hesap/sifre-sifirla" }
        ]
      }
    ]
  }
}

Android: how to set up App Links

On Android, an intent filter is declared in the app manifest for the relevant screen with the autoVerify attribute enabled. On the server, an assetlinks.json file goes into the same .well-known folder; it contains the package name and the SHA-256 fingerprint of the certificate that signs the app. This is where the most common mistake happens: if the app is published with Google Play App Signing, the store build is signed with Google’s key. If the file only lists the fingerprint of the developer’s upload key, the link works on the test device but not in the app downloaded from the store. The correct fingerprint is on the app signing page in Play Console.

Most deep link problems live in the verification file, not in the code: a redirected address, the wrong content type or the upload key’s fingerprint. The link never throws an error; it simply opens in the browser instead of the app.

Routing inside the app: a React Native example

Once the operating system hands the link to the app, the app decides which screen to open. In React Native projects this is usually done with React Navigation’s linking configuration: URL patterns are mapped to screens and parameters are passed to them. The key point is to treat every parameter from a link as user input; a product ID must be validated, and screens that require a session should send signed-out users to the sign-in screen first and return them to the target afterwards.

import type { LinkingOptions } from '@react-navigation/native';
import type { RootStackParamList } from './types';

export const linking: LinkingOptions<RootStackParamList> = {
  prefixes: ['https://yourdomain.com', 'myapp://'],
  config: {
    screens: {
      Product: {
        path: 'urun/:id',
        parse: { id: (id: string) => (/^\d+$/.test(id) ? Number(id) : 0) },
      },
      Order: 'siparis/:orderId',
      ResetPassword: 'hesap/sifre-sifirla',
      NotFound: '*',
    },
  },
};

The NotFound line collects every unknown address on an error screen; without it, a link to a page newly added on the web might land on a blank screen in the app. That is why it is safer to claim only the paths that actually exist in the app in your apple-app-site-association and assetlinks.json files. Test links both on a cold start, when the app is closed, and on a warm start, when it is waiting in the background; the two go through different code paths.

Deferred deep links and campaign links

For a long time Firebase Dynamic Links covered this need; since Google shut the service down, apps that relied on it had to move their links to another solution. On Android, the Play Install Referrer can pass the link that brought the user to the store into the app after installation. iOS has no equivalent official mechanism; third-party services use probabilistic matching, which is neither exact nor free from privacy restrictions. The practical advice: do not make critical flows depend on deferred links. Values such as invite or campaign codes should also be offered for manual entry on first launch. Using consistent UTM parameters to measure campaign links also keeps you aligned with your ASO and app store optimization work.

Where deep linking makes a difference

  • Push notifications: a user who taps a notification should see the related order or message; a notification that lands on the home screen wastes the tap. Details in our push notification article.
  • Email and SMS: order tracking, password reset and email verification links should open the right screen in the app.
  • Sharing: a product link shared by a user should open in the app for friends who have it, and on the web for those who do not.
  • Ads and campaigns: if a user from an ad lands on the generic home screen instead of the campaign page, the conversion is lost.

Common mistakes and a checklist

These checks before release catch most problems: are the verification files reachable over HTTPS without redirects, does the Android fingerprint belong to the store signing key, are the www and non-www versions of the domain claimed separately, do session-gated screens return to their target after sign-in, and do undefined paths go to an error screen. A website migration or a redirect change on the web side can affect the verification files too; when moving a site, check that these files sit at the same address on the new server. And when an app changes its link structure, old addresses must not break; review this whenever you release a mobile app update.

Conclusion

Deep linking is the infrastructure that lets your app speak the same address language as your website, email, notifications and ads. Setting it up correctly means using verified HTTPS addresses for every shared link, publishing both platforms’ verification files in full and routing inside the app while validating every parameter. If you would like to set up link infrastructure in your app or review an existing setup, take a look at our mobile app service or request a quote.

Let's Build Your Project

Get a free consultation for your website, mobile app, or corporate software project.

Get a Free QuoteExplore our Mobile App service