# What the mobile SDKs send

> Every data field the Whisperr Swift, React Native and Flutter SDKs send, for your App Store privacy and Google Play Data safety answers.

This page lists the data that the Whisperr mobile SDKs (Swift, React Native, Flutter) send to `https://api.whisperr.net` over HTTPS. Use it to fill in the [App Store privacy answers](/privacy/app-store/) and the [Google Play Data safety answers](/privacy/google-play/). You own your app’s answers: also add the data that the rest of your app collects.

## What do the SDKs send with no code from you?

| Data                                 | What it is                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `anonymous_id`                       | A random ID that the SDK creates on the device. It identifies the device before `identify()`. `reset()` creates a new one.                                                                                                                                                                                                                                                                                                                                             |
| Automatic events                     | `app_installed`, `app_updated`, `app_opened` (with `cold_start`) and `app_backgrounded` (with `foreground_ms`). `trackAutomaticEvents: false` (Flutter), `trackAppLifecycleEvents: false` (React Native) or `automaticEvents: false` (Swift) turns them off.                                                                                                                                                                                                           |
| Launch source and visit counts       | From React Native 0.7.0, Flutter 0.8.0 and Swift 0.7.0. `app_opened` adds `launch_source` and, for a link, the redacted path (`link_route`, ids replaced by `:id`), the host of an http(s) link (`link_host`) and the link’s `utm_source`, `utm_medium` and `utm_campaign`. It never sends the full URL or the query. A push or email open adds the Whisperr message ID. `app_backgrounded` adds the session ID and counts of screens, events and errors in the visit. |
| Errors (`app_error`)                 | From the same versions. For an uncaught error, and for each `trackError()` call: the error type (`error_name`, such as `TypeError`), a `fingerprint` (a hash of the type and the top three function names of the stack), the kind, whether it was fatal, and the last screen name. Never the error message, the stack, file paths or URLs. `captureErrors: false` turns off the automatic capture; `trackError()` still sends.                                         |
| Crashes (`app_crashed`)              | From the same versions. On the next launch after the app ended while in the foreground: the crash kind, how it was detected, the app version, session ID and last screen name of that run. Debug builds never send it. It follows the automatic-events switch above.                                                                                                                                                                                                   |
| App and device context               | Automatic events carry `app_version`, `app_build`, `platform`, `os_name`, `os_version`, `sdk_name`, `sdk_version`, `locale`, and `timezone` or `timezone_offset_minutes`. Every event carries `app_version`, `app_build`, `platform`, `sdk_name` and `sdk_version` in its `context`. The React Native SDK also puts the OS name (`os`) and the SDK name and version (`library`) there.                                                                                 |
| Event metadata                       | The time of each event (`occurred_at`) and a random `$message_id` per event, used to remove duplicates. A random `session_id` that changes after 30 minutes without events (React Native; Flutter from 0.8.0 and Swift from 0.7.0, where it also changes on each cold start).                                                                                                                                                                                          |
| Notification permission (Swift only) | The Swift SDK reads the permission each time the app comes to the foreground and sends `push_permission_changed` when it changed. From 0.7.0 it also sends the notification settings the device exposes (`alerts_enabled`, `lock_screen`, `scheduled_summary`, `time_sensitive`). `automaticPushPermission: false` or `automaticEvents: false` turns this off.                                                                                                         |
| Restore identify                     | At app start, for a user your app identified before: the user ID, the `anonymous_id`, the `locale`, the time zone and the app language.                                                                                                                                                                                                                                                                                                                                |

## What do the SDKs send only when your code passes it?

| Data                         | Call                                                                                                                                                                                                                                                                                                              |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| User ID                      | `identify(userId)`: your app’s own ID for the user.                                                                                                                                                                                                                                                               |
| Events and screens           | `track()` and `screen()`, with the properties you pass.                                                                                                                                                                                                                                                           |
| Traits, such as a first name | `identify(userId, traits: …)`. `identify()` adds `locale` and the time zone (`timezone`, or `timezone_offset_minutes` in Flutter).                                                                                                                                                                                |
| Email address                | An email channel or the `email` parameter in `identify()`.                                                                                                                                                                                                                                                        |
| Phone number                 | The `phone` parameter or a phone channel in `identify()`. Whisperr does not send SMS today, so you don’t need to send a phone number.                                                                                                                                                                             |
| Push token                   | `setPushToken()`. With the token, the SDK sends its kind (`fcm`, `apns`, `expo` or `onesignal_sub`), the `platform`, the app’s bundle ID or package name (`client_app_id`), the Firebase, EAS or OneSignal project ID (`provider_project`), and for APNs tokens the environment (`push_env`), when it knows them. |
| Notification permission      | React Native and Flutter: `setPushPermission()`, or `requestPushAuthorization()` in React Native. It sends `push_permission_changed` with the status when it changed.                                                                                                                                             |
| Push opens                   | `trackPushOpened()` (Swift: `handleNotificationResponse()`) sends `push_opened` with the Whisperr message ID, the deep link, `action_id` and `cold_start`.                                                                                                                                                        |
| Push receipts                | `trackPushReceived()` (Swift: `handleWillPresent()`; Flutter: `whisperr_firebase_messaging` calls it) sends `push_received` for a Whisperr push.                                                                                                                                                                  |
| App language                 | `setAppLanguage()`: the language the user picked in your app, as the trait `app_language`.                                                                                                                                                                                                                        |

Whisperr drops event property keys that are named like personal data, such as `email`, `phone` or `first_name`. It also drops trait values that are email addresses or phone numbers. Send those as channels.

## What does Whisperr add that the SDK does not send?

| Data    | What it is                                                                                                                                                                                                                                                       |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Country | For each event sent with the publishable key, Whisperr derives the country (an ISO 3166-1 alpha-2 code such as `DE`) from the request’s IP address at its edge and stores it as `context.country`. A `country` the app already put in the event context is kept. |

Declare this as approximate location if your answers count a country as location. See the [App Store](/privacy/app-store/) and [Google Play](/privacy/google-play/) pages.

## What do the SDKs not collect?

The SDKs do not read the advertising ID (IDFA, Android advertising ID), the identifier for vendor, the device model or name, GPS or other device location, contacts or photos. They do not put the IP address in any payload. Whisperr still derives a country from the IP address of each event request (see above). The Swift SDK’s privacy manifest declares no tracking (`NSPrivacyTracking` is `false`).

## What do the SDKs store on the device?

The SDKs keep their queue, the user ID, the `anonymous_id`, the opt-out choice, the last push token sent, the last notification permission reported, the app language, the last app version seen, the IDs of push messages already reported, and a record of the last identify sent (the user ID, the locale, time zone and app language it carried, and the time), used to skip a repeated restore identify. The React Native SDK also keeps its `session_id`. From React Native 0.7.0, Flutter 0.8.0 and Swift 0.7.0 the SDKs also keep a running-visit record (session ID, last screen name, app version) while the app is in the foreground, used to detect `app_crashed`. The Swift SDK uses `UserDefaults` and declares it in its privacy manifest with reason `CA92.1`. The Flutter SDK uses `shared_preferences`. The React Native SDK uses AsyncStorage when it is installed, or the storage adapter you pass.

## How does Whisperr use the data, and how do I delete it?

Whisperr uses the data to predict churn and to send your retention messages. For your users’ data, Whisperr is your processor. It does not sell personal data or use it for advertising. See the [privacy policy](https://whisperr.net/privacy/), in particular [Retention](https://whisperr.net/privacy/#retention) and [Your rights](https://whisperr.net/privacy/#rights).

When a user asks you to delete their data, call [`DELETE /v1/users/{external_id}`](/api/data-subjects/) from your backend with the server key. `optOut()` stops new data from the device, but it does not delete data that Whisperr already has.

## Common questions

### Do the Whisperr mobile SDKs read the advertising ID?

No. The Swift, React Native and Flutter SDKs do not read the IDFA, the Android advertising ID or the identifier for vendor. Their only device-level IDs are a random anonymous_id they create and the push token you pass.

### Can a user stop the SDK from sending data?

Yes. Call optOut(). The SDK deletes its queue and sends nothing until optIn(), except requests that opt this device's push token out. Data already sent stays on the server until you erase it.

### How do I delete a user's data from Whisperr?

Call DELETE /v1/users/{external_id} from your backend with the server key (wrk_…). The publishable key in your app cannot erase data.

Source: https://docs.whisperr.net/privacy/sdk-data/
