Deep Linking - Technical Documentation
For Marketing/Non-Technical Users: See Deep Linking Usage Guide for how to create and use deep links.
Overview
This document provides technical implementation details for deep linking in the Eli Health ecosystem. The system supports Universal Links (iOS) and Custom URL Schemes for seamless app navigation from emails, SMS, and marketing campaigns.
Note: Eli Health currently only has an iOS app. Android users see fallback pages served by the backend.
Key Features
- Automatic App Opening (iOS): Links open directly in the app when installed
- Backend Fallback Pages: Professional landing pages when app is not installed
- Campaign Attribution: UTM parameters automatically tracked for marketing analytics
- Password Reset: Secure password reset flows via email links (mobile-only)
- Sign-up Links: Direct users to sign-up with campaign tracking
How It Works
Signup Flow
Password Reset Flow
User Experience Summary
Signup Links
- iOS with app: Pop-up → Allow → App opens → Signup screen
- iOS without app: Pop-up → Error → Fallback page → Download → Retry → Success
- Android: Fallback page → Download instructions
Password Reset Links
- iOS with app on mobile: Pop-up → Allow → App opens → Reset screen
- iOS without app on mobile: Pop-up → Error → Fallback page → Download → Retry → Success
- Android on mobile: Fallback page → Download instructions
- Desktop (any OS): Fallback page with warning to use mobile device
Important for Password Reset: Users MUST click the reset link on the same mobile device where they requested the reset. Desktop links will show a warning.
Supported Routes
| Route | Purpose | Notes |
|---|---|---|
/signup | User registration | Captures campaign data |
/register | User registration | Alias for /signup |
/reset-password | Password reset | Mobile device only |
/shopify/callback | Shopify OAuth callback | Handles OAuth redirect from Shopify |
URL Formats by Environment:
- Production:
https://app.eli.health/signup - Development:
https://dev.eli-app.com/signup - Staging:
https://staging.eli-app.com/signup - Custom scheme (testing):
eli://signup
Campaign Tracking
Marketing Link Format
Production:
https://app.eli.health/signup?utm_source=SOURCE&utm_medium=MEDIUM&utm_campaign=CAMPAIGN&campaign_id=ID
Development/Testing:
https://dev.eli-app.com/signup?utm_source=SOURCE&utm_medium=MEDIUM&utm_campaign=CAMPAIGN&campaign_id=ID
Supported Parameters
| Parameter | Description | Example |
|---|---|---|
utm_source | Traffic source | instagram, facebook, email |
utm_medium | Marketing medium | social, email, cpc |
utm_campaign | Campaign name | summer_2024 |
campaign_id | Campaign identifier | IG_SUMMER_001 |
Examples
# Email campaign
https://app.eli.health/signup?utm_source=newsletter&utm_medium=email&utm_campaign=monthly_may
# Instagram bio
https://app.eli.health/signup?utm_source=instagram&utm_medium=social&utm_campaign=bio_link
# Facebook ad
https://app.eli.health/signup?utm_source=facebook&utm_medium=cpc&utm_campaign=spring_sale&campaign_id=FB_AD_456
Campaign Data Flow
Key Points:
- Campaign data captured from URL parameters
- Stored locally until signup completion
- Sent to Firebase Analytics with
account_createdevent - Available as user properties for cohort analysis
Technical Implementation
Backend Fallback Pages
Location: eli-backend-api/src/modules/
- Signup:
deep-links/signup.controller.ts - Password Reset:
reset-password/reset-password.controller.ts - Shopify OAuth:
deep-links/shopify-callback.controller.ts
Features:
- Branded Eli Health logo (base64 PNG)
- Responsive design with Eli design system colors
- Automatic app launch attempt via custom URL scheme
- Clear instructions and download button
- Works on all platforms (iOS, Android, Desktop)
Signup Page (/signup, /register):
Title: "Join Eli Health"
Message: "You should have received a pop-up to open the app..."
Action: Opens eli://signup → Falls back to App Store link
Password Reset Page (/reset-password):
Title: "Password Reset Required"
Warning: "Must open on same mobile device where reset was requested"
Message: "You should have received a pop-up..."
Action: Opens eli://reset-password → Falls back to App Store link
Note: All deep linking is handled by the backend. No Cloudflare Workers or Shopify configuration needed. AASA file is still served for iOS universal links.
iOS Configuration
1. Entitlements File
The production entitlements file (Eli.Production.Release.entitlements) includes:
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:eli.health</string>
</array>
2. Custom URL Scheme
Configured in Info.plist:
<key>CFBundleURLSchemes</key>
<array>
<string>eli</string>
</array>
3. Apple App Site Association (AASA)
Must be served from the web server at:
https://eli.health/.well-known/apple-app-site-associationhttps://eli.health/apple-app-site-association
Example AASA file:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "XS3FBW645N.health.eli.Eli",
"paths": ["/signup", "/register", "/reset-password"]
}
]
}
}
Important: Serve with Content-Type: application/json header.
Mobile App Code
Location: eli-app/src/shared/UniversalLinkHandler.tsx
Handles:
- URL parsing (both
eli://andhttps://eli.health/) - Campaign data storage (AsyncStorage)
- Navigation routing
- App lifecycle events
Adding New Routes:
- Update
UniversalLinkHandler.tsxwith new path logic - Update AASA file paths array
- Deploy AASA to server
- Test on physical device
Testing
Quick Test Guide
iOS Physical Device:
- Send test link via iMessage:
https://dev.eli-app.com/signup?utm_source=test - Tap link → verify app opens
- Check Firebase Analytics for campaign data
iOS Simulator:
Use custom scheme: eli://signup?utm_source=test
Android Device: Open link → verify backend fallback page displays
Fallback Page Test:
- Uninstall app
- Click link (use dev/staging URL) → verify fallback page with logo and download button
- Reinstall app and retry
Campaign Attribution:
Firebase Console → Analytics → Events → Look for account_created
Troubleshooting
Links Not Opening App
- Check AASA: Visit
https://app.eli.health/.well-known/apple-app-site-association - Validate: Use Apple's validator
- Clear Cache: Uninstall app → Restart device → Reinstall
- Test Method: Don't type in Safari address bar - send via Messages/Email
Campaign Data Missing
- Check console logs for
📱 [DeepLink]and✅ [Campaign] - Verify Firebase Analytics integration
- Allow 24-48 hours for data to appear in Firebase
Password Reset Issues
- Must use mobile device where reset was requested
- Check Firebase email template includes correct URL format
- Verify
oobCodeparameter is present in URL
Best Practices
Marketing
- Always include UTM parameters (minimum:
utm_source,utm_medium) - Use consistent naming: lowercase with underscores (
summer_promo_2024) - Test before launch: Verify on iOS and Android, with and without app
- Track performance: Use unique
campaign_idper campaign
Development
- Test after changes: Always verify deep links still work
- Preserve campaign data: Don't clear AsyncStorage prematurely
- Update AASA: When adding routes, update AASA file and clear CDN cache
- Monitor logs: Look for
📱 [DeepLink]and✅ [Campaign]prefixes
Reference
Related Code:
- Backend fallback pages:
eli-backend-api/src/modules/deep-links/,eli-backend-api/src/modules/reset-password/ - App handler:
eli-app/src/shared/UniversalLinkHandler.tsx - Tests:
eli-app/src/__tests__/shared/universal-link-handler-test.ts
External Resources: