Broken deep links silently kill conversion rates. A user taps a link in an email, a push notification, or a social post – and instead of landing on the right product page inside your app, they hit a 404 screen, get dumped on the home screen, or worse, see nothing at all. Deep link troubleshooting is one of the most underestimated disciplines in mobile app development, yet it directly impacts retention, paid campaign ROI, and user experience.
This guide walks development teams and technical decision-makers through every major failure category, root cause analysis, and fix – platform by platform.
Why Deep Link Troubleshooting Matters for Mobile Business
Before diving into technical fixes, the business case is important to understand. According to Branch's Mobile Growth Report, apps with properly functioning deep links achieve 2x higher retention rates and up to 3x better campaign conversion compared to apps that fall back to a generic home screen.
The cost of broken links adds up quickly:
- Paid UA campaigns route users via tracked deep links – a broken link wastes every cent of that budget
- Email re-engagement flows rely on deep links to take users directly to the content referenced in the message
- App Store re-engagement ads depend on deferred deep linking to maintain context after install
- Cross-platform journeys (web-to-app, desktop-to-mobile) break entirely when Universal Links or App Links fail silently
Deep link troubleshooting is therefore not purely a developer concern – it affects product, growth, and finance teams equally.
The Core Categories of Deep Link Troubleshooting
Deep link errors fall into five broad categories. Understanding which category applies to your issue reduces debugging time significantly.
1. Configuration Errors
These are the most common source of failures and include:
- Missing or malformed apple-app-site-association (AASA) file on iOS
- Missing or misconfigured assetlinks.json file on Android
- Wrong bundle ID or package name in the configuration file
- HTTPS not enforced on the hosting domain
- File served with wrong Content-Type header (must be `application/json`)
2. Routing Errors
These occur when the link opens the app but routes to the wrong screen:
- URI scheme handled by the wrong Activity or ViewController
- Missing intent filter in AndroidManifest.xml
- Regex pattern in route definitions too narrow or too broad
- Deep link parameters stripped or URL-encoded incorrectly
3. Fallback Errors
When the app is not installed, the link should redirect to the App Store or Play Store – or to a web fallback. Common failures here include:
- Fallback URL pointing to a non-existent page
- User-agent detection logic on the server sending mobile users to the desktop site
- Deferred deep link state not preserved after install
4. Platform-Specific Failures
iOS and Android each have distinct behaviours that require platform-specific deep link troubleshooting:
- iOS Safari sometimes bypasses Universal Links in favour of the web URL (especially after a long-tap or redirect chain)
- Android Chrome may not trigger App Links when the domain fails verification
- WebViews on both platforms frequently ignore Universal Links and App Links entirely
5. Third-Party Attribution SDK Conflicts
If you use a Mobile Measurement Partner (MMP) such as Adjust, AppsFlyer, or Singular, the deep link handling chain becomes more complex. SDK version mismatches, misconfigured redirect chains, or missing `onDeepLink` callbacks are frequent culprits.
Deep Link Troubleshooting on Android: Step-by-Step
Android App Links rely on Digital Asset Links verification. Here is a structured debugging workflow:
Step 1 – Verify your assetlinks.json
Navigate to `https://yourdomain.com/.well-known/assetlinks.json` in a browser. The file must:
- Return HTTP 200
- Be served as `application/json`
- Contain the correct SHA-256 fingerprint of your signing certificate
Use the Google Digital Asset Links API to run an automated verification.
Step 2 – Check intent filters in AndroidManifest.xml
Every deep-linkable screen must have:
xml
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="yourdomain.com" />
</intent-filter>
Missing `android:autoVerify="true"` is one of the most common deep link troubleshooting findings in Android apps.
Step 3 – Test with ADB
bash
adb shell am start -W -a android.intent.action.VIEW \
-d "https://yourdomain.com/product/123" com.yourapp.package
If this opens the app correctly but a real link does not, the issue is likely in the App Links verification flow, not your routing code.
Step 4 – Check verification status on device
bash
adb shell pm get-app-links com.yourapp.package
Look for `verified` status. Any domain showing `none` or `legacy_failure` needs further investigation.
Common Android Fixes
- Regenerate your SHA-256 fingerprint after a new signing key is introduced
- Add all subdomains explicitly – `www.yourdomain.com` and `yourdomain.com` are treated as separate origins
- Ensure your assetlinks.json is accessible without redirects (Android's verifier does not follow redirects)
Deep Link Troubleshooting on iOS: Step-by-Step
iOS Universal Links use the apple-app-site-association file. Apple caches this file aggressively, which means configuration changes can take time to propagate.
Step 1 – Validate your AASA file
Check `https://yourdomain.com/.well-known/apple-app-site-association` or `https://yourdomain.com/apple-app-site-association`. Use the Apple AASA Validator to identify formatting issues.
A valid AASA structure:
json
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.yourapp.bundle",
"paths": ["/product/*", "/category/*"]
}
]
}
}
Step 2 – Confirm Associated Domains entitlement
In Xcode, navigate to Signing & Capabilities → Associated Domains. Your domain must appear as `applinks:yourdomain.com`. Provisioning profiles must be regenerated after adding this entitlement.
Step 3 – Implement the correct AppDelegate/SceneDelegate handler
swift
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else { return false }
return handleDeepLink(url: url)
}
Missing or empty return values here silently break Universal Links on iOS.
Common iOS Fixes
- Force Apple to re-fetch your AASA: delete and reinstall the app on a real device (not simulator)
- Avoid redirect chains before the final Universal Link URL – Apple's CDN fetches the AASA only from the final destination domain
- Ensure your domain is not behind a VPN or IP whitelist that blocks Apple's crawlers
- For iOS 13+, implement the SceneDelegate equivalent handler alongside the AppDelegate one
Debugging Deferred Deep Links
Deferred deep linking preserves context across an app install. If a user does not have the app, they are sent to the store, install the app, and on first launch are routed to the originally intended screen. This mechanism is more complex to troubleshoot.
Key checks:
1. Attribution window: most MMP SDKs have a 24–72 hour attribution window. Links clicked outside this window will not trigger deferred deep link routing
2. Fingerprint matching: some platforms use device fingerprinting as a fallback when IDFA/GAID is unavailable – test on a device with tracking disabled
3. First-open callback: ensure the deferred deep link callback in your SDK integration fires before any navigation logic runs at startup
Test deferred deep linking with a clean install:
- Uninstall the app
- Click the campaign link
- Install from the store
- Verify the first screen on launch
Deep Link Troubleshooting Tools and Resources
A short toolkit every mobile team should have:
- Android: ADB, Google Statement List Debugger, Android App Links Assistant in Android Studio
- iOS: Apple Console logs, Charles Proxy for AASA fetch inspection, Xcode Instruments
- Cross-platform: Branch AASA Validator, Firebase Dynamic Links dashboard (if applicable), Postman for verifying JSON file headers
- Production monitoring: integrate deep link open events into your analytics pipeline – track `deep_link_open`, `deep_link_fallback`, and `deep_link_error` as distinct events
Building a Prevention Checklist
Reactive deep link troubleshooting is costly. A proactive pre-release checklist reduces incidents dramatically:
1. Verify assetlinks.json and AASA files on a staging domain before going live
2. Run ADB tests for all deep-linkable routes as part of your CI/CD pipeline
3. Test Universal Links on a physical iOS device – simulators do not process them
4. Validate fallback URLs return HTTP 200 and are mobile-optimised
5. Test on devices with the app not installed to confirm deferred deep link behaviour
6. Test across OS versions – behaviour changed significantly in Android 12+ and iOS 14+
7. Document all deep-linkable routes in a centralised schema registry
Adding automated deep link health checks to your CI/CD pipeline can catch regressions before they reach production. Even a simple cURL test verifying that your assetlinks.json and AASA files return the expected content and headers provides significant coverage.
When to Escalate: Structural vs. Configuration Problems
Some deep link failures point to structural issues in app architecture that cannot be fixed with simple configuration changes:
- Legacy URL scheme (`myapp://`) used instead of Universal Links or App Links – these are interceptable by other apps and non-verifiable
- Multiple apps sharing the same domain without a clear path-based routing strategy
- WebView-heavy architectures where deep links are expected to work inside embedded browsers
In these cases, the solution is architectural refactoring, not a config tweak. Identifying this distinction early saves weeks of misdirected debugging effort.
If your team is dealing with recurring deep link failures or planning a major app overhaul, professional guidance can significantly accelerate resolution. Explore more app development best practices on the Pilecode blog or reach out to our team to discuss your specific architecture.
Summary: Deep Link Troubleshooting Done Right
Effective deep link troubleshooting combines platform knowledge, structured diagnostics, and preventive engineering. The key takeaways:
- Start with configuration verification (assetlinks.json, AASA) before touching code
- Use platform-native tools (ADB, Xcode Console) before reaching for third-party debuggers
- Treat deferred deep linking as a separate, distinct system requiring its own test matrix
- Build prevention into CI/CD – do not rely solely on reactive bug reports
- Distinguish between configuration issues and structural architecture problems
A working deep link infrastructure is not a one-time setup task. It requires ongoing monitoring, especially after OS updates, signing certificate rotations, and domain changes. Teams that invest in systematic deep link troubleshooting consistently outperform those that treat it as an afterthought.
Ready to resolve persistent deep link issues in your app?
Schedule a free initial consultation →
Have questions about this topic? Get in Touch.