Implementing Deep Linking and Universal Links
1. Configuring Deep 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 |
Example: Deep Link Configuration
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).
2. Setting Up iOS Universal Links
| 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.
3. Setting Up Android App Links
| Step | Description | Action |
|---|---|---|
| 1 | Configure App Links in AndroidManifest.xml | Add intent filters to handle deep links |
| 2 | Create asset links file | Place .well-known/assetlinks.json at root of your domain |
| 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 Assistantadb 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.
Example: Handling Deep Links in Ionic
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);
});
}
4. Handling Deep Link Routes
| 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.
5. Parsing Deep Link Parameters
| Parameter | Type | Description | Example |
|---|---|---|---|
| url | string |
The deep link URL to parse | ionic://myapp/somepage?param1=value1¶m2=value2 |
| queryParams | object |
Object containing parsed query parameters | { param1: 'value1', param2: 'value2' } |
| path | string |
The path component of the URL | /somepage |
Example: Parsing Deep Link Parameters
import { parseUrl } from '@ionic/utils';
const url = 'ionic://myapp/somepage?param1=value1¶m2=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 |
7. Testing Deep Links
Example: Testing Deep Links in Ionic
// Test deep link navigation in Ionic app
import { TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
import { DeepLinker } from '@ionic/angular';
describe('Deep Link Testing', () => {
let router: Router;
let linker: DeepLinker;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [IonicModule.forRoot()],
providers: [DeepLinker]
});
router = TestBed.inject(Router);
linker = TestBed.inject(DeepLinker);
});
it('should navigate to correct route', () => {
const url = '/user/123/profile';
const route = linker.getRouteFromPath(url);
expect(route).toBe('/user/:id/profile');
});
});
| 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 |
Testing Deep Links Workflow
- Set up test environment with
TestBed - Create mock router and deep linker instances
- Define test URLs and expected routes
- Assert route matching behavior
- 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.
8. Handling Deferred Deep Links
| 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 |
Example: Configure Deferred Deep Link Handling
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
10. Debugging Deep Link Issues
Example: Logging Deep Link Events
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.