Consent in apps
You choose how consent works in your app, per app and in code. X3 gives you three modes, four
separate purposes, a consent sheet for the first launch and a privacy settings screen, and it
enforces your choice on the device and on the server. There is no hidden default: consent.mode is
a required option of configure, so the decision is always a conscious one.
You decide how consent works in your app, and you are responsible for that decision. X3 implements your choice technically but does not check whether it is legally right for your users and countries. Clarify the legal basis with your privacy counsel and describe X3 in your privacy policy and in the App Store and Google Play privacy details.
This page explains the technical behaviour and lists typical obligations. It is not legal advice.
Consent modes
| Mode | Dashboard label | Before a decision | After a grant | After a denial or opt-out |
|---|---|---|---|---|
always | Immer an (Always on) | sends everything your app enabled, from the first launch | no change | only setOptOut(true) (for example the switch in your settings) or a purpose set to false stops it |
opt_in | Opt-in | sends nothing: no config request, no batch, no install request, no recording; the purposes are pending | the granted purposes start at once (install id, session, config) | nothing is sent; with bufferUntilDecision the in-memory buffer is dropped |
opt_out | Opt-out | sends everything your app enabled, from the first launch | no change; explicit choices are remembered | the denied purposes stop at once; an opt-out stops everything and deletes the local data |
Choose the mode in configure:
X3.configure(key: "pk_3x_YOUR_APP_KEY", options: X3Options(consent: X3ConsentOptions(mode: .optIn)))X3.configure(context, "pk_3x_YOUR_APP_KEY", X3Options(consent = X3ConsentOptions(mode = X3ConsentMode.OPT_OUT)))X3.configure("pk_3x_YOUR_APP_KEY", { consent: { mode: "always", purposes: { adPlatforms: true } } });await X3.configure('pk_3x_YOUR_APP_KEY', const X3Options(consent: X3ConsentOptions(mode: X3ConsentMode.optIn)));Typical choices (your counsel decides): opt_in for apps with users in the EU when you rely on
consent; opt_out where your legal basis allows measurement by default with an easy way out;
always when you have another legal basis (for example outside the EU, or an internal company app)
and still offer an opt-out in your settings. The dashboard shows the mode each app reports
(Einstellungen › Apps), so you can check every release.
Buffer until a decision. In opt_in mode the option bufferUntilDecision: true keeps this
process's events in memory (at most 200, never on disk) until the user decides: granted, they are
sent; denied, they are dropped. Without it, everything before the decision is lost on purpose.
Changing the mode between app versions. Persisted decisions keep their meaning: a user who
granted analytics in an opt_in version stays granted after you switch to opt_out, and a user who
opted out stays opted out.
Purposes
| Purpose (code) | Dashboard and sheet label (DE / EN) | Covers | Enforced |
|---|---|---|---|
analytics | Nutzung messen / Usage analytics | install id, sessions, screens, events, identify, the offline queue, config requests | on the device: nothing is sent without it; on the server: batches without it are not stored |
attribution | Herkunft der Installation / Install attribution | reading the Play Install Referrer and the Apple Ads token, SKAdNetwork and AdAttributionKit conversion value updates, deep link attribution | on the device; the server stores installs without it with tier unknown |
recordings | Sitzungen aufzeichnen / Session recordings | wireframe and screenshot recordings | on the device (recorder off) and the server (packets refused) |
adPlatforms | Werbung messen / Ad measurement | reporting conversions of this person to Meta, Google Ads, TikTok and LinkedIn | on the server: no upload for the session without it |
purposes in configure says which purposes your app uses at all. Defaults: analytics and
attribution on, recordings and adPlatforms off. A purpose that is not used is never asked for
and never active. analytics is the base: without it nothing else is sent either.
Each batch carries the consent mode and a four-letter consent string in the order analytics,
attribution, recordings, adPlatforms, with g granted, d denied, p pending and x not
used: gdxx means analytics granted, attribution denied, recordings and ad platforms not used.
State rules
The effective state of a used purpose:
| Situation | State |
|---|---|
the user opted out (setOptOut(true)) | denied |
mode always or opt_out, and the user did not deny this purpose | granted |
mode always or opt_out, and the user denied this purpose (consent(…: false)) | denied |
mode opt_in, the user granted this purpose | granted |
mode opt_in, the user denied this purpose | denied |
mode opt_in, no decision yet | pending |
X3.consentState() returns the mode, the four states, optedOut and needsDecision (mode
opt_in, some used purpose still pending, not opted out). Show your consent screen when
needsDecision is true.
Decisions are stored in consent.json in the SDK's private directory, the only file the SDK writes
while analytics is not granted. Only explicit decisions are stored; a later version of your app
reads them back.
Transitions
| Change | What happens at once |
|---|---|
| any purpose granted | that purpose starts; the first grant of analytics creates the install id, the device secret and the session |
analytics denied | everything stops; the queue (memory and disk), install id, device secret, identity, account token and cached config are deleted; nothing more is sent. A later grant starts a new install (new install id, the original install source is lost) |
attribution denied | no more attribution reads or conversion value updates; an install request not sent yet is never sent |
recordings denied | the recorder stops and sends one revoke packet: X3 deletes this session's recordings |
adPlatforms denied | the next batches say so; X3 stops uploads for this session |
setOptOut(true) | all used purposes denied, with the effects above |
setOptOut(false) | back to the mode's states; explicit decisions are kept |
Changing consent from code
X3.consent(X3ConsentUpdate(recordings: true, adPlatforms: false)) // per purpose
X3.consentAll(true) // every used purpose
X3.setOptOut(true) // the "Allow measurement" switch off
let state = X3.consentState()
let subscription = X3.onConsentChange { state in } // main queue; subscription.cancel()Kotlin X3.consent(X3ConsentUpdate(recordings = true)), X3.addConsentListener { state -> };
React Native X3.onConsentChange(listener) returns an unsubscribe function; Flutter
X3.consentChanges is a stream.
Consent management platforms. X3 has no adapters for mobile CMPs. Call X3.consent(…) from your
CMP's callback (Usercentrics, OneTrust, Didomi and others), mapping your CMP's categories to the four
purposes, and set the mode to opt_in.
Consent UI helpers
The helpers never show themselves; you decide when. They follow the device language (de* →
German, otherwise English), support Dynamic Type and font scaling, VoiceOver and TalkBack, 44 pt / 48
dp touch targets and light and dark appearance.
| Helper | iOS (X3KitUI) | Android | React Native | Flutter |
|---|---|---|---|---|
| consent sheet | X3ConsentView(texts:onDone:), X3.presentConsent(from:texts:completion:) | X3ConsentDialog.show(activity, texts) { state -> }, Compose X3ConsentSheet(...) | <X3ConsentSheet visible onDone texts /> | X3ConsentSheet.show(context, texts: …) |
| settings | X3PrivacySettingsView(texts:), X3PrivacySettingsViewController | X3PrivacySettingsDialog.show(activity, texts), Compose X3PrivacySettings(...) | <X3PrivacySettings texts /> | X3PrivacySettings(texts: …) |
Consent sheet. Lists the used purposes (usage analytics first, then install attribution, session recordings, ad measurement) with a switch each (on for granted, off otherwise), a link to your privacy policy when you set its URL, and three equally prominent buttons: Alle akzeptieren (grant all used purposes), Ablehnen (deny all used purposes), Auswahl speichern (apply the switches).
Settings. The same switches, applied immediately. In mode always it shows an info line and one
switch Messung erlauben (Allow measurement) bound to setOptOut.
Default texts (override any of them with X3ConsentTexts; {app} is the app's display name or
appName):
| Key | DE | EN |
|---|---|---|
title | Hilf uns, {app} besser zu machen | Help us improve {app} |
body | Wir möchten verstehen, wie Du {app} nutzt. Du entscheidest, was erlaubt ist, und kannst Deine Wahl jederzeit in den Einstellungen ändern. | We would like to understand how you use {app}. You decide what is allowed and can change your choice in the settings at any time. |
analytics.title | Nutzung messen | Usage analytics |
analytics.text | Welche Bildschirme Du öffnest und welche Funktionen Du nutzt. Hilft uns, die App zu verbessern. | Which screens you open and which features you use. Helps us improve the app. |
attribution.title | Herkunft der Installation | Install attribution |
attribution.text | Über welche Anzeige oder welchen Link Du zu uns gekommen bist. | Which ad or link brought you to us. |
recordings.title | Sitzungen aufzeichnen | Session recordings |
recordings.text | Eine vereinfachte Aufzeichnung Deiner Bildschirme. Eingaben werden nie aufgezeichnet. | A simplified recording of your screens. What you type is never recorded. |
adPlatforms.title | Werbung messen | Ad measurement |
adPlatforms.text | Wir melden Anmeldungen und Käufe an Werbepartner wie Meta oder Google, um unsere Werbung zu verbessern. | We report sign-ups and purchases to ad partners such as Meta or Google to improve our ads. |
acceptAll | Alle akzeptieren | Accept all |
rejectAll | Ablehnen | Reject |
save | Auswahl speichern | Save choice |
privacyPolicy | Datenschutzerklärung | Privacy policy |
settings.title | Datenschutz | Privacy |
settings.alwaysInfo | Diese App misst die Nutzung, um sie zu verbessern. | This app measures usage to improve it. |
settings.allow | Messung erlauben | Allow measurement |
indicator | Aufnahme | Recording |
If you change texts, keep them accurate: they must describe what your app really does with each purpose, and Ablehnen must stay as easy to reach as Alle akzeptieren.
Your obligations
Whatever mode you choose, you are the controller of your users' data and X3 is your processor. You are responsible for the legal basis and for what you tell your users and the stores. Typical obligations (check them with your privacy counsel):
- Privacy policy. Name X3 Growth Intelligence (good vibes GmbH, Gartenstrasse 7, c/o excent AG, Zweigniederlassung Zug, 6300 Zug, Switzerland) as your processor, the purposes you use (usage analytics, install attribution, session recordings, ad measurement), what is collected (install id, screens and events, hashed user id and e-mail, purchases, campaign of the install, coarse location derived from the IP address), the ad platforms you report to, retention and the users' rights. The privacy policy template for websites is a starting point.
- App Store privacy details. Declare the data types of the modules you use in App Store Connect (table). Apple counts hashed e-mail addresses as e-mail addresses.
- App Tracking Transparency. When iOS conversions with user data (hashed e-mail, user id) go to
ad platforms, Apple treats that as tracking: ask for ATT permission, declare tracking in App Store
Connect, and set
adPlatformsaccordingly. X3 sends iOS user data to ad platforms only with ATTauthorized(ATT rule). - Google Play data safety. Fill in the data safety form with the Play rows for your modules.
- GDPR legal basis. Processing needs a legal basis (Art. 6 GDPR): consent (Art. 6(1)(a)) or, only after your own documented assessment, legitimate interest (Art. 6(1)(f)). Recordings and reporting to ad platforms are typically consent cases.
- Device access (§ 25 TDDDG, formerly TTDSG, and Art. 5(3) ePrivacy). Storing the install id on the device and
reading device information (install referrer, Apple Ads token, ATT status) is access to the
terminal equipment in the sense of § 25 TDDDG and Art. 5(3) of the ePrivacy Directive; the EDPB
guidelines 2/2023 on its technical scope apply to apps as much as to browsers. Unless an exception
applies, this needs consent;
opt_inis the mode for that. - Data subject rights. Answer access and deletion requests. Delete a user's app data with
POST /v1/projects/{project}/app-users/erase(by user id, e-mail or install id); Apple also requires account deletion inside apps that offer accounts. - Data processing agreement. Conclude the DPA (Art. 28 GDPR) with X3 before you go live (processor and DPA).
- Recordings. Apple's App Review Guideline 2.5.14 requires explicit consent and a clear visual indication when an app records user activity; keep the recording indicator on.
X3 makes no promise of legal compliance on your behalf, and your texts should not either without your counsel's review.
You decide how consent works in your app, and you are responsible for that decision. X3 implements your choice technically but does not check whether it is legally right for your users and countries. Clarify the legal basis with your privacy counsel and describe X3 in your privacy policy and in the App Store and Google Play privacy details.
Health projects
Projects with the health preset keep stricter rules regardless of the mode you choose:
- recordings are accepted only from an explicit opt-in grant: an app in mode
alwaysoropt_outrecords nothing in a health project, and the server refuses its packets; - conversions are uploaded to ad platforms only from explicit opt-in grants of
adPlatforms; - the health preset's recording rules apply as on the web: masking relaxations are locked, more screens are excluded and recordings cannot be shared by link (recordings);
- health data needs explicit consent (Art. 9 GDPR): use
opt_infor every purpose.
What the server checks
| Request | Rule |
|---|---|
| batches | stored only when analytics is granted; otherwise answered stored: false with reason consent |
| install request | without attribution granted the install is stored without sources (tier unknown) |
| recording packets | need analytics and recordings granted; in health projects also mode opt_in |
| ad platform uploads | need adPlatforms granted in the session; iOS user data only with ATT authorized; health projects only from opt-in grants |