Edok Studio Edok Studio
Guide

Deep links that open your app — without an SDK

Updated August 31, 2026 6 min read

One link, three outcomes: it opens your app at the right screen if the app is installed, sends a phone without it to the right store, and shows a web page on a laptop. That is a solved problem, it is free, and — despite what most of the pages ranking for this query imply — it needs no SDK. What it needs is two files on your domain and one app release.

Verified against Apple’s associated-domains documentation and Google’s Android App Links verification guide on 31 August 2026.

The whole mechanism, in four parts

Universal Links and App Links are an operating-system feature. The chain is short, and nothing in it is proprietary:

Once that is done, a tap on your link never reaches any server: the phone recognises the address and opens your app directly. That is worth stating plainly, because it explains both why the feature is reliable and why the click numbers in any dashboard undercount.

iOS: the entitlement and the AASA file

Add the Associated Domains capability in Xcode, with one entry per domain in the form applinks:links.yourapp.com. Then serve a file named apple-app-site-association — no extension — from the .well-known directory of that domain. Apple is explicit that it must be served over https:// with a valid certificate and with no redirects.

The no-redirect rule is the cruellest failure mode in this whole topic: a redirect is invisible when you open the URL in a browser — the file appears, the JSON looks right — and fatal to verification. A www rule or a CDN page rule is the usual culprit.

The file names your app as TEAMID.bundle.id and lists the paths it should handle. Scope those paths. If you also host a marketing page or your privacy policy on the same domain, a file claiming * tells iOS to open your app for those pages too.

Android: the intent filter and assetlinks.json

Add an intent filter to the activity that should receive the link, carrying android:autoVerify="true", the VIEW action, both the DEFAULT and BROWSABLE categories, and your https host. Then serve /.well-known/assetlinks.json over HTTPS, naming your package and its SHA-256 signing certificate fingerprints. Android verifies this at install time.

Then get the fingerprint right, because this is where most setups fail. The fingerprint has to match the certificate the installed APK is actually signed with. If your app uses Play App Signing — the default for new apps — Google re-signs your upload with a key you have never seen, so the fingerprint from your own keystore verifies nothing. Publish the one from Play Console → Test and release → App signing, and list your upload key as well so locally-installed debug builds keep working. The file accepts an array of fingerprints for exactly this reason.

You can check what Google itself sees with its Digital Asset Links checker, which reports whether your site grants your package permission to handle its links.

The one thing that genuinely does not work

“Tap a link for a product, don’t have the app, install it, and land on that product.” This is called deferred deep linking, and it is not a routing problem. When the user opens your freshly installed app from the home screen, it launches cold: no intent, no activity, no launch URL. The operating system preserved nothing across the install, so your route handler is fine — it simply never fires.

PlatformDeferred deep linkingWhy
AndroidWorks, exactlyAdd ?referrer=… to the Play Store URL. Play carries it through the install and hands it to the app on first launch via the Install Referrer library (ReferrerDetails.installReferrer, available for 90 days).
iOSProbabilistic at bestApple provides no mechanism that carries a payload through an App Store install. SKAdNetwork postbacks go to ad networks, AdServices covers Apple Search Ads only, and the clipboard trick now shows the user a banner.
An SDK does not change either row — on iOS it performs the same guess, using IP and device characteristics.

What is left on iOS is matching a new install against a recent click by IP address, device model and time window. That breaks in cafés, offices and anywhere behind carrier NAT, breaks entirely under iCloud Private Relay, and is exactly the practice privacy regulators single out. Treat anyone claiming reliable iOS deferred deep linking with suspicion.

The workaround nobody advertises is free and completely reliable: after installing, tap the original link again. The Universal Link now fires and lands on the right screen. Plenty of well-known apps say precisely this on their post-install screen.

Why every deep-link dashboard undercounts

When the mechanism works, the OS opens your app without contacting a server — so that tap is invisible to us, to Branch, to AppsFlyer, and to you. Any number you see is the fallback traffic: visitors without the app, desktop browsers, and in-app webviews. That is a property of the platform, not a bug in a tool, and a dashboard that does not explain it is training you to read it wrongly.

When a link opens the browser: the checklist

Where a hosted option helps

Nothing above needs a vendor — but all of it needs a domain you control, serving two exact paths over HTTPS, and most indie developers have no server at all. That, rather than the mechanism, is the actual gap.

Edok Studio gives each app a domain (or connects yours), serves both association files from it, and lets you create and change links afterwards without touching the app again — with QR codes, click analytics, and a live check that fetches your files the way Apple and Google do and tells you which of the failure modes above you have hit. Android deferred deep linking is supported deterministically through the install referrer; we do not claim the iOS version, because it does not work.

Set up your app links

Design once with device frames and export every required App Store & Google Play size in one ZIP — watermark-free on the free plan.

Start free — no card

Frequently asked questions

Do I need an SDK for deep links?

No. Universal Links on iOS and App Links on Android are operating-system features. They need two JSON files hosted on your domain, an entitlement or intent filter in your app, one release, and routing code you write yourself. An SDK can add attribution and analytics, but it cannot make the link work — the OS does that.

Why does my link open the browser instead of my app?

Four causes cover almost every case: the SHA-256 fingerprint in assetlinks.json is the upload key rather than the Play App Signing key Google re-signed with; the apple-app-site-association file is served through a redirect, which Apple does not follow; a CDN is serving a cached older copy of either file; or the app release carrying the entitlement has not shipped yet.

Does deferred deep linking work on iOS?

Not reliably, for anyone. Apple provides no mechanism that carries a payload through an App Store install: nothing survives the round trip, SKAdNetwork postbacks go to ad networks rather than your app, and the clipboard trick now shows the user a banner or asks permission. What remains is probabilistic matching on IP and device characteristics, which breaks on shared networks and under iCloud Private Relay. On Android the same feature is exact, because the Play Store carries an install referrer through the install.

Do I need my own web server?

You need somewhere to serve two files over HTTPS at fixed paths under /.well-known/ on the domain your links use. Many indie developers have no server at all, which is the real reason deep links go unimplemented. A hosted option — including Edok Studio — serves both files for you from a domain per app.

What is the difference between a deep link, a universal link and an app link?

A deep link is any URL that points at a specific place inside an app. A Universal Link (Apple) and an App Link (Google) are the modern web-URL forms of it: an https:// address that the operating system hands to your app when your domain and app vouch for each other, and that opens a normal web page when the app is not installed. A custom URI scheme like myapp:// is the older form — it still works inside some in-app browsers, but it fails silently when the app is missing.

Keep reading