Respectlytics Respect lytics
Menu
Swift (iOS) Paywall view Privacy-first

How to track paywall views in Swift (iOS) without personal data

Paywall view is the top of the monetization funnel — and the place teams over-instrument with placement metadata, experiment assignment IDs, and per-user variant tracking. Respectlytics helps developers avoid collecting personal data in the first place: in Swift (iOS), paywall view is one named event, with no payload. If you A/B-test placements or copy variants, encode the variant into the event name. Below: the Swift (iOS) pattern, the conversion-rate math you can still do, and the metadata trade-offs.

Fire the call when the paywall surface is actually visible to the user — not on push, not on configure. SwiftUI/Compose/RN/Flutter visibility callbacks are the right hook. Don't pass the variant ID, the placement, or the offer config as metadata.

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 SwiftUI

struct PaywallScreen: View {
    var body: some View {
        VStack { /* paywall content */ }
            // Fires on actual visibility, not configure.
            .onAppear { Respectlytics.track("paywall_view") }
    }
}

For UIKit, place the track call in viewDidAppear(_:), not viewDidLoad() — load fires before the user can possibly see the surface.

Privacy & implementation notes

Fire the event on actual visibility, not on data fetch. SwiftUI's .onAppear, Compose's LaunchedEffect(Unit), RN's useFocusEffect, and Flutter's AfterFirstLayout mixin are the canonical hooks. Tracking on configure inflates the rate with paywalls the user never saw.

Experiment IDs are tempting because they look harmless — they're really not. A stable experiment ID across thousands of sessions becomes a per-user fingerprint via the variant assignment pattern. Encode the variant in the event name; discard the assignment ID.

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

Paywall view eventFirebase AnalyticsMixpanelRespectlytics
Per-user identityapp_instance_iddistinct_idNever
Variant / experiment ID as parameterRecommendedRecommendedUse distinct event_name
Placement (home, settings, …) as parameterRecommendedRecommendedUse distinct event_name
Computed metric: paywall_view → paywall_purchase ratePer-userPer-userSession-grouped
Bot / accidental view filteringHeuristic per userHeuristic per userCountry + session aggregate

Frequently asked questions

How do we measure paywall conversion rate without joining view → purchase per user?

Per-session. A session that emits both paywall_view and paywall_purchase is a converting session. The ratio across all sessions is your conversion rate. The noise from sessions where the user views the paywall on day 1 and converts on day 3 is small at scale — and your billing system already has the longitudinal truth.

Can we A/B-test paywall variants?

Yes. Emit paywall_view_a, paywall_view_b, etc., and pair with paywall_purchase_a, paywall_purchase_b. Per-variant conversion rate falls out of session-grouped event counts.

What about tracking which placement the paywall was shown from?

Distinct event names per placement: paywall_view_home, paywall_view_settings, paywall_view_post_onboarding. Keep the taxonomy short — under 8 placements is comfortable; past that, bucket the long tail.

Should we track the offered price or product set?

No. Pricing changes belong in your release notes and your billing system, not in your analytics pipeline. Mixing them in produces stale data the moment you change a price.

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.