Respectlytics Respect lytics
Menu
Swift (iOS) Deep link open Privacy-first

How to track deep-link opens in Swift (iOS) without personal data

Deep-link opens carry rich attribution payload by default — UTM parameters, source campaigns, referral codes, full URLs — and most analytics SDKs ingest all of it on open. Respectlytics helps developers avoid collecting personal data in the first place: in Swift (iOS), deep-link open is one named event, optionally differentiated by source via the event name. The full URL stays in your routing code; only the high-level entry point reaches analytics. Below: handlers for Universal Links, App Links, and custom schemes; what to keep out of the event name; and how to compute campaign attribution differently.

Fire the call inside your deep-link handler — SceneDelegate.scene(_:continue:) on iOS, Intent filter receiver on Android, the equivalent React Native Linking handler, Flutter's uni_links callback. Don't pass the URL or its query parameters.

Install the Swift (iOS) SDK

swift Respectlytics
// Package.swift
dependencies: [
    .package(url: "https://github.com/respectlytics/respectlytics-swift.git", from: "3.0.0")
]
// Or via Xcode → File → Add Packages → paste the URL above.

The SDK ships only via Swift Package Manager. CocoaPods and Carthage are not published — fewer integration paths means fewer surfaces to keep audited.

Initialize Respectlytics in Swift (iOS)

swift Respectlytics
import Respectlytics

@main
struct MyApp: App {
    init() {
        Respectlytics.configure(appKey: "<YOUR_APP_KEY>")
    }
    var body: some Scene { WindowGroup { ContentView() } }
}

Call configure once at app launch — typically in your App struct's init. No Info.plist keys are required: the SDK does not call ATTrackingManager and does not request the IDFA, so NSUserTrackingUsageDescription should NOT be added.

Track the event in Swift (iOS)

swift Respectlytics
import Respectlytics
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        // Universal Link entry — fire the event, don't pass the URL.
        Respectlytics.track("deeplink_open")
        if let url = userActivity.webpageURL {
            router.handle(url) // routing keeps the URL; analytics doesn't.
        }
    }
}

For custom-scheme URLs, use scene(_:openURLContexts:) instead — same track call. If you use SwiftUI's .onOpenURL, fire track inside that closure.

Privacy & implementation notes

A deep-link URL often contains the user's tracking ID, the campaign source, the referrer, and sometimes a session token — concatenated into a single free-form string. Respectlytics's API rejects free-form strings as event metadata. Your routing code keeps the URL; analytics gets the event name.

Install attribution and deep-link open are different signals. Install attribution requires server-side callbacks from the App Store / Play Store. Deep-link open is the in-app signal that the user navigated via a link. Don't use the open event as a proxy for install — they fire at different times for different populations.

Apple rejected approximately 3% of apps in 2024 for incorrectly omitting NSUserTrackingUsageDescription when ATT was required by the SDKs they shipped. Respectlytics doesn't trigger ATT. The corollary is also true: do not add the key on Respectlytics's account — its presence implies you track across apps, even if your code never calls requestTrackingAuthorization.

Internally the Swift SDK uses Swift Concurrency: events are queued in an actor-isolated buffer (RAM-only), flushed on a 30-second timer and on UIApplication.willResignActiveNotification. Force-quit before flush drops queued events — by design. There is no UserDefaults or file backing.

How this compares to other analytics SDKs

Deep-link open eventFirebase AnalyticsMixpanelRespectlytics
Full URL storedOften (via Dynamic Links)OftenRejected by API
UTM parameters as event propertiesYes (default for web tracking)YesRejected by API
Referral code as parameterRecommendedRecommendedUse distinct event_name (top-N) or skip
Per-campaign attributionPer-userPer-userSession-scoped, top-N campaigns only
Click-through rate (link → app open)With Dynamic LinksWith server-side joinOut of scope (use server-side analytics)

Frequently asked questions

How do we know which campaign drove an install?

Server-side, not in product analytics. App Store Connect (Apple Search Ads) and Play Console (Play Store referrer API) deliver install attribution to your backend via server-to-server callbacks. Respectlytics is for in-app product engagement — different question, different system of record.

What about top-N campaign tracking via event names?

If you have a small set of high-volume campaigns (under 10), distinct event names work: deeplink_open_summer_sale, deeplink_open_press_pickup. The long tail bucketed as deeplink_open_other. For high-cardinality campaign ID tracking, use server-side attribution instead.

Should we distinguish Universal Links / App Links from custom schemes?

If your app supports both (which is common during a migration), use distinct event names: deeplink_open_universal, deeplink_open_custom_scheme. The rate of each tells you how successfully you've migrated traffic to the modern API.

What if the deep link triggers in-app navigation but no other events?

Common with deep links to settings or specific content. Fire deeplink_open anyway — the open itself is the signal. If the user goes on to convert in the same session, the funnel groups them together via session_id.

Related guides

Track what matters. Collect nothing you don't.

Five-field event schema, RAM-only event queue, no IDFA, no AAID, no persistent user IDs. Helps developers avoid collecting personal data in the first place.