What leaves the device, and what we never see
This page describes behaviour you can verify: the SDK is open source, the wire schema is published, and the list of things it will not collect is normative rather than aspirational.
- Event name, millisecond timestamp, sequence number
- Flat event properties you choose to send
- Session id, scoped to one install
- Install id: a random UUID, salted and SHA-256 hashed on device
- App id (bundle id), app version and build number, SDK version
- OS name and version, device model, CPU architecture
- Locale and the device's region setting (not derived from IP)
- Whether the build is a debug build
- Screen size and scale, light or dark mode, and whether it is a TestFlight install — real values only if your app supplies them; otherwise placeholder values (no screen, no colour scheme, not TestFlight) are sent
- A hashed user id — only if your app calls
identify(), hashed on the device with your salt
- IP addresses — not stored with any event
- IDFA or any advertising identifier
- IDFV, Keychain values, device serial
- Location, of any precision
- Free text, screenshots, session replay
- Email, name or account identifier, unless you deliberately call
identify(), which hashes it first - Anything that links one app to another, or one device to another — unless your app calls
identify()with the same account id on several devices, which links them by design
Why the install id is not a person
The id starts as a random UUID generated on the device, is hashed with a salt you choose and commit with your app, and never leaves in raw form. It is scoped to one app: the same device running two apps produces two unrelated ids, and no backend can join them. Deleting the app deletes it. It counts installs, which is why the dashboard says "installs, not people" on the tile rather than letting you round it up to users.
The identity consent group is what keeps it. It is in the SDK's default since 0.3.0; withhold it (an app passes [.usage, .diagnostics], as the 0.2.0 default did) and the id becomes per-session instead of persistent: every session then counts as a new install, and retention numbers are gone.
No cookies, no banner code
The SDK sets no cookies, uses no web view, and sends no IP address to be retained. There is nothing for a consent banner to describe, and no ATT prompt: NSPrivacyTracking is false and there are no tracking domains.
What your own app must disclose is still yours to determine — declare Product Interaction, Other Diagnostic Data and, with identity consent on (the default since 0.3.0), Device ID, all not linked. The SDK's own privacy manifest declares those three; your nutrition label must match. Call identify() and you add User ID, and every category becomes linked to the user. This is a description of the SDK's behaviour, not legal advice.
Consent, and what it costs
usage — events and sessions. Denied: nothing is captured.diagnostics — OS version, device model, locale, region, screen, light or dark mode. Denied: documented fallbacks are sent instead.identity — a persistent install id, and the hashed user id from identify(). Granted by default since 0.3.0 (not on 0.2.0). Denied: per-session id, so installs count sessions, retention becomes unavailable and the dashboard says so on the tile.