Respectlytics Respect lytics
Menu
Swift (iOS) Notification permission granted Privacy-first

How to track notification permission grants in Swift (iOS) without personal data

Notification permission outcomes — beyond the simple opt-in moment — include OS-level permission revocations, deferred prompts, and provisional grants. Respectlytics helps developers avoid collecting personal data in the first place: in Swift (iOS), each permission outcome is its own named event, fired at the moment the system delivers the result. Below: how to wire the call to platform-specific permission callbacks, how to distinguish the states, and what to leave to your push-delivery backend.

Wire each callback path to its own event_name: granted, denied, provisional, deferred. The platform permission API delivers the result asynchronously — fire on the result, not on the request.

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 UserNotifications

func resolvePermissionState() {
    UNUserNotificationCenter.current().getNotificationSettings { settings in
        switch settings.authorizationStatus {
        case .authorized: Respectlytics.track("push_optin")
        case .provisional: Respectlytics.track("push_provisional_optin")
        case .denied: Respectlytics.track("push_decline")
        case .ephemeral: Respectlytics.track("push_ephemeral_optin")
        case .notDetermined: break
        @unknown default: break
        }
    }
}

Read the current state on app foreground, not just on initial prompt — users may have changed permission in Settings while the app was backgrounded.

Privacy & implementation notes

Notification permission state is asymmetric: granting and revoking go through different OS pathways. Granting fires through your prompt callback; revoking happens silently in Settings, with no event delivered to your app. Detect revocation lazily on next foreground if you need it.

If you prompt at multiple points in the funnel (onboarding, post-first-session, after key feature), use distinct event names per timing — push_prompt_at_onboarding, push_prompt_post_session. Conversion-rate-by-timing falls out of session-grouped event counts.

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

Notification permission eventFirebase AnalyticsMixpanelRespectlytics
Per-user permission stateYes (user property)Yes (profile)Out of scope
Push token / FCM ID storedYesYesNever
Permission outcome states distinguishableManual (params)Manual (params)Distinct event_name per outcome
Time-to-grant after first promptPer-userPer-userSession-scoped

Frequently asked questions

Should we track when the user revokes permission later?

Hard to detect reliably from the app. The OS doesn't deliver an explicit revocation event — you only learn at the next foreground when getNotificationSettings() returns denied. If you do detect it, fire push_revoked_detected (with no metadata) and use it for rate analysis only.

What's the right event for re-prompting after a deferred decision?

If you prompt twice, fire distinct events for each prompt: push_prompt_v1, push_prompt_v2. Apple and Google both have anti-spam policies — a second prompt is allowed only after meaningful product context, and you should instrument that decision point.

How does this differ from `push-opt-in`?

push-opt-in is the narrow event that fires on grant. notification-permission is the broader category that includes all permission outcomes — granted, denied, provisional, deferred, revoked. Use both, with non-overlapping event names per outcome.

What about silent / background-only notification capability?

On iOS, notification permission is independent from background-fetch capability. On Android 13+, POST_NOTIFICATIONS is required for visible notifications regardless of background fetch. If you care about background-only delivery, fire a separate push_background_only event when relevant.

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.