
Consent-first product analytics for web and mobile apps
A practical checklist for consent-gated product analytics on web and mobile, and how marketing consent for Engage differs from analytics collection.
Regulators and platform policies pushed consent to the front of mobile and web shipping. Product teams still need funnels, experiments, and lifecycle triggers. The mistake is treating one toggle as permission for everything: product analytics, crash reporting, ads, and lifecycle email do not share the same legal or user-expectation bucket.
This post is a engineering-focused checklist for consent-first product analytics on React Native and web, plus how Rheo Engage fits when you need marketing consent separate from analytics. Honest scope: Rheo is not legal advice. Patterns here match how growth teams ship in the EU, UK, and US without collecting events into the void: or blasting email before consent exists.
Two consents, two pipelines
| Purpose | Typical legal basis (varies by region) | User expectation | Rheo surface |
|---|---|---|---|
| Product analytics, funnels, A/B metrics | Legitimate interest / consent (web) | "Help improve the app" | Analytics SDK after gate |
| Lifecycle email, promotional push | Marketing consent | "Send me offers and tips" | Engage automations |
| Strictly necessary | Contract / necessity | Login, billing, security | Always on |
Mixing them creates bugs: Engage fires win-back email to users who only accepted analytics, or web analytics fires before the CMP returns granted.
Rule of thumb: analytics events for measurement can often start after analytics consent (or LI with opt-out, depending on counsel). Engage journeys that promote the product need marketing consent on the profile.
Web: wait for the CMP, then initialize
On web, Rheo and other SDKs should not call init with full tracking until consent is known.
Recommended sequence
- Load app shell with no analytics network calls (or only anonymous, non-identifying pings if counsel approves).
- Render CMP (Cookiebot, OneTrust, custom banner).
- On
analytics: true, initialize Rheo Analytics with your app id. - On
marketing: true, enable Engage enrollment and marketing identifiers. - Persist consent version + timestamp on the user record for audit.
Web checklist
| Step | Implementation note |
|---|---|
| Block SDK init | Guard Rheo.init behind consent callback |
| Default denied | No pre-consent events in network tab |
| Re-consent | Handle CMP updates; re-run init or flush queue |
| GPC / DNT | Respect signals your policy promises |
| Session replay (if any) | Stricter gate than page views: often separate toggle |
User lands → CMP shown → analytics granted → Rheo.init({ analytics: true })
marketing granted → engage.enableMarketing()
If you use PostHog or Mixpanel on web in parallel, apply the same gate so you do not leak one vendor before consent while Rheo waits.
Mobile: ATT, GDPR, and in-app privacy screens
Mobile adds App Tracking Transparency (iOS), Google Play Data safety declarations, and in-app privacy settings.
iOS patterns
| Layer | What to gate |
|---|---|
| ATT prompt | IDFA-linked ad networks: not always product analytics |
| In-app privacy center | Analytics on/off, marketing email on/off |
| SDK init | Delay identifying events until user accepts in-app policy |
Product analytics using first-party app instance ids often sits below ATT for many teams, but EU users may still need explicit analytics consent in your privacy UI. Do not conflate "ATT denied" with "no analytics."
React Native checklist
| Item | Detail |
|---|---|
| Single consent module | Expose getAnalyticsConsent() / getMarketingConsent() to JS |
| Lazy SDK start | Native module no-ops until consent true |
| Pre-consent queue | Optional: queue events locally, flush once: cap queue size |
| Identify timing | Call identify only after account + consent align |
| Push tokens | Register for push only after marketing consent if pushes are promotional |
| Deep links | Do not auto-enroll Engage from campaign until marketing consent |
Expo and bare React Native share the same rule: native module init order matters. If a third-party SDK auto-starts in AppDelegate, you may leak events before JS consent runs: audit native dependencies.
Engage-specific: marketing consent on the profile
Rheo Engage automations: trial nudges, win-back email, feature adoption pushes: should check marketing consent (and channel preferences) before send.
| Automation type | Consent check |
|---|---|
| Transactional (receipt, password reset) | Usually outside marketing: use your auth/email stack |
| Lifecycle tips with upsell | Marketing |
| Win-back with discount | Marketing |
| "You stalled on onboarding" product email | Often marketing; counsel may treat differently if purely functional |
Sync consent from:
- Signup checkbox ("Send me product updates")
- Account settings toggle
- CMP marketing category on web
When consent is revoked, Engage should suppress future promotional sends and respect unsubscribe on email. Product analytics may continue only if analytics consent remains (region-dependent).
Data minimization for subscription apps
Subscription funnels tempt you to collect everything. Consent-first design collects what you use.
| Event | Collect when… | Skip when… |
|---|---|---|
onboarding_step_completed | Analytics consent | Pre-consent |
paywall_viewed | Analytics consent | Pre-consent |
| Email address for Engage | Marketing + account | Lead forms without opt-in |
| Revenue properties | Often server-side from RC/Stripe | Duplicating PAN or raw receipts in client events |
Server-side revenue from RevenueCat webhooks reduces client PII and keeps finance-aligned truth.
Testing consent flows
| Test | Pass criteria |
|---|---|
| Fresh install, deny all | No Rheo analytics requests in Charles/Proxyman |
| Grant analytics only | Funnel events appear; Engage promo does not send |
| Grant marketing | Engage test journey delivers to test user |
| Revoke marketing mid-journey | Next step suppressed |
| Web hard refresh | Consent read from storage; no double fire |
Automate at least one Detox/Maestro flow that asserts network silence before accept.
Rheo in a mixed analytics stack
Teams on Amplitude or PostHog for warehouse analytics sometimes run Rheo for Convert + Engage only. Consent still applies:
- Mirror consent flags into event properties (
analytics_consent: true) for downstream filtering. - Do not forward pre-consent events to third parties via integrations.
Operational ownership
| Role | Owns |
|---|---|
| Engineering | SDK gates, init order, consent APIs |
| Legal / DPO | Wording, basis per region |
| Growth | Which Engage journeys require marketing consent |
| Support | Privacy center UX and export/delete requests |
Ship a one-page consent matrix linked from your internal wiki before the next major SDK bump.
Consent-first analytics is slower to instrument once and faster forever: fewer incident calls, fewer angry reviews, and Engage that actually respects the checkbox users clicked.
Regional snapshots (not legal advice)
| Region | Common pattern for analytics | Marketing email/push |
|---|---|---|
| EU / UK | Explicit consent or strict LI with opt-out | Opt-in marketing consent |
| US state laws | Disclosure + opt-out for sale/share | CAN-SPAM unsubscribe |
| Apple platforms | Privacy nutrition labels match behavior | ATT for tracking across apps |
Align in-app copy with App Store and Play Data safety forms: reviewers compare screenshots to network traffic.
When analytics is "off" but product still works
Users who deny analytics consent should still complete onboarding and purchase. Rheo Convert flows render; only measurement and optional Engage segments that depend on denied events should degrade gracefully. Log locally in dev when a funnel step cannot be recorded so PMs do not confuse "zero conversion" with "zero traffic."
Start for free and configure Analytics and Engage with separate consent hooks in your React Native or web app.