Every iOS app needs analytics. You need to know which features people use, where they drop off, and whether that onboarding redesign actually moved the needle. But since Apple introduced PrivacyInfo.xcprivacy in 2024 and started enforcing privacy nutrition labels, the question is no longer which analytics SDK has the most features. The question is: which SDK lets you collect the data you need without collecting data you should not have?
We run 27 apps across iOS, macOS, watchOS, and visionOS. Every one of them uses TelemetryDeck for analytics. Here is why we chose it over Firebase, what the real differences are, and how the implementation works at scale.
The Privacy Problem with Firebase Analytics
Firebase Analytics is powerful. It gives you event tracking, user properties, audience segments, funnel analysis, and deep integration with Google Ads. For a marketing-driven app with ad monetization, it is hard to beat.
But for indie apps that monetize through subscriptions or one-time purchases, most of that power is irrelevant — and the privacy cost is real.
Firebase collects device advertising identifiers (IDFA when available), IP addresses for geolocation, device model, OS version, app instance IDs, and user engagement data. It sends this data to Google's servers in the US. Under GDPR, this means you are transferring personal data to a third country, which triggers obligations around Standard Contractual Clauses and data processing agreements.
For your PrivacyInfo.xcprivacy, Firebase requires you to declare data collection categories that include device identifiers, usage data, and diagnostics — and depending on your configuration, potentially advertising data. Your App Store privacy label grows accordingly. Users see it. Reviewers see it.
None of this is wrong. If you run ads, Firebase is the right tool. But if you do not run ads — if your revenue comes from StoreKit 2 subscriptions and one-time purchases — you are taking on privacy overhead for features you will never use.
What TelemetryDeck Does Differently
TelemetryDeck is a privacy-first analytics service built specifically for Apple platform developers. The core architectural difference: it does not collect or store any personally identifiable information. No IP addresses. No device IDs. No advertising identifiers. No user accounts.
Instead of tracking individual users, TelemetryDeck uses a double-hashed anonymous identifier. Your app generates a user identifier (we use a random UUID stored in UserDefaults), and TelemetryDeck hashes it twice with a daily-rotating salt. The result is an anonymous session identifier that cannot be reversed to identify a specific user, cannot be correlated across days, and cannot be linked to any other service's data.
The practical result: your PrivacyInfo.xcprivacy declaration stays minimal. TelemetryDeck does not require you to declare any collected data types beyond basic analytics. Your App Store privacy label can honestly say "Data Not Linked to You" and "Data Not Used to Track You."
The PrivacyInfo.xcprivacy Declaration
Since Spring 2024, every app submitted to the App Store must include a privacy manifest. This is where the practical difference between Firebase and TelemetryDeck becomes concrete.
With TelemetryDeck, the analytics-related section of your privacy manifest is straightforward:
<key>NSPrivacyCollectedDataTypes</key>
<array>
<!-- TelemetryDeck: anonymous usage signals only -->
</array>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
No tracking domains. No collected data types for analytics. The most common entry you will need is the UserDefaults API declaration (reason code CA92.1), which almost every app needs regardless of analytics choice.
With Firebase, the privacy manifest must declare additional data categories, tracking domains (firebase-settings.crashlytics.com, app-measurement.com, and others), and the collected data types expand to include device identifiers and usage data at minimum.
Across 27 apps, this difference is not cosmetic. Every additional privacy declaration is another surface for App Store review questions. Every tracking domain is another entry that privacy-conscious users can look up.
Implementation: One Line Per App
Our entire analytics setup lives in AppFoundation, the shared Swift Package that powers all 27 apps. The TelemetryDeck initialization is part of the centralized AppSetup.configure() call:
import TelemetryDeck
// Inside AppFoundation's AppSetup
static func configure(tdAppID: String, ...) {
let config = TelemetryDeck.Config(appID: tdAppID)
TelemetryDeck.initialize(config: config)
}
Each app passes its unique TelemetryDeck App ID at launch. That is it. No additional configuration, no consent dialogs to build, no GDPR banner to implement. Because TelemetryDeck does not collect personal data, explicit user consent for analytics is not required under GDPR — the legal basis is legitimate interest.
Sending an event is equally minimal:
TelemetryDeck.signal("onboarding.completed")
TelemetryDeck.signal("paywall.shown", parameters: ["source": "settings"])
TelemetryDeck.signal("purchase.started", parameters: ["product": "yearly"])
We track about 15 standard events across all apps: onboarding steps, paywall impressions, purchase starts and completions, feature usage counts, and error states. The naming convention follows a feature.action pattern that maps cleanly to TelemetryDeck's dashboard filters.
What You Give Up
TelemetryDeck is not Firebase. If you need these, TelemetryDeck is the wrong choice:
- User-level journey tracking. You cannot see what User #12345 did before churning. You see aggregate patterns: 40% of users who reached the paywall started a trial. Not which specific users.
- Ad attribution. No IDFA collection means no install-source attribution from ad campaigns. If you run paid acquisition, you need a different tool.
- Real-time dashboards. TelemetryDeck data has a short processing delay. Firebase gives you real-time event streams.
- A/B testing infrastructure. Firebase Remote Config lets you run experiments. TelemetryDeck is analytics only — you need a separate tool for experiments.
- Free tier at massive scale. Firebase Analytics is free regardless of volume. TelemetryDeck has a generous free tier (100K signals per month) and paid plans beyond that.
For a portfolio of indie apps monetized through subscriptions, none of these gaps have been a problem. We do not run ads. We do not need user-level journeys. We need to know: does the onboarding convert? Does the paywall show at the right time? Which features are actually used? TelemetryDeck answers all of those.
The Full Privacy Stack
Analytics is one piece. Our complete privacy-first instrumentation stack across all 27 apps:
- Analytics: TelemetryDeck — anonymous usage signals, no PII collected.
- Crash reporting: Sentry — device info and stack traces only. No user emails, no names, no account data. Sentry's on-device symbolication means raw crash data never leaves the device unsymbolicated.
- Monetization: RevenueCat — manages subscription state. Stores purchase tokens and entitlements. No payment card data (Apple handles that). No personal information beyond an anonymous app user ID.
Each service has its own PrivacyInfo.xcprivacy bundled within its SDK. Apple's privacy report generator (Product > Generate Privacy Report in Xcode) aggregates all manifests from your app and its dependencies into one report. Running this before every submission catches gaps before reviewers do.
The Privacy Manifest Gotcha That Catches Everyone
The most commonly missed entry in PrivacyInfo.xcprivacy has nothing to do with analytics. It is UserDefaults.
Almost every app calls UserDefaults.standard — for onboarding state, settings, cached preferences. Apple requires you to declare reason code CA92.1 (app-specific data only) for the NSPrivacyAccessedAPICategoryUserDefaults category. Miss it, and your submission gets flagged.
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array><string>CA92.1</string></array>
</dict>
</array>
Other common categories to check: FileTimestamp (if you use NSFileCreationDate), SystemBootTime (if anything in your dependency chain calls mach_absolute_time), and DiskSpace (if you check available storage before downloads).
Comparison Table
| TelemetryDeck | Firebase Analytics | |
|---|---|---|
| PII collected | None | Device IDs, IP address, IDFA (optional) |
| Data location | EU (Germany) | US (Google Cloud) |
| GDPR consent required | No (no personal data) | Yes (personal data transfer to US) |
| Privacy label impact | Minimal | Device IDs + Usage Data |
| User-level tracking | No (aggregate only) | Yes |
| Ad attribution | No | Yes (with IDFA) |
| SDK size | ~200 KB | ~5 MB (with dependencies) |
| Swift-native | Yes (SPM) | Partial (Obj-C core, SPM support) |
| Free tier | 100K signals/month | Unlimited |
When to Use Firebase Instead
Firebase is the right choice when:
- Your app monetizes through ads and you need attribution data.
- You need real-time event streams for live monitoring dashboards.
- You are running A/B tests through Remote Config.
- Your app is Android-first or cross-platform (Firebase's Android support is stronger).
- You need user-level cohort analysis for product decisions.
Firebase is not a privacy-hostile tool. It is a comprehensive platform that collects data commensurate with its feature set. The question is whether you need those features.
Key Takeaways
- If you do not run ads, you probably do not need Firebase Analytics. The privacy overhead is not justified for subscription-monetized apps.
- TelemetryDeck's double-hashed identifiers mean no GDPR consent dialogs. One less thing to build, one less legal question to answer.
PrivacyInfo.xcprivacyis mandatory. Run Xcode's privacy report generator before every submission. The most commonly missed entry is UserDefaults (CA92.1).- Your privacy stack compounds. TelemetryDeck + Sentry + RevenueCat gives you analytics, crash reporting, and monetization with near-zero PII collection.
- SDK size matters at scale. Across 27 apps, the difference between a 200 KB and a 5 MB analytics dependency adds up in build times and binary size.