The tracking call is one line. Place it where your purchase observer sees a successful transaction — the same callback you'd already use to grant entitlement to the user. Avoid the temptation to pass price, currency, product SKU, or user ID; Respectlytics's API rejects extra fields with a 400 Bad Request, so this fails fast in development if a teammate adds a field by reflex.
▸ Install the Swift (iOS) SDK
// 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)
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)
import Respectlytics
import StoreKit
// In your StoreKit 2 transaction listener:
Task {
for await result in Transaction.updates {
guard case .verified(let transaction) = result else { continue }
if transaction.revocationDate == nil {
// No price, no product ID, no user ID. Session-scoped event is enough.
Respectlytics.track("paywall_purchase")
await transaction.finish()
}
}
}
Equivalent code in StoreKit 1's `SKPaymentTransactionObserver` is one-line shorter; the principle is the same — call `track` on the *successful* transaction state.
✦ Privacy & implementation notes
Most analytics SDKs default to tying purchase events to a persistent `user_id` or device-level identifier. Respectlytics's `session_id` rotates every two hours, so a paywall purchase becomes "a purchase happened in this session" — sufficient for funnel analysis, insufficient for resale or cross-app re-targeting. This is the data-minimization trade-off in one line.
The natural aggregation bucket is **(country, platform, day)**. "78% of paywall views convert in DE on iOS today" is a useful comparison even without per-user identity. Most paywall A/B-test decisions are made on differences this granular — going down to per-user is operationally expensive and rarely changes the conclusion.
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
| What gets sent on a paywall purchase | Firebase Analytics (default) | Mixpanel (default) | Respectlytics |
|---|---|---|---|
| IDFA / AAID | Yes (with user consent) | Optional | Never |
| Persistent user ID | app_instance_id | distinct_id | Never |
| Purchase amount / currency | Recommended | Recommended | Rejected by API |
| Product / SKU identifier | Recommended | Recommended | Rejected by API |
| Transaction ID | Recommended | Recommended | Rejected by API |
| IP address stored | Yes | Yes (90-day default) | Used transiently for country, then discarded |
| What you can compute | Per-user LTV, cohort revenue | Per-user LTV, cohort revenue | Session-grouped funnel, country-level conversion rate |
❓ Frequently asked questions
How do we attribute revenue without a user ID?
You don't, at the user level. You attribute by **session, country, and day**. For most product decisions — "is the new paywall design converting more sessions in DE on iOS?" — that's enough. If you need per-user LTV for investor reporting, that lives in your billing system (Stripe, RevenueCat, App Store Connect) — not in your product analytics.
Can we still A/B-test paywall variants?
Yes. Emit different `event_name` values for each variant — e.g. `paywall_purchase_a`, `paywall_purchase_b`. Aggregation buckets them automatically. No randomized user assignment is stored — variant assignment lives in the client until the event fires.
What about refunds and chargebacks?
Out of scope for product analytics. Your billing system already has authoritative refund data, with the user IDs and amounts you legitimately need to act on. Mixing those into your conversion funnel produces double-counted noise — keep them separate.
Will the App Store reject my app for not collecting purchase metadata?
No. Apple's review guidelines do not require you to collect product or price metadata. Your `Receipt` and `transactionIdentifier` already exist on-device and on Apple's servers — duplicating them into your analytics pipeline is a choice, not a requirement.