Adding Deep Linking Support
Deep links direct users to specific content within your app. When users tap a deep link on a device with your app installed, the app opens directly to the intended content, such as a product page or specific experience.
Singular tracking links support both standard deep linking (for installed apps) and deferred deep linking (for new installs). For comprehensive information, see the Deep Linking FAQ and Singular Links FAQ.
Requirements
Prerequisites
Complete the Singular Links Prerequisites to enable deep linking for your app.
Notes:
- This article assumes your organization is using Singular Links - Singular's tracking link technology. Older customers may be using legacy tracking links.
- Your app's deep link destinations need to be configured on the Apps page in Singular (see Configuring Your App for Attribution Tracking).
Implement Singular Links Handler
The SingularLink handler provides a callback mechanism to retrieve deep link, deferred deep link, and passthrough parameters from Singular tracking links when the app opens.
Available Parameters:
- Deep Link (_dl): The destination URL within your app for users clicking the link
- Deferred Deep Link (_ddl): The destination URL for users who install the app after clicking the link
- Passthrough (_p): Custom data passed through the tracking link for additional context
Platform Configuration
Configure native platform code to pass deep link data to the Singular SDK for attribution tracking and navigation.
Android Configuration
Update MainActivity
Enable the Singular SDK to process launch-related data and handle deep
links by modifying the MainActivity file to pass the
Intent object to the Singular SDK.
import singular_cordova_sdk.SingularCordovaSdk;
@Override
public void onNewIntent(Intent intent) {
SingularCordovaSdk.handleNewIntent(intent);
}
The Intent object contains information about how and why
your app was launched, which Singular uses for attribution tracking and
deep link navigation.
Location: Add this code to your main activity file,
typically located at
platforms/android/app/src/main/java/[your-package]/MainActivity.java
iOS Configuration
Update AppDelegate
Enable the Singular SDK to process launch-related data and handle deep
links by passing the launchOptions and
userActivity objects to the Singular SDK in your AppDelegate
file.
import UIKit
import SingularCordovaSdk
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var viewController: MainViewController?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Initialize window
window = UIWindow(frame: UIScreen.main.bounds)
// Configure view controller
viewController = MainViewController()
window?.rootViewController = viewController
// Initialize Singular SDK with launch options
SingularCordovaSdk.setLaunchOptions(launchOptions)
// Make window visible
window?.makeKeyAndVisible()
return true
}
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([Any]?) -> Void
) -> Bool {
return SingularCordovaSdk.startSession(with: userActivity)
}
}
These methods ensure the Singular SDK receives critical information about how and why your app was launched, which Singular uses for attribution tracking and deep link navigation.
Location: Modify your AppDelegate file located at
platforms/ios/[YourAppName]/Classes/AppDelegate.swift
or AppDelegate.m for Objective-C projects
SDK Configuration
Configure the Singular SDK to handle deep links and deferred deep links
by implementing the withSingularLink callback during initialization.
Add withSingularLink Callback
Basic Implementation
Configure the withSingularLink callback to handle incoming
deep link and deferred deep link data during SDK initialization.
// Create configuration
var singularConfig = new cordova.plugins.SingularCordovaSdk.SingularConfig(
'YOUR_SDK_KEY',
'YOUR_SDK_SECRET'
);
// Define link handler function
var linkHandler = function(data) {
var deeplink = data.deeplink;
var passthrough = data.passthrough;
var isDeferred = data.isDeferred;
console.log('Deep link:', deeplink);
console.log('Passthrough:', passthrough);
console.log('Is deferred:', isDeferred);
// Add link handling logic here
if (deeplink) {
handleDeepLink(deeplink, isDeferred);
}
};
// Attach link handler to configuration
singularConfig.withSingularLink(linkHandler);
// Initialize SDK
cordova.plugins.SingularCordovaSdk.init(singularConfig);
Note: The withSingularLink callback
is triggered only when the app opens through a Singular Link. For
more information, see the
Singular Links FAQ.
Advanced Implementation
Implement comprehensive deep link handling with navigation logic, passthrough data parsing, and error handling for production apps.
document.addEventListener('deviceready', initializeApp, false);
function initializeApp() {
// Create configuration
var config = new cordova.plugins.SingularCordovaSdk.SingularConfig(
'YOUR_SDK_KEY',
'YOUR_SDK_SECRET'
);
// Configure deep link handler
config.withSingularLink(function(params) {
console.log('=== Singular Link Resolved ===');
console.log('Full params:', JSON.stringify(params));
var deeplink = params.deeplink;
var passthrough = params.passthrough;
var isDeferred = params.isDeferred;
// Log for debugging
console.log('Deep link:', deeplink || 'null');
console.log('Passthrough:', passthrough || 'null');
console.log('Is deferred:', isDeferred);
// Handle passthrough data
if (passthrough) {
handlePassthroughData(passthrough);
}
// Handle deep link navigation
if (deeplink) {
handleDeepLinkNavigation(deeplink, isDeferred);
}
});
// Initialize SDK
cordova.plugins.SingularCordovaSdk.init(config);
}
function handlePassthroughData(passthroughString) {
try {
var data = JSON.parse(passthroughString);
// Apply promo code if present
if (data.promo_code) {
applyPromoCode(data.promo_code);
}
// Set user segment
if (data.segment) {
setUserSegment(data.segment);
}
// Track campaign
if (data.campaign_id) {
trackCampaign(data.campaign_id);
}
} catch (error) {
console.error('Error parsing passthrough:', error);
}
}
function handleDeepLinkNavigation(url, isDeferred) {
// Parse URL to extract route and parameters
var urlObj = parseDeepLink(url);
console.log('Navigating to: ' + urlObj.route);
console.log('Parameters:', urlObj.params);
console.log('Deferred install:', isDeferred);
// Route based on deep link structure
switch (urlObj.route) {
case 'product':
navigateToProduct(urlObj.params.id);
break;
case 'promo':
navigateToPromo(urlObj.params.code);
break;
case 'category':
navigateToCategory(urlObj.params.name);
break;
default:
navigateToHome();
}
}
function parseDeepLink(url) {
// Parse myapp://product/123?variant=blue
var parts = url.split('?');
var path = parts[0];
var queryString = parts[1];
var pathParts = path.replace(/^[^:]+:\/\//, '').split('/');
var route = pathParts[0];
// Parse parameters
var params = {};
// Add path parameters
if (pathParts.length > 1) {
params.id = pathParts[1];
}
// Add query parameters
if (queryString) {
queryString.split('&').forEach(function(pair) {
var keyValue = pair.split('=');
params[keyValue[0]] = decodeURIComponent(keyValue[1]);
});
}
return { route: route, params: params };
}
// Navigation functions
function navigateToProduct(productId) {
console.log('Navigating to product:', productId);
// Your navigation logic
}
function navigateToPromo(promoCode) {
console.log('Navigating to promo:', promoCode);
// Your navigation logic
}
function navigateToCategory(categoryName) {
console.log('Navigating to category:', categoryName);
// Your navigation logic
}
function navigateToHome() {
console.log('Navigating to home');
// Your navigation logic
}
// Utility functions
function applyPromoCode(code) {
console.log('Applying promo code:', code);
}
function setUserSegment(segment) {
console.log('Setting user segment:', segment);
}
function trackCampaign(campaignId) {
console.log('Tracking campaign:', campaignId);
}
Parameter Details
Understanding the parameters provided in the Singular Link callback helps you build robust deep linking logic.
| Parameter | Type | Description |
|---|---|---|
deeplink
|
String |
The destination URL within your app for users clicking the
link (e.g., myapp://product/123)
|
passthrough
|
String | Custom data passed through the tracking link, typically JSON-encoded for additional context |
isDeferred
|
Boolean | Indicates whether this is a deferred deep link (user installed the app after clicking the link) |
Best Practices
- Parse URLs Safely: Always validate and sanitize deep link URLs before using them for navigation to prevent malicious redirects
- Handle Missing Data: Check for null or undefined values before accessing deep link parameters
- Test Deferred Links: Test both immediate and deferred deep link scenarios to ensure proper navigation after fresh installs
- Log for Debugging: Enable detailed logging during development to verify deep links are received and parsed correctly
- Use Passthrough for Context: Leverage passthrough parameters to send additional context like campaign IDs, promo codes, or user segments
- Coordinate with Marketing: Work with your marketing team to define and document your app's deep link URL structure
For complete method documentation, see withSingularLink reference.
Handler Behavior
Understanding Callback Triggers
The withSingularLink callback behavior differs depending
on whether the app is freshly installed or already present on the device.
Fresh Install Scenario
On a fresh install, there is no Open URL when the app launches. Singular must complete attribution to the last touchpoint and determine if the tracking link contained a configured Deep Link or Deferred Deep Link (DDL) value.
How It Works:
- The attribution process occurs when the Singular SDK sends the first session to Singular servers
-
If applicable, the deep link value is returned to the SDK's
withSingularLinkhandler -
The deep link appears in the
deeplinkparameter withisDeferredset totrue - This process may take a few seconds as it requires server communication
Already Installed Scenario
If the app is already installed, clicking a Singular Link opens the app
immediately. The operating system provides the full tracking link URL,
which the Singular SDK parses during initialization to extract the
deeplink and passthrough values.
How It Works:
- The deep link is available immediately when the handler is triggered
-
The
isDeferredparameter is set tofalse - No server communication is required, resulting in faster callback execution
Testing Deep Links
Follow these steps to test deferred deep linking behavior in your development environment.
Testing Requirements:
- Uninstall the app from the test device (if currently installed)
- Reset your advertising identifier (IDFA on iOS, GAID on Android)
- Click the Singular tracking link from the device. Ensure the link is configured with a deep link value
- Install and open the app
- Verify that attribution completes and the DDL value is passed to your handler
Development Build Testing: When testing with a development
version of your app with a different package name (e.g.,
com.example.dev instead of com.example.prod),
ensure the tracking link is configured specifically for the development
app's package name. After clicking the test link, install the development
build directly onto the test device (via CLI or IDE) rather than
downloading from the app store.
Advanced Features
Passthrough Data
If a passthrough (_p) parameter is included in the tracking
link, the handler's passthrough parameter contains the corresponding
data. Use this for capturing campaign metadata, user segmentation data,
or any custom information you need in the app.
// Example tracking link with passthrough:
// https://example.sng.link/A?_dl=myapp://product/123&_p={"campaign":"summer","promo":"SAVE20"}
singularConfig.withSingularLink(function(data) {
var deeplink = data.deeplink;
var passthrough = data.passthrough;
if (passthrough) {
// Parse JSON passthrough data
var passthroughData = JSON.parse(passthrough);
console.log('Campaign:', passthroughData.campaign);
console.log('Promo code:', passthroughData.promo);
}
});
Query Parameter Forwarding
To capture all query parameters from the tracking link URL, append the
_forward_params=2 parameter to your Singular tracking link.
All query parameters will be included in the deeplink parameter
of the handler.
// Example tracking link with parameter forwarding:
// https://example.sng.link/A?_dl=myapp://product&_forward_params=2&category=electronics&sort=price
singularConfig.withSingularLink(function(data) {
var deeplink = data.deeplink;
// deeplink will contain: myapp://product?category=electronics&sort=price
console.log('Deep link with parameters:', deeplink);
// Parse and use the forwarded parameters
});
Important: The withSingularLink callback
is triggered only when the app opens through a Singular Link. Regular
app launches without a deep link will not trigger the handler.