Events and privacy
What the SDK sends to Miniwall, what it never sends, what it stores on the device, how to answer the App Store and Google Play privacy questions, and how to turn analytics off.
What is sent
Only for screens loaded by placement or paywall ID, and only while analytics is not false. Screens from a JSON source send nothing.
| Event | When |
|---|---|
view | A screen is shown. Each screen of a flow is one. Counts toward your monthly views. |
close | The user closes the screen (including a toast fading out). |
purchase_click | A purchase button was tapped. |
purchase | onPurchase finished without returning false, or reportPurchase was called. |
purchase_cancel, purchase_error | onPurchase returned false, or threw. |
restore | A restore succeeded. |
action | A "Run your code" button was pressed, with its actionId. |
answer | A chosen option of a choice question, with fieldId and optionId. |
holdout | The user was held out. |
holdout_purchase | reportPurchase for a held-out user. |
Each event carries: the type, the screen's paywallId, version and placement, packageId where it applies, the A/B test id and side if a test picked the screen, a random visitorId, and a timestamp. Requests carry the header X-Miniwall-SDK with the platform and SDK version.
Events are queued on the device and sent in batches of up to 50, about 2 seconds after they happen. A batch that fails (no network, a server error) stays queued and is retried later; events older than 7 days are dropped. A key may send up to 1200 events a minute per server instance, after which the API answers 429 and events are dropped. Analytics never breaks your app.
What is never sent
- Attributes you pass for audiences. They are only compared on the device.
- Text typed into text fields. Only chosen options of choice questions are sent.
- Names, emails, advertising identifiers (IDFA, GAID), device identifiers or any user identity. The visitor ID is a random UUID created by the SDK, not tied to a person, and
resetcreates a new one. - Prices, amounts, or card data.
- The user's location. The locale is read on the device and used only to pick a language.
What is stored on the device
| Key or file | Where | Purpose |
|---|---|---|
uikit:vid | UserDefaults suite com.miniwall.sdk on iOS, SharedPreferences file com.miniwall.sdk on Android | The random visitor ID. |
uikit:shown: plus a placement | the same | Frequency counters and times seen. |
uikit:first-seen | the same | Date for the "Days since first visit" condition. |
uikit:pending-purchase, uikit:last-exposure | the same | The last buy tap and the last placement met (30 days), for reportPurchase. |
uikit:app-opens | the same | How many times the app opened, for the "every N th time" trigger. |
| Saved copies of published screens, the event queue, downloaded fonts | The app's cache directory | Offline use and sending events later. |
Everything stays inside your app's sandbox and is removed when the app is uninstalled.
App Store and Google Play answers
Based on what the SDK does, it collects app interaction data (views, taps and chosen answers) for analytics, linked to a random identifier that is not tied to a person. It does not track users across apps and sites. Check these answers against your own app's other data collection before you submit.
- iOS. The SDK ships a privacy manifest (
PrivacyInfo.xcprivacy). It declares no tracking, no tracking domains, Product Interaction data collected for analytics and not linked to the user's identity, and theUserDefaultsrequired-reason API (reasonCA92.1: the SDK reads only its own values). Xcode merges it into your app's privacy report. - Android. The library asks for the
INTERNETpermission only. In the Play Console Data safety form, declare app interactions collected for analytics, and describe the identifier as a random install ID. - If your app needs consent first (for example in the EU), call
configureand the other SDK functions after the user consents, or turn analytics off.
Turning analytics off
Miniwall.configure(apiKey: "pk_...", options: .init(analytics: false))No events are sent. Frequency limits and holdouts still work, because they are counted on the device. Analytics and results in the dashboard stay empty, and so does Usage for views from that app.