iOS SDK - Supporting Deep Links

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.

Required Configuration Steps:

  • Associated Domains: In Xcode, add a Singular Custom Subdomain to Signing & Capabilities > Associated Domains
  • URL Types: Add the app scheme to your URL Types at Info > URL Types
  • Singular Platform: Add your Apple Developer Team ID and Scheme in the Apps page in the Singular platform

Notes:

  • If the app is already configured to use iOS Universal Links, the Universal Link domain already exists in Associated Domains and can remain. This domain should be added to the Supported Domains config option , as noted in the advanced section below
  • You must also include the Singular custom link domain , so that Singular can track attributions from marketing campaigns and handle deep links from these campaigns

Implement Singular Links Handler

The SingularLinkHandler 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: The destination URL within your app for users clicking the link
  • Deferred Deep Link: The destination URL for users who install the app after clicking the link
  • Passthrough: Custom data passed through the tracking link for additional context
  • URL Parameters: All query parameters from the tracking link URL

SDK Configuration

Add SingularLinkHandler to Config

Configure the SingularLinkHandler during SDK initialization to process incoming deep link and deferred deep link data.

Swift Objective-C
func getConfig() -> SingularConfig? {
    // Create config with API credentials
    guard let config = SingularConfig(apiKey: "SDK_KEY", andSecret: "SDK_SECRET") else {
        return nil
    }
    
    // Set deep link handler
    config.singularLinksHandler = { params in
        self.handleDeeplink(params: params)
    }
    
    return config
}

func handleDeeplink(params: SingularLinkParams?) {
    // Get Deeplink data from Singular Link
    let deeplink = params?.getDeepLink()
    let passthrough = params?.getPassthrough()
    let isDeferred = params?.isDeferred()
    let urlParams = params?.getUrlParameters()
    
    print("Deeplink: \(deeplink ?? "null")")
    print("Passthrough: \(passthrough ?? "null")")
    print("Is Deferred: \(isDeferred ?? false)")
    
    // Handle deep link routing
    if let url = deeplink {
        handleDeepLinkRouting(url: url, isDeferred: isDeferred ?? false)
    }
}

Note: The SingularLinkHandler is triggered only when the app opens through a Singular Link. For more information, see the Singular Links FAQ .


Handler Behavior

The SingularLinkHandler behaves differently depending on whether the app is freshly installed or already installed.

Fresh Install (Deferred Deep Link)

On a fresh install, no Open URL exists when the app launches. Singular completes attribution to determine if the tracking link contained a deep link or deferred deep link value.

Deferred Deep Link Flow:

  1. User clicks a Singular tracking link configured with a deep link value
  2. User installs and opens the app for the first time
  3. Singular SDK sends the first session to Singular servers
  4. Attribution completes and identifies the deep link from the tracking link
  5. Deep link value returns to the SingularLinkHandler with isDeferred = true

Testing Deferred Deep Links:

  1. Uninstall the app from the test device (if currently installed)
  2. Reset your IDFA on the device (Settings > Privacy > Apple Advertising > Reset Advertising Identifier)
  3. Click the Singular tracking link from the device (ensure it's configured with a deep link value)
  4. Install and open the app

Attribution should complete successfully, and the deferred deep link value will be passed to the SingularLinkHandler.

Pro Tip: When testing deep links with a development build using a different bundle identifier (e.g., com.example.dev instead of com.example.prod ), configure the tracking link specifically for the development app's bundle identifier. After clicking the test link, install the development build directly onto the device via Xcode or TestFlight, rather than downloading the production app from the App Store.


Already Installed (Immediate Deep Link)

When the app is already installed, clicking a Singular Link opens the app immediately using iOS Universal Links technology.

Immediate Deep Link Flow:

  1. User clicks a Singular tracking link
  2. iOS provides an Open URL containing the entire Singular tracking link
  3. During SDK initialization, Singular parses the NSUserActivity or URL
  4. Singular extracts the deep link and passthrough values
  5. Values return through the SingularLinkHandler with isDeferred = false

Passthrough Parameters

Capture additional data from the tracking link click using passthrough parameters.

If a passthrough parameter is included in the tracking link, the SingularLinkHandler'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.

Swift Objective-C
func handleDeeplink(params: SingularLinkParams?) {
    // Extract passthrough data
    if let passthroughData = params?.getPassthrough() {
        // Parse JSON passthrough data
        if let data = passthroughData.data(using: .utf8),
           let jsonData = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
            
            let campaignId = jsonData["campaign_id"] as? String
            let userSegment = jsonData["segment"] as? String
            
            print("Campaign ID: \(campaignId ?? "unknown")")
            print("User Segment: \(userSegment ?? "unknown")")
        }
    }
}

URL Parameters

Capture all query parameters from the tracking link URL using the getUrlParameters() method.

The SingularLinkHandler provides access to all URL parameters from the tracking link, giving you complete access to custom parameters and UTM tags.

Swift Objective-C
func handleDeeplink(params: SingularLinkParams?) {
    // Get all URL parameters
    if let urlParams = params?.getUrlParameters() {
        for (key, value) in urlParams {
            print("Parameter: \(key) = \(value)")
        }
        
        // Access specific parameters
        if let utmSource = urlParams["utm_source"] as? String {
            print("UTM Source: \(utmSource)")
        }
        
        if let promoCode = urlParams["promo"] as? String {
            print("Promo Code: \(promoCode)")
        }
    }
}

Example Tracking Link:
https://yourapp.sng.link/A1b2c/abc123?_dl=myapp://product/123&utm_source=facebook&promo=SALE2024

The SingularLinkHandler will provide access to all parameters including utm_source and promo through the getUrlParameters() method.


Advanced Configuration

Support Universal Links from third-party partners like Google Ads and Facebook for attribution tracking.

For Singular iOS SDK versions 12.0.3 and above, non-Singular Universal Links are supported by default.

Deprecated feature: The supportedDomains property and the startSession:...andSupportedDomains: overloads are annotated __attribute__((deprecated)) in the current SDK. The block below is shown only for legacy SDK versions (below 12.0.3); upgrade the SDK rather than continuing to set supportedDomains in new code.

To support third-party deep links in older versions of the SDK:

  • Add all associated domains (excluding sng.link ) to the supportedDomains configuration option in the Config object every time the Singular SDK is initialized
  • This allows for third-party deep link behavior but does not allow for attribution to the deep link. For attribution, you still have to use Singular tracking links
  • supportedDomains functionality assumes you have configured your app for Universal Links and currently host your own AASA file on your domain
Swift Objective-C
func getConfig() -> SingularConfig? {
    guard let config = SingularConfig(apiKey: "SDK_KEY", andSecret: "SDK_SECRET") else {
        return nil
    }
    
    // Add supported domains for third-party Universal Links
    config.supportedDomains = [
        "subdomain.mywebsite.com",
        "anothersubdomain.myotherwebsite.com"
    ]
    
    return config
}

Enable Universal Links served by Email Service Providers (ESPs) for email campaign attribution.

The ESP domain must be HTTPS-enabled. Apple requires that iOS apps pull apple-app-site-association files from an HTTPS-enabled endpoint without redirects. Check with your ESP how they host this file for your app, as it may require DNS configuration on your site's DNS.

To support an ESP domain, add the custom tracking domain to the espDomains configuration option in the config object every time the Singular SDK is initialized.

Swift Objective-C
func getConfig() -> SingularConfig? {
    guard let config = SingularConfig(apiKey: "SDK_KEY", andSecret: "SDK_SECRET") else {
        return nil
    }
    
    // Add ESP domains for email campaign tracking
    config.espDomains = ["links.mywebsite.com"]
    
    return config
}