Skip to main content

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

  • 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
  • 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

RoutePurposeNotes
/signupUser registrationCaptures campaign data
/registerUser registrationAlias for /signup
/reset-passwordPassword resetMobile device only
/shopify/callbackShopify OAuth callbackHandles 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

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

ParameterDescriptionExample
utm_sourceTraffic sourceinstagram, facebook, email
utm_mediumMarketing mediumsocial, email, cpc
utm_campaignCampaign namesummer_2024
campaign_idCampaign identifierIG_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_created event
  • 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-association
  • https://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:// and https://eli.health/)
  • Campaign data storage (AsyncStorage)
  • Navigation routing
  • App lifecycle events

Adding New Routes:

  1. Update UniversalLinkHandler.tsx with new path logic
  2. Update AASA file paths array
  3. Deploy AASA to server
  4. Test on physical device

Testing

Quick Test Guide

iOS Physical Device:

  1. Send test link via iMessage: https://dev.eli-app.com/signup?utm_source=test
  2. Tap link → verify app opens
  3. 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:

  1. Uninstall app
  2. Click link (use dev/staging URL) → verify fallback page with logo and download button
  3. Reinstall app and retry

Campaign Attribution: Firebase Console → Analytics → Events → Look for account_created

Troubleshooting

  1. Check AASA: Visit https://app.eli.health/.well-known/apple-app-site-association
  2. Validate: Use Apple's validator
  3. Clear Cache: Uninstall app → Restart device → Reinstall
  4. Test Method: Don't type in Safari address bar - send via Messages/Email

Campaign Data Missing

  1. Check console logs for 📱 [DeepLink] and ✅ [Campaign]
  2. Verify Firebase Analytics integration
  3. 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 oobCode parameter 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_id per 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: