Deep Linking with Universal Links and App Links
Deep linking allows users to navigate directly to specific content within your mobile app from external sources like websites, emails, or other apps. This guide covers implementing deep links using Universal Links (iOS) and App Links (Android) with Expo Router.
Overview
Deep linking comes in three main forms:
- URL Schemes - Custom protocol URLs (e.g.,
myapp://profile/123) - Universal Links (iOS) - Standard HTTP(S) URLs that open the app when installed
- App Links (Android) - Android’s equivalent to Universal Links
Universal Links and App Links are preferred because they:
- Work seamlessly with web fallbacks
- Don’t require custom URL schemes
- Provide better user experience
- Are more secure and verified
Universal Links (iOS)
Universal Links allow iOS apps to handle standard HTTP(S) URLs. When a user taps a Universal Link, iOS opens the app directly if installed, or falls back to the website.
How Universal Links Work
- iOS checks if an app can handle the URL
- If the app is installed and configured, it opens the app
- If not, it opens the URL in Safari
- The app receives the full URL and can parse parameters
iOS Configuration
1. Associated Domains Entitlement
Add associated domains to your app configuration:
{
"expo": {
"ios": {
"associatedDomains": ["applinks:myapp.com", "applinks:www.myapp.com"]
}
}
}
2. Apple App Site Association File
Create /.well-known/apple-app-site-association in your website:
Important!
The file can’t have an extension. If you leave the.jsonextension, it won’t work as expected
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.yourcompany.yourapp",
"paths": ["/profile/*", "/product/*", "/share/*", "*"]
}
]
}
}
Please edit the following:
- Replace
TEAMIDwith your Apple Developer Team ID - Replace
com.yourcompany.yourappwith your app’s bundle ID - Change the list of paths for the ones used by your app that you want to deep link
App Links (Android)
App Links are Android’s implementation of verified deep links using standard HTTP(S) URLs.
How App Links Work
- Android checks for apps that can handle the URL
- Verifies the app’s association with the domain
- Opens the verified app directly
- Falls back to browser if no verified app is found
Android Configuration
1. Intent Filter Configuration
Add intent filters to your Android manifest:
Important!
Duplicate each item inside the data array to have both withwww.and without
{
"expo": {
"android": {
"intentFilters": [
{
"action": "VIEW",
"autoVerify": true,
"data": [
{
"scheme": "https",
"host": "myapp.com",
"pathPrefix": "/relative_path_to_screen"
},
{
"scheme": "https",
"host": "www.myapp.com",
"pathPrefix": "/relative_path_to_screen"
}
],
"category": ["BROWSABLE", "DEFAULT"]
}
]
}
}
}
2. Digital Asset Links File
Inside the public folder of your website, create /.well-known/assetlinks.json:
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.yourcompany.yourapp",
"sha256_cert_fingerprints": [
"SHA256_FINGERPRINT_OF_YOUR_SIGNING_CERTIFICATE"
]
}
}
]
Then:
- Replace
com.yourcompany.yourappwith your Android package name - Get SHA256 fingerprint from your signing certificate
- Add as many certificates as you need, usually the one from the key used to sign the APKs by EAS and the one used by Google itself to sign the build being released on the store.
Getting SHA256 Fingerprint
From EAS:
- Open the terminal and execute:
eas credentials -p android
- Select
productionenvironment - Copy the value for
SHA256 Fingerprint
From Google Play Console:
-
Sign in to Google Play Console and open your app.
-
In the left menu go to Release (or Test and release) → Setup → App integrity (sometimes labeled Play App Signing / App signing).
-
In the App signing key certificate section you’ll see the certificate fingerprints (MD5, SHA‑1, SHA‑256). Copy the SHA‑256 certificate fingerprint shown there.
Testing Website Configuration
Verify Apple App Site Association:
curl -I https://www.myapp.com/.well-known/apple-app-site-association
Verify Android Asset Links:
curl -I https://www.myapp.com/.well-known/assetlinks.json
Both should return 200 OK with Content-Type: application/json.
Testing Deep Links
iOS Testing
-
Simulator Testing:
xcrun simctl openurl booted "https://www.myapp.com/profile/123" -
Device Testing:
- Send the URL via Messages or Email
- Use Notes app to create a clickable link
- Test from Safari address bar
Android Testing
-
ADB Testing:
adb shell am start -a android.intent.action.VIEW \ -c android.intent.category.BROWSABLE \ -d "http://wwww.myapp.com/reset-password?token=test" -
Device Testing:
- Use Chrome browser to navigate to your URL
- Send via messaging apps
- Test from other apps that handle links
Best Practices
1. URL Structure Design
Keep URLs simple and intuitive:
https://www.myapp.com/profile/123
https://www.myapp.com/product/awesome-sneakers
https://www.myapp.com/share?type=post&id=456
2. Graceful Fallbacks
Always provide web fallbacks:
- Create corresponding web pages for all deep link URLs
- Implement Progressive Web App (PWA) features
- Add “Open in App” banners on web pages
Troubleshooting
Common iOS Issues
-
Links not opening app:
- Verify team ID and bundle ID in AASA file
- Check associated domains entitlement
- Ensure HTTPS and valid SSL certificate
-
AASA file not loading:
- Check file accessibility:
curl https://yoursite.com/.well-known/apple-app-site-association - Verify Content-Type header
- Check for redirects (not allowed)
- Make sure you are not using the
.jsonextension
- Check file accessibility:
Common Android Issues
-
App Links not verified:
- Check SHA256 fingerprint matches
- Verify package name in assetlinks.json
- Use
adb shell dumpsys package domain-preferred-apps
-
Intent filters not working:
- Ensure
autoVerify="true"is set - Check scheme and host configuration
- Verify BROWSABLE and DEFAULT categories
- Ensure
-
SendGrid updating the link sent by email:
- Disable the click tracking
Testing Tools
Useful Links
- Apple Universal Links Documentation
- Android App Links Documentation
- Expo Docs: Android App Links
- Expo Docs: iOS Univesal Links
Remember to test deep links thoroughly on both platforms and various scenarios. Keep your association files updated when changing domains or app configurations. Always provide graceful fallbacks for better user experience.