Skip to main content

Implementing Deep Linking and Universal Links

Property Description Values Notes
deeplinks Defines deep link configurations Array<Object> Required for deep linking support
urlScheme URL scheme for deep links string Must be unique per app
path Path to match for deep link string Can use regex patterns
component Component to load when matched string Must be a valid component reference
import { defineCustomElements } from '@ionic/core/loader';

defineCustomElements();

const deeplinks = [
  {
    url: 'myapp://profile/:id',
    component: 'app-profile-page'
  },
  {
    url: 'myapp://settings',
    component: 'app-settings-page'
  }
];

export { deeplinks };
Note: Deep links require proper configuration in both app and platform-specific manifest files (e.g., AndroidManifest.xml, Info.plist).
Step Description Action
1 Configure App ID Enable Associated Domains in Apple Developer Portal for your App ID.
2 Create Apple App Site Association (AASA) file Host the AASA file at https://yourdomain.com/.well-known/apple-app-site-association.
3 Update Info.plist Add Associated Domains to your app's Info.plist.
4 Implement in Ionic Use cordova-plugin-ionic-webview to handle deep links.

Example: Info.plist Configuration

<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:yourdomain.com</string>
</array>
Note: The AASA file must be served over HTTPS with a valid SSL certificate.
Warning: Ensure the AASA file is correctly formatted JSON and matches your app's bundle ID.
Step Description Action
1 Configure App Links in AndroidManifest.xml Add intent filters to handle deep links
<intent-filter>
  <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>
2 Create asset links file Place .well-known/assetlinks.json at root of your domain
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.yourapp.android",
    "sha256_cert_fingerprints": ["YOUR_APP_SHA256_FINGERPRINT"]
  }
}]
3 Generate SHA256 fingerprint Run command to get SHA256:
keytool -list -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
4 Test App Links Use adb shell am start or Google App Links Assistant
adb shell am start -W -a android.intent.action.VIEW -d "https://yourdomain.com/path" com.yourapp.android
Note: Ensure your domain's SSL certificate is valid and properly configured for App Links to work correctly.
import { Deeplinks } from '@ionic-native/deeplinks/ngx';

constructor(private deeplinks: Deeplinks) {}

ionViewDidLoad() {
  this.deeplinks.routeWithDeepLinks({
    '/user/:id': 'UserPage',
    '/product/:id': 'ProductPage'
  }).subscribe((match) => {
    console.log('Matched:', match);
  }, (nomatch) => {
    console.log('No match:', nomatch);
  });
}
Route Description Parameters Notes
/deep-link/:id Handles deep links with a dynamic ID parameter :id Used for routing to specific content based on ID
/deep-link/:category/:id Handles deep links with category and ID :category, :id Allows for hierarchical content navigation

Example: Route Configuration

import { RouteConfig } from '@ionic/angular';

const routes: RouteConfig[] = [
  {
    path: 'deep-link/:id',
    component: ContentPage
  },
  {
    path: 'deep-link/:category/:id',
    component: CategoryContentPage
  }
];
Note: Ensure that your route configuration matches the structure of your deep links to properly handle navigation.
Parameter Type Description Example
url string The deep link URL to parse ionic://myapp/somepage?param1=value1&param2=value2
queryParams object Object containing parsed query parameters { param1: 'value1', param2: 'value2' }
path string The path component of the URL /somepage
import { parseUrl } from '@ionic/utils';

const url = 'ionic://myapp/somepage?param1=value1&param2=value2';
const parsed = parseUrl(url);

console.log(parsed.path); // /somepage
console.log(parsed.queryParams); // { param1: 'value1', param2: 'value2' }
Note: The parseUrl utility is part of the @ionic/utils package and provides a standardized way to parse deep links across platforms.

6. Implementing Custom URL Schemes

Property Description Example
scheme Custom URL scheme used to open the app myapp://
host Host part of the URL scheme (optional) myapp://home

Example: Configuring Custom URL Scheme in Ionic

import { registerPlugin } from '@capacitor/core';
import { App } from '@capacitor/app';

const handleOpenUrl = (url: string) => {
  console.log('URL opened:', url);
};

App.addListener('appUrlOpen', handleOpenUrl);

// Register custom scheme
registerPlugin({
  name: 'CustomUrlScheme',
  platforms: ['ios', 'android'],
  // Implementation details...
});
Note: Custom URL schemes are supported on both iOS and Android but require platform-specific configuration.
Warning: Ensure that your custom scheme does not conflict with existing app schemes.
Scheme Platform Status
myapp:// iOS Supported
myapp:// Android Supported
// Test deep link navigation in Ionic app
import { TestBed } from &#x27;@angular/core/testing&#x27;;
import { Router } from &#x27;@angular/router&#x27;;
import { DeepLinker } from &#x27;@ionic/angular&#x27;;

describe(&#x27;Deep Link Testing&#x27;, () => {
  let router: Router;
  let linker: DeepLinker;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [IonicModule.forRoot()],
      providers: [DeepLinker]
    });
    router = TestBed.inject(Router);
    linker = TestBed.inject(DeepLinker);
  });

  it(&#x27;should navigate to correct route&#x27;, () => {
    const url = &#x27;/user/123/profile&#x27;;
    const route = linker.getRouteFromPath(url);
    expect(route).toBe(&#x27;/user/:id/profile&#x27;);
  });
});
Test Type Description Tools
Unit Testing Testing individual deep link logic with mocks Jest, Angular Testing
Integration Testing Testing deep link navigation with actual router Cypress, Playwright
End-to-End Testing Testing deep links in real app environments E2E with Capacitor
  1. Set up test environment with TestBed
  2. Create mock router and deep linker instances
  3. Define test URLs and expected routes
  4. Assert route matching behavior
  5. Run tests with npm test
Note: Ensure deep link paths match the defined routes in your Ionic app configuration.
Warning: Deep link testing requires proper URL encoding to avoid path mismatches.
Property Description Default Value Notes
deferredDeepLink Flag to enable handling of deferred deep links false Set to true to enable deferred deep link support
deepLinkPath Path to navigate when a deferred deep link is received null Used to define the route in the app for deferred links
import { IonicConfig } from '@ionic/angular';

const config: IonicConfig = {
  deferredDeepLink: true,
  deepLinkPath: '/app/deep-link'
};

export default config;
Note: Deferred deep links are handled after the app is launched and may require additional setup in your app's routing module.

9. Using Branch.io Integration

Example: Setting up Branch.io with Ionic

// Install Branch SDK
npm install branch-sdk

// Import in app.module.ts
import { Branch } from 'branch-sdk';

// Initialize in app.component.ts
Branch.init('key_live_xxx');

// Handle deep link
Branch.subscribe((data) => {
  console.log('Deep link data:', data);
});
Feature Description Support
Branch.init() Initialize Branch SDK with your app key NEW v5.0+
Branch.subscribe() Listen for deep link events Stable
Branch.setIdentity() Set user identity for tracking NEW v5.1+
Note: Ensure your app is configured for Universal Links (iOS) or App Links (Android) in Branch dashboard.

Branch.io vs Native Deep Linking

  • Branch.io: Cross-platform, analytics, fallback handling
  • Native: Platform-specific, no third-party dependency
import { Plugins } from '@capacitor/core';

const { App } = Plugins;

App.addListener('appUrlOpen', (event) => {
  console.log('Deep link opened:', event.url);
  // Log the full URL and any query parameters
});

App.addListener('appRestoredResult', (event) => {
  console.log('App restored from background:', event);
});
Issue Possible Cause Solution
Deep link not opening app URL scheme not registered in app Verify CFBundleURLTypes in Info.plist (iOS) or intent-filter in AndroidManifest.xml
Deep link opens app but not to correct page Incorrect route mapping in app Ensure deep link paths match Ionic route configuration
App crashes on deep link Missing or invalid URL parameter Add error handling and validation for URL parameters
Universal Links not working on iOS Associated Domains not configured Verify associated-domains entitlement and Apple App Site Association file
Note: Use capacitor.config.json to define URL schemes and universal links.

Debugging Steps

  1. Check that the deep link URL is correctly formatted
  2. Verify app registration for the URL scheme or domain
  3. Use device logs to trace deep link handling
  4. Test with ionic serve and ionic capacitor run
  5. Validate URL parameters in app logic

Was this article helpful?