- Google Play's data safety form and Apple's
PrivacyInfo.xcprivacyare the same idea in two formats, and both reject apps whose declarations don't match reality. - Audit every SDK before touching either form: what it collects, linked or unlinked, and the purpose.
- The six categories that catch first-timers: crash reporting, IP addresses, purchase history, diagnostics, ad SDKs, account creation.
- Apple's manifest has been enforced since May 2024. Missing entries surface as App Store Connect warnings, then rejections.
- Automate the mapping: keep an SDK inventory file and regenerate the declaration on every release.
Every mobile app submission has a wall you don't see coming. Not the review queue, not screenshot rejections: the privacy declaration. Google Play's data safety section and Apple's privacy manifest are the same idea in two formats, and both reject an app whose declaration doesn't match reality.
Why this matters
An incorrect privacy declaration is not a technical bug, it is a policy violation. Google Play rejects the update, and repeated violations put the developer account at risk. Apple's privacy manifest (PrivacyInfo.xcprivacy, enforced since May 2024) surfaces missing entries as App Store Connect warnings, then rejections.
Most indie developers fill these forms from memory five minutes before submitting, then spend the next week resubmitting because they forgot Sentry collects device identifiers.
The full inventory audit
Before touching either form, list every third-party SDK in the app. For each, note three things: what it collects, whether that data is linked to the user (account ID or device ID) or unlinked, and whether it serves analytics, personalization, advertising, or app functionality.
Common indie-app SDKs and what they collect:
| SDK | Collects | Linked? | Purpose |
|---|---|---|---|
| Firebase Analytics | Device ID, session data, user actions | Linked (Firebase user ID) | Analytics |
| Sentry | Device model, OS version, stack traces | Unlinked unless user context attached | Diagnostics |
| RevenueCat | Purchase history, subscription state | Linked (RevenueCat user ID) | App functionality |
| Mixpanel / PostHog | User actions, custom events | Linked (your user ID) | Analytics |
| AdMob / AppLovin | Device ID, ad interaction | Linked | Advertising |
This audit output is what you reference against every question on both platforms' forms.
The 6 categories that trip up first-time submitters
- Crash reporting. Counts as collection even if you never look at it. Sentry, Crashlytics, Bugsnag all collect declarable types.
- IP addresses. Every network request logs an IP somewhere. If your backend logs IPs (it does), you collect device identifiers.
- Purchase history. StoreKit or Play Billing plus RevenueCat means financial info, even though card data never touches your servers.
- Diagnostic data. Performance metrics, ANR reports, custom logs. All collection.
- Ad SDK data. Any monetization SDK means collecting for advertising. The most common source of rejections.
- Account creation. Email, password hash, phone: always linked, always declared.
Google Play vs App Store
Same intent, different formats.
| Google Play | App Store | |
|---|---|---|
| Format | Question-based Console form |
PrivacyInfo.xcprivacy plist in the bundle |
| Structure | ~40 questions across 14 data categories | Typed entries per data type plus required-reason API codes |
| Filled | In the Play Console UI | In code, merged from your app and every SDK's own manifest |
Xcode 15+ merges your manifest with every SDK's bundled manifest into one privacy report, which feeds the App Store label. Fill the two platforms out separately; there is no shared source unless you build one.
Copy-paste starting point
For a typical indie app (analytics + crash reporting + payments):
| You use | Play form answer | Apple manifest data type |
|---|---|---|
| Firebase Analytics | Collects: Device IDs, App interactions. Purpose: Analytics |
NSPrivacyCollectedDataTypeDeviceID, NSPrivacyCollectedDataTypeProductInteraction
|
| Sentry | Collects: Crash logs, Diagnostics |
NSPrivacyCollectedDataTypeCrashData, NSPrivacyCollectedDataTypePerformanceData
|
| RevenueCat | Collects: Purchase history | NSPrivacyCollectedDataTypePurchaseHistory |
A starting point, not an answer key: verify each SDK's current documentation at submission time, since collection profiles change between versions.
Automate this, don't guess
Maintain a spreadsheet or JSON file with your SDK inventory and each one's collection profile, and regenerate the declaration on every release instead of recalling it. CI tooling such as LetsDeploy can diff your dependency list against the last declared inventory and fail the build when a new SDK appears undeclared. Fifteen minutes building this system saves days of rejection cycles per year.
What's the SDK that surprised you most on a privacy form? Mine was learning that crash logs count. Drop yours in the comments.
Top comments (0)