RORK LABJP
IOS27 — iOS 27 and iPadOS 27 ship on September 14, three days out. The ground always shifts under app builders in the days right after a releaseWAIT — Standard Rork waits on Expo and React Native to catch up. Rork Max can follow as soon as Xcode and the SDK are ready. Different kinds of waitingFOLD — The folding iPhone Duo starts at $1,999. A new screen shape is the first place a generated layout tends to come apartSTACK — Standard Rork emits React Native through Expo; Rork Max emits native Swift. A great many write-ups still conflate the twoPRICE — Standard tiers run Free, Junior at $25, Middle at $50 and Senior at $100. Rork Max spans $200 to $1,800 a month depending on tierSOURCE — Funding figures differ across secondary coverage right now. If you cannot verify a number at the source, leave it outIOS27 — iOS 27 and iPadOS 27 ship on September 14, three days out. The ground always shifts under app builders in the days right after a releaseWAIT — Standard Rork waits on Expo and React Native to catch up. Rork Max can follow as soon as Xcode and the SDK are ready. Different kinds of waitingFOLD — The folding iPhone Duo starts at $1,999. A new screen shape is the first place a generated layout tends to come apartSTACK — Standard Rork emits React Native through Expo; Rork Max emits native Swift. A great many write-ups still conflate the twoPRICE — Standard tiers run Free, Junior at $25, Middle at $50 and Senior at $100. Rork Max spans $200 to $1,800 a month depending on tierSOURCE — Funding figures differ across secondary coverage right now. If you cannot verify a number at the source, leave it out
Articles/App Dev
App Dev/2026-06-25Intermediate

The App Privacy Section That Grows the Moment You Add Ads and Subscriptions — Notes on What I Actually Checked

How I filled out App Store Connect's App Privacy section for a Rork (Expo) app with AdMob, RevenueCat, and Crashlytics — including the tracking-to-ATT chain, written up as field notes from running six apps.

App Store88Privacy10AdMob71RevenueCat30Expo205

The other day I tried to submit a new wallpaper app to App Store Connect. The build was fine, yet a red banner — "This app has no App Privacy information" — stopped me from going any further. The code was finished, but I was blocked at the very last step. When you ship apps as a solo developer, this declaration screen always makes you brace yourself a little.

The App Privacy section is where you, the developer, declare what kinds of data your app collects. The tricky part is that you are responsible not only for your own code, but also for whatever the third-party SDKs you embed — ads, billing, crash reporting — quietly collect in the background. For my first few apps I was bounced back here repeatedly, and ended up re-checking what each SDK gathers, one by one.

In this article I'll leave field notes on what I actually checked for a fairly standard setup: AdMob, RevenueCat, and Crashlytics. The exact answers shift with your configuration and SDK versions, so please verify against your own environment in the end.

App Privacy and the privacy manifest are two different things

These are easy to confuse, so let me separate them first. There are two similar-sounding things, and you need both.

NameWhat it isWhere you set it
Privacy manifest (PrivacyInfo.xcprivacy)A file embedded in the app binary. Declares collected data types and the reasons for using "Required Reason APIs" in a machine-readable formThe build (Expo config / bundled by each SDK)
App Privacy (nutrition label)The "data practices" list shown on your store product page. A developer self-declarationThe web form in App Store Connect

The former is a machine-facing declaration read by crawlers; the latter is a human-facing summary that users read on the product page. Even if your manifest is correct, you still have to fill in the web-side declaration yourself. Early on I assumed these two were the same thing, got my manifest in order, still couldn't submit, and spent a while not understanding why.

Adding ads, billing, and crash reporting expands what you must declare

For a wallpaper app that only displays images, the declaration stays minimal. But once you add three SDKs for monetization and operations, it tips firmly toward "data is collected." Here is roughly what I ended up checking for my setup.

SDK (purpose)Main data types collectedLinked to the userUsed for tracking
AdMob (ads)Identifiers (advertising ID / IDFA, etc.), Usage Data, DiagnosticsYes (for ad delivery)Yes (with personalized ads)
RevenueCat (billing)Purchases, Identifiers (user ID), Usage DataYesNo
Crashlytics (crash reporting)Diagnostics, Identifiers (installation ID)No (in most setups)No

The biggest fork in the road here is AdMob's "used for tracking." Once you enable personalized ads, you are using the advertising ID to track users, which puts you under "Used to Track You" in the declaration. In my setup, RevenueCat and Crashlytics collect data to operate my own service but do not track across third parties, so I leave them out of the tracking column.

Each SDK publishes a page summarizing exactly what data it collects. If you fill the form from guesswork without reading these, discrepancies surface later. Before every declaration, I reopen each vendor's latest data-collection document and only then fill in the form.

Checking "used for tracking" makes ATT mandatory

This is the chain that trips people up most at submission time. If you declare "identifiers used for tracking" in App Privacy but your app never shows the App Tracking Transparency (ATT) permission dialog, the review will bounce you — because the declaration and the implementation contradict each other.

With Expo, add expo-tracking-transparency and set the permission string.

{
  "expo": {
    "plugins": [
      [
        "expo-tracking-transparency",
        {
          "userTrackingPermission": "We use your activity to show ads that are relevant to you."
        }
      ]
    ]
  }
}

Then always request permission before loading personalized ads.

import { requestTrackingPermissionsAsync } from "expo-tracking-transparency";
 
const { status } = await requestTrackingPermissionsAsync();
// Only enable personalized ads when granted
const personalized = status === "granted";

If permission is denied, turn personalization off and fall back to non-personalized ads. "Declared it = implemented ATT = stop tracking when the user declines" — unless all three line up, a contradiction will eventually show somewhere. I once set the ATT string but forgot to actually call the dialog, noticed only after submitting, and had to swap it in a hurry.

How to decide the three axes (collected / linked / tracking)

App Privacy is, for each data type, a matter of deciding three things in order. When in doubt, asking yourself in this order keeps it tidy.

First, "is it collected at all?" Take inventory of what your own code collects plus what the embedded SDKs collect. The moment you add an ad SDK, identifiers and usage data fall onto the "collected" side.

Second, "is it linked to the user?" If you can identify an individual through an account or device ID, it is "linked." Purchase history is tied to the account, so I put RevenueCat-related data under "linked."

Third, "is it used to track across third parties?" This is the heaviest call, and it ties directly to ATT. Personalized ads qualify; plain operational analytics usually does not. Leaving this vague and "checking everything just in case" needlessly forces ATT and lowers your opt-in rate, so I find it more practical to narrow it down with a clear rationale.

Revisit the declaration whenever you update an SDK

The hard part of operations is that this isn't fill-once-and-forget. A major SDK update can quietly add new collected data types. Since I run six apps in parallel, I now always set aside time at the once-a-year SDK update to reconcile each vendor's data-collection document against my own declaration.

Lately I keep a single mapping table of my own — "data collected per SDK to App Privacy category" — and when I ship a new app I copy it and only fix the differences. That has cut mistakes far more than thinking it through from scratch every time.

Before you submit your next app, start by listing the SDKs you've embedded and opening each one's latest data-collection page. Those ten-odd minutes turn out to be the shortcut, rather than getting stuck at the declaration after the code is done. I hope this helps anyone stuck at the same spot.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

App Dev2026-08-21
Apple's automated pass reads what your purpose strings are for, not whether they exist
Submit a Rork or Expo iOS build and you may get it back under Guideline 5.1.1 with a note about placeholder or otherwise insufficient purpose strings. Here is how to read a rejection that names no key, and how to rewrite the strings from app.json.
App Dev2026-07-16
Placing Native Ads in a Masonry Wallpaper Grid: Designing the Lifetime of an Ad Cell
One native ad in a masonry gallery pushed memory from 180 MB to 420 MB over twenty minutes of scrolling. Here is why cell recycling and ad object lifetime never line up, the pool-based implementation that fixed it, and how I picked the insertion interval from measured numbers.
App Dev2026-03-15
Production AI Companion Apps: Streaming, Voice & Monetization
Build a production-grade AI companion with streaming responses, voice I/O, mood tracking, offline support, and subscription monetization. App Store submission guidelines included.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links