Blog

How to Configure AASA Files for Universal Links

Lakshith Dinesh

Lakshith Dinesh

Head of Growth, Linkrunner

How to Configure AASA Files for Universal Links

Your Universal Link opens Safari instead of the app. Nine times out of ten, the culprit is not your code; it is a malformed or mis-hosted apple-app-site-association file. It is the single most common Universal Links failure we see across deep linking audits, and it is almost always a small, fixable detail in one JSON file.

This is the file-level guide: how to structure the AASA file, where to host it, and how to validate it so links open the app every time. For why links break once they are inside Instagram or TikTok, that is a separate problem covered in our in-app browser guide.

What is an AASA file, and why do Universal Links depend on it?

An apple-app-site-association (AASA) file is a JSON file hosted on your domain that tells iOS which app is allowed to open which URLs on that domain. Without a valid one, iOS has no reason to hand a link to your app, so it opens the URL in Safari instead.

When your app is installed, iOS fetches the AASA file for any domain listed in the app's associated-domains entitlement, then uses it to decide whether a tapped link should deep link into the app. If the file is missing, unreachable, or malformed, the association silently fails and every link falls back to the browser. For where Universal Links sit among the broader link types, see our complete guide to deep links.

The anatomy of a correct AASA file

The file lives under the applinks key. A minimal modern version looks like this:

{
  "applinks": {
    "details": [
      {
        "appIDs": ["TEAMID.com.yourcompany.app"],
        "components": [
          { "/": "/promo/*", "comment": "Open promo links in app" },
          { "/": "/blog/*", "exclude": true }
        ]
      }
    ]
  }
}

The details that matter:

  • appID format is TeamID.bundleID. The Team ID is your 10-character Apple Developer team identifier, not the app name. A wrong Team ID is a frequent cause of silent failure.
  • Use components (newer) or paths (legacy). components allows finer matching and exclusions; paths still works. Do not mix the two carelessly.
  • Path matching is literal and order-sensitive. Wildcards (*) and exclusions behave exactly as written, so an over-broad * can route URLs you meant to keep in the browser.

Tech Explainer: why the JSON itself breaks things. iOS parses this file strictly. A trailing comma, a .json extension that changes how your server sets the content-type, or BOM characters from a text editor can all make the file unparseable. The link then fails with no error shown to the user. Validate the raw bytes, not just how it looks in a browser tab.

Hosting requirements that trip teams up

Getting the file right is half the job; serving it correctly is the other half:

  • Host at https://yourdomain/.well-known/apple-app-site-association. HTTPS is mandatory. The .well-known path is the expected location.
  • Serve it with no redirect. If the request 301s or 302s to another URL, iOS treats the association as invalid. Serve the file directly with a 200 response.
  • Use the right content-type and no extension. The file should have no .json extension and be served as application/json. A misconfigured server is a classic break point.
  • Add the associated-domains entitlement in the app. The domain must be declared on the app side (for example applinks:yourdomain) or iOS never fetches the file at all.

For branded or subdomain hosting (DNS, SSL, and where the file sits), our custom link domains guide covers the domain side in full. Apple's own associated-domains documentation is the authoritative reference for the entitlement.

How to validate and debug an AASA file

Most AASA problems show the same handful of signatures. Diagnose in this order:

  1. Confirm the file is served correctly. Request the .well-known URL directly and check for a 200, application/json, no redirect, and valid JSON.
  2. Test on a real device, not the simulator. Universal Links behave differently in the simulator; a clean install on a physical device is the only reliable test.
  3. Read the failure signature:
  • Opens Safari every time: the file is unreachable, redirected, or the entitlement is missing.
  • Opens the app but the wrong screen: the file is valid but your path matching or in-app routing is off.
  • Works on one iOS version only: stale entitlement or a caching issue on older builds.

The cache gotcha most guides skip: Apple fetches the AASA file through a CDN at install time and caches it. Editing the file does not take effect on already-installed apps immediately, and a fresh install pulls Apple's cached copy, not your edit, until it refreshes. Plan changes ahead of campaigns rather than minutes before. For a fuller iOS failure-mode tree, see why your deep links break on iOS.

AASA and attribution: keeping context through the open

A correct AASA file is necessary for Universal Links, but it is not sufficient for measurement:

  • The file gets the user into the app. It does nothing on its own to preserve the campaign context or attribute the open.
  • To carry context (which campaign, which creative, which destination) through the tap and, if needed, through an install, you pair Universal Links with deferred deep linking and attribution, as in Linkrunner's deferred deep linking setup.
  • Android parity: the equivalent file for Android App Links is assetlinks.json, hosted at the same .well-known path with the same no-redirect, correct-content-type discipline.

A pre-launch AASA checklist

Before any campaign that relies on Universal Links goes live:

  • The .well-known/apple-app-site-association URL returns 200, application/json, no redirect.
  • The appID uses the correct TeamID.bundleID.
  • Path components match exactly the URLs you intend to open in-app, with deliberate exclusions.
  • The associated-domains entitlement is present in the shipped build.
  • You have tested a real-device install, and allowed time for Apple's cache after any edit.

Re-run the full list after any domain change, Team ID change, or app rebuild. Our deep link QA checklist folds this into a wider pre-launch routine. Platforms like Linkrunner host and maintain the AASA file on a branded subdomain so teams do not hand-edit it before every change.

Frequently asked questions

Where do I host the apple-app-site-association file?

At https://yourdomain/.well-known/apple-app-site-association, served over HTTPS, with a 200 response and no redirect.

Why are my Universal Links opening Safari instead of the app?

Almost always because iOS could not validate the association: the file is unreachable, redirected, served with the wrong content-type, has a malformed appID, or the associated-domains entitlement is missing from the app.

Does the AASA file need a .json extension or a specific content-type?

No extension. Serve it as application/json. An incorrect content-type or an added .json extension is a common reason iOS rejects the file.

How long do AASA file changes take to propagate?

Not instantly. Apple fetches the file through a cached CDN at install time, so edits may not reach already-installed apps or fresh installs immediately. Make changes ahead of launches, not at the last minute.

The takeaway

Universal Links almost never fail because of clever code; they fail because of a small detail in one JSON file: a wrong Team ID, a stray redirect, the wrong content-type, a missing entitlement, or Apple's cache not yet refreshed. Get the structure right, host it strictly, test on a real device, and respect the cache, and links will open the app reliably. Then pair the file with deferred deep linking so the open is also measured.

If you would rather not hand-maintain the AASA file and its caching quirks, request a demo from Linkrunner and run the pre-launch checklist above against your current setup first.

Start measuring the installs your team cares about

Bring attribution, deep links, SKAN, cohorts, and campaign intelligence into one workflow your growth team can trust.