How to Alert on Broken Universal Links and Android App Links
Learn how to monitor association files and installed-app taps, distinguish browser fallback from wrong-screen bugs, and use Airbridge with scheduled alerts.

The practical answer: monitor both the association and the tap.
- Check each production domain’s AASA or
assetlinks.jsonfile on a schedule.- Run an installed-app tap test on iOS and Android, then verify the expected screen opens.
- Alert separately on a broken file, a failed app-opening test, and an app that opens to the wrong route.
- Use Airbridge to configure and test deep links; use a separate scheduled monitor for recurring checks and alert delivery.
A link that opens in a browser when the app is installed is a different failure from a link that opens the app and lands on the wrong screen. A file check catches many association problems, while a device tap test checks the behavior your user actually sees. Set up both checks for each production domain, then make an alert identify which layer failed.
1. Separate browser fallback from a wrong-screen bug
Start by identifying what happened after the tap. A browser fallback means the operating system handled the URL as a website link instead of opening the installed app. A wrong-screen result means the app opened, but its own link-handling code routed the URL to the wrong place.
Apple’s Universal Links setup guide requires a two-way website-app association and app code that handles the user activity delivered when a link opens the app. Once the app receives a tapped URL, its handler chooses how to respond, so a successful app launch followed by the wrong screen points to app-level route parsing or navigation.
Android’s App Links troubleshooting guide identifies the browser opening instead of the app, or a disambiguation prompt appearing, as an association or verification symptom. Apple also says that a link to a website opens in Safari when the app is not installed, which is expected website fallback behavior. For this guide’s alert, test with the app installed and distinguish that case from a broken app route.
Record the observed outcome in three separate categories:
- Browser opened: the app was installed, but the link remained in the browser. Investigate domain association, app identity, supported URL rules, and the device’s link preference.
- App opened, wrong destination: association and handoff likely worked. Investigate the app’s URL parser, route table, login state, and navigation behavior.
- App did not open, test could not tell where the URL went: treat this as an inconclusive test result. Collect the device and test-run details before paging a developer for an app defect.
2. Build a domain-to-app inventory
Before writing a monitor, create one expected-configuration record for every production hostname that appears in a user-facing link. Include Apple’s Apple App Site Association (AASA) file or Android’s assetlinks.json file for each exact host. Treat example.com and www.example.com as separate hosts if links can use both.
Apple’s associated-domains documentation says to create a file named apple-app-site-association, without a file extension, and to list Universal Link app identifiers in the applinks service. The file is served from either the domain root or /.well-known/. Apple’s Universal Links programming guide describes the app identifier as the Team ID or app ID prefix followed by the bundle ID. Record the value that matches the production app’s signed identity, not merely a developer’s local project name.
For each Apple host, store:
- The exact hostname, including whether it uses
www. - The AASA URL at the root or
/.well-known/apple-app-site-association. - The production Team ID or app ID prefix and bundle ID expected in the association.
- The URL paths or components the production app is meant to handle.
- The production app version or release channel used for the device test.
Android uses a different file and identity. Android’s website-association setup guide specifies /.well-known/assetlinks.json. Its records identify an Android package using package_name and the signing identity using sha256_cert_fingerprints. Add the production application ID and the SHA-256 fingerprint for the certificate that signs the production app. The Digital Asset Links prerequisites describe the delegate_permission/common.handle_all_urls relationship used to enable Android App Links.
For each Android host, store:
- The exact hostname and its
https://<host>/.well-known/assetlinks.jsonURL. - The production application ID, also called the package name in the association file.
- Each signing-certificate SHA-256 fingerprint used for the production distribution you support.
- The URL patterns in the app’s intent filters and, where used, its Android 15+ dynamic link rules.
- The Android versions and signed app builds represented in the tap test.
Publish the Android association file on every host your app supports. Android explicitly requires a file on each supported host. The same principle makes a host-by-host inventory useful on iOS: a correct record at the apex domain says nothing about a separate www domain unless that host also serves the intended association.
Keep production and staging identities distinct in the inventory. A staging package, an internal signing certificate, or a test-only iOS bundle ID can make a development tap work while the public production app remains unmatched. During review, compare the association entries to the identity in the app build that users install.
3. Automate checks for changes to association files
Run a recurring check against the exact association URL for each host. The monitor should request the file over HTTPS without following redirects, retain the response metadata, parse the JSON, and compare the relevant values with the expected configuration you recorded in the previous step.
For Apple, check that the exact AASA endpoint returns the file directly, that its body parses as JSON, and that the applinks section still names the expected app identifier and intended URL rules. Apple’s file requirements specify the root or /.well-known/ location, HTTPS, and no redirects. For apps running iOS 9.3.1 or later, Apple’s archived guide sets a 128 KB maximum for the uncompressed file. Keep that limit in the check if your app supports those versions.
For Android, check that assetlinks.json is available over HTTPS with no redirect, parses as JSON, and contains the intended relation, package name, and signing-certificate fingerprint. Android’s setup guide says a 301 or 302 redirect does not meet its file requirement. Its troubleshooting instructions also flag redirects from HTTP to HTTPS and from a non-www domain to www as possible verification failures. Request the canonical association URL directly rather than treating a redirect to a working copy as a passing result.
The status code, content type, parsed body, and identity comparison answer different questions. A server can return a success status with an HTML error page, serve valid JSON for the wrong package, or preserve the app identity while accidentally removing a path rule. Store those results separately so the notification says whether the file could not be fetched, could not be parsed, or no longer matches the approved configuration.
Use a controlled expected configuration rather than alerting on every byte change. A JSON reformat or harmless key ordering change can alter the file while leaving its meaning intact. Compare the fields that affect association, and send a review alert when those values change. If your deployment process intentionally updates a fingerprint or URL rule, update the expected record alongside the release so the monitor can distinguish an approved change from an unexplained one.
A scheduled endpoint check reads the association file currently served by the website. On iOS 14 and later, Apple’s Universal Link debugging note says its CDN retrieves and caches the AASA file, and devices check for updates about once a week after app installation. After changing an AASA file, run an installed-device tap test to check the behavior on a device.
4. Run a scheduled tap test on real devices
Schedule an installed-app canary that taps an HTTPS Universal Link or App Link and records which app opens and whether it reaches the intended screen. Use a physical device or a device-testing environment that can report the resulting app and screen, and retain the URL used for the test.
Build a small set of stable test links that represent important route patterns, such as a subscription offer, an account page, and a campaign landing screen. Use safe test accounts and test content so the canary does not start a purchase or create production user activity. Include every distinct production host and any routing pattern whose failure would block a core task. The team chooses the run frequency based on how quickly it needs to detect a regression and how much test-device operation it can maintain.
For each platform, make the tap originate in a context that behaves like a user tapping an ordinary web link. On iOS, Apple’s TN3155 recommends pasting a link into Notes and long-pressing it to inspect the app and browser options. The note also provides a Universal Links diagnostic in Developer settings: enable Developer Mode, turn on Associated Domains Development, open Diagnostics, and enter the full URL. That diagnostic reports whether the link is valid for an installed app.
For Android, first verify the operating system’s recorded domain state, then perform a tap. Android’s verification guide documents adb shell pm get-app-links PACKAGE_NAME for reviewing verification results. A scheduled device test should still open the link and confirm which app and route appeared.
Use an installed app for the association canary. Apple’s Universal Link documentation says that when the app is absent, iOS opens the URL in the user’s default browser, so test installed-app association on a device with the app installed. If you also need to test deferred deep linking or installation flows, keep those as a separate test case with its own expected result.
Apple’s user choice can affect a test result: its TN3155 says that selecting the app or browser option sets the device’s default behavior for future Universal Links from that domain. Keep the test device’s choice known and repeatable. When a device opens a link in a browser, record whether the user previously selected browser handling before treating the result as an association regression.
A useful canary run records the platform, OS version, app build, install state, domain, full test URL, start time, final app or browser, and expected versus actual screen. Capture a screenshot or a short test artifact when the device framework supports it. Those fields turn “deep links are broken” into a test that another developer can reproduce.
5. Choose alert conditions that give the team a next action
Create separate alert types for endpoint configuration and device behavior. An endpoint alert means the association file failed a delivery, parsing, or expected-identity check. A canary alert means a tap did not produce the expected app and destination on a named device configuration. A wrong-screen alert means the app did open but produced a different route.
| Signal | Example condition | What the alert tells the on-call developer |
|---|---|---|
| Association endpoint | Expected file returns an error, redirects, fails JSON parsing, or changes an approved app identity or rule | Inspect the named host’s response, deployment, and expected configuration |
| App-opening canary | An installed-app tap opens a browser, shows a chooser unexpectedly, or fails to launch the production app | Check domain verification, app identity, OS state, and user link preference |
| Route canary | The production app opens, but the test URL does not reach its expected screen | Check the URL handoff and app route handler rather than starting with DNS or the association file |
| Test-run health | Device offline, app unavailable, test timed out, or result could not be observed | Restore the test runner or repeat the check before declaring a customer-facing link failure |
A single failed device run can be transient, so set the evaluation window to match the canary schedule and your incident tolerance. Prometheus’s alerting rules activate a rule on its first evaluation without a for clause; with for, the condition must remain active for the configured duration before the alert fires. A short pending period selected by your team can filter a brief device hiccup while still surfacing a persistent failure quickly.
Apply that delay to unstable device-run results, not automatically to a serious configuration event. If the production file is returning an error or the production identity disappears, a team may want an immediate notification. If a single scheduled device is sometimes unavailable, require a repeated failure or a second confirming run. Set those conditions from the reliability of your own test service and the customer impact of the affected routes; there is no universal failure percentage that fits every app.
Group notifications by the smallest useful incident boundary, such as platform, host, and check type. If three URLs on the same iOS host fail for the same AASA change, one incident with the affected URLs is more actionable than three identical pages. Keep Android and iOS failures distinct because their files, signing identities, and verification steps differ.
Include enough context that the first notification can start the diagnosis:
- Platform, host, full test URL, and check type.
- App version or build number, OS version, install state, and device or runner identifier.
- Expected outcome, observed outcome, and timestamp with timezone.
- For file checks, response status, redirect target if present, content type, parse result, and which expected identity or rule differed.
- A link to the failed test artifact, the relevant deployment, and the runbook for that platform.
A useful alert says, for example, “iOS tap test for links.example.com opened Safari instead of app build 214 at 14:05 UTC; AASA endpoint passed at 14:04 UTC.” That message directs the developer to device verification and user preference first, while preserving the file check’s independent result. If the same test says the app opened to the wrong route, send the developer to the app’s route handler instead.
6. Use Airbridge for link setup and validation, then add scheduled monitoring
Airbridge Core includes direct and deferred deep linking, plus a tracking link manager, API, and testing console. Airbridge’s deep-link testing guide describes tests for an app that is already installed, including Universal Links or App Links and tracking links created with a custom domain. Its console also has a test scenario for an app that is not installed.
That makes Airbridge relevant when your team is configuring a link, checking a specific deep-link path, or validating a custom-domain tracking link. Run the appropriate installed-app test while setting up the link and use the console’s result to check that the intended deep-link test completed. If the app is not installed and your task is to test deferred deep linking, use that separate scenario and its own expected result.
For recurring operations, add a scheduled configuration monitor and device canary as separate pieces of your app’s monitoring setup. Airbridge’s documented link setup and testing tools support configuring and testing links; the recurring checks and alert delivery in this guide belong to the monitoring service your team chooses. Keep the outcome boundaries clear: a manual or console link test helps validate a link at test time, while scheduled checks tell you when a later file change or device regression occurs.
A small subscription-app team can keep this lightweight. Start with the production domains that receive paid-campaign traffic, the actual production app identities, and one installed-app canary per supported platform. Add route coverage as your app introduces more high-value destinations. If your links also lead through a subscription platform such as RevenueCat, Adapty, or Superwall, keep that billing configuration separate from the OS association check; this alert is about whether the app receives and routes the URL.
7. Triage the alert and prove the repair
Use the alert’s check type to start with the failing layer, then rerun both kinds of checks after a fix.
- Classify the failed layer. Start with the notification’s observed outcome. A file response error points to the host or deployment. A browser result points to domain association or device link preference. An app opening to the wrong screen points to route handling. A timeout points to the test runner.
- Use the failing URL’s hostname to select that host’s association record and expected app identity.
- Restore the expected association response for the affected host. Compare HTTPS delivery, redirect behavior, JSON response, and association contents with the platform’s requirements. Inspect the proxy, CDN, deployment, or access rule that serves the file when its response differs. For Android, match
package_nameand the signing certificate’s SHA-256 fingerprint inassetlinks.json. For iOS, match the Team ID or app ID prefix and bundle ID in theapplinkssection, along with the intended URL rules. - Refresh the iOS association on a test device. Reinstall the app to download a newer AASA file; Apple’s debugging note says there is no direct CDN invalidation option.
- Android’s verification guide uses
adb shell pm get-app-links PACKAGE_NAMEto report domain verification results. For updated dynamic rules on Android 15 or later, runadb shell pm verify-app-links --re-verify PACKAGE_NAMEto force a re-fetch, as documented in Android’s troubleshooting guide. Use the production app’s exact package name in the command. - For an app that opens to the wrong screen, inspect route handling. Log the URL delivered to the app, then compare its path and parameters with the route the app expects. Apple’s Universal Links guide says iOS delivers a tapped Universal Link as an
NSUserActivitywith the typeNSUserActivityTypeBrowsingWeb. Log the URL at the handoff and after parsing so the team can see whether the error occurred before or after route selection. - Prove recovery with the production app identity. Repeat the endpoint check and installed-app tap using the intended production domain and a production-signed build. Confirm the correct app opened, the expected screen appeared, and the alert condition cleared. Retain the failing and passing run artifacts with the deployment or app release that introduced the repair.
On Android 17 and later, adb shell am start --debug-link -a android.intent.action.VIEW -d "<URL>" shows candidate apps and the manifest or dynamic assetlinks.json rules that match a specific URL, according to Android’s App Links testing guide.
Keep a compact regression record for each incident: the original URL, the exact host, the failed signal, the relevant AASA or asset links response, production app identity, device and OS, root cause, and passing retest. The same record helps catch a later certificate rotation, hostname change, app bundle change, or route refactor before customers report browser fallback.
FAQ
Can a successful association-file check prove that every deep link works?
No. It confirms the web server is returning the expected association data. A device tap test is still needed to check operating-system handoff, and a route assertion is needed to confirm the app reached the right screen.
Should I alert when the app is not installed and the link opens in a browser?
No. Apple’s Universal Link documentation says the link opens in the default browser when the app is absent; run install and deferred-deep-link flows as a separate test with their own expected outcome. Apple says website links open in Safari when the app is not installed. Track install and deferred deep-link behavior as a separate flow with a separate expected result.
Does an Android verification status replace a real tap test?
No. adb shell pm get-app-links PACKAGE_NAME lets you inspect the verification result for the package. A tap test separately confirms the installed app opens from the test URL and reaches the intended route.
Can I use Airbridge as the scheduled alerting service?
Airbridge Core includes link setup and testing tools, including a testing console. Pair those with a separate scheduled configuration and device-monitoring service for recurring checks and alert delivery.
What should I include in the first alert?
Include the platform, hostname, URL, app build, OS version, observed result, time, and the file-check outcome. That lets the on-call developer tell a server-side association failure from a device handoff, app route, or test-runner problem.
Get Started Free
See how these criteria hold up on the real thing.


