BlogEngineering
Engineering

App Links vs Universal Links: the practical setup guide nobody wrote

AASA, assetlinks.json, MIME types, scheme fallbacks. A field-tested checklist for shipping deep links that actually open the app.

DODaniel OkaforPrincipal EngineerFeb 12, 2026·10 min read

On paper, Universal Links and App Links are 'just' verified deep links served from your domain. In practice, half the apps we audit have at least one of them silently broken — usually because of a MIME type, a stale AASA cache, or an over-eager web router that catches the URL before the OS can.

The five-step checklist that catches 90% of bugs

  1. 1Serve apple-app-site-association from https://yourdomain/.well-known/apple-app-site-association as application/json. No redirects. No content negotiation. No subdomain forwarding.
  2. 2Serve assetlinks.json from https://yourdomain/.well-known/assetlinks.json. Include every package signature you ship under, including debug.
  3. 3Add the appropriate intent filter (Android) and associated domain entitlement (iOS). One typo and the OS silently fails open.
  4. 4Test on a fresh install, in a fresh browser, with the app force-quit. 'Works on my device' is a function of stale caches.
  5. 5Have a scheme-fallback path. If the OS doesn't intercept the URL, your web page should detect mobile and route to a custom scheme — Link Trail handles this for you out of the box.

What Link Trail handles for you

We serve AASA and assetlinks.json from your custom short domain with the correct MIME type, regenerate them when you add a new bundle ID, and ship a smart fallback page so URLs that aren't intercepted still route through a custom scheme. You configure the domain and the bundle IDs once.

# Verify your AASA is well-formed
curl -sI https://your.link/.well-known/apple-app-site-association \
  | grep -i content-type
# Expect: content-type: application/json
Tagged#iOS#Android#Deep linking