feat(studio): posthog cookieless tracking with consent gating#3028
Conversation
ENG-9790: add cookieless_mode 'on_reject' so rejected/default opt-out users are tracked anonymously, wire Osano consent to PostHog opt-in/out (previously PostHog ignored consent entirely), and gate identify()/PII behind opt-in. Bump posthog-js to ^1.395.0 for cookieless_mode support.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughAdds Osano consent handling to Studio, updates PostHog initialization and runtime opt-in/opt-out behavior, and gates identify() calls behind PostHog opt-in. The PostHog client dependency is also updated. ChangesOsano Consent + PostHog Integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
studio/src/pages/_app.tsx (1)
30-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAlign the new Osano types and callbacks with the TS guidelines.
Use an interface for the consent object shape and annotate the local callback return types.
Proposed cleanup
-type OsanoConsent = { ANALYTICS?: string; MARKETING?: string }; +interface OsanoConsent { + ANALYTICS?: string; + MARKETING?: string; +} ... - const applyConsent = () => { + const applyConsent = (): void => { ... - const onOsanoReady = () => { + const onOsanoReady = (): void => {As per coding guidelines, TypeScript object shapes should prefer interfaces, and function return types should be explicit.
Also applies to: 83-95
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@studio/src/pages/_app.tsx` around lines 30 - 37, The Osano typings in _app.tsx use a type alias and leave callback/return annotations implicit, which does not match the TS guidelines. Replace the OsanoConsent type alias with an interface, and update the Osano.cm API declarations and the local consent-handling callback(s) to use explicit return types and parameter types. Use the existing Osano, getConsent, and addEventListener symbols to locate the declarations and keep the shape consistent across the related code.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@studio/src/lib/track.ts`:
- Around line 113-115: The consent check in track.ts only covers PostHog, but
setupReo(email) still runs in production and can send PII even when opt-in is
rejected or default. Update the tracking flow around the consent gate used in
the track function so Reo is only initialized when
posthog.has_opted_in_capturing() is true, or else adjust the nearby comment to
explicitly apply only to PostHog. Use the existing setupReo and
posthog.has_opted_in_capturing symbols to keep the behavior aligned.
In `@studio/src/pages/_app.tsx`:
- Around line 85-87: The consent-granted branch in _app.tsx only calls
posthog.opt_in_capturing() and reloadFeatureFlags(), so users who identified
before Osano opt-in can stay anonymous. Update the consent handling path around
posthog.opt_in_capturing() to immediately replay the current user/org identity
after opt-in, or have studio/src/lib/track.ts persist and restore a pending
identify payload so identify() is re-run once consent is accepted.
---
Nitpick comments:
In `@studio/src/pages/_app.tsx`:
- Around line 30-37: The Osano typings in _app.tsx use a type alias and leave
callback/return annotations implicit, which does not match the TS guidelines.
Replace the OsanoConsent type alias with an interface, and update the Osano.cm
API declarations and the local consent-handling callback(s) to use explicit
return types and parameter types. Use the existing Osano, getConsent, and
addEventListener symbols to locate the declarations and keep the shape
consistent across the related code.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 17edcf08-ebd8-4695-b441-72d598e3fe86
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
studio/package.jsonstudio/src/lib/track.tsstudio/src/pages/_app.tsx
Add useAnalyticsConsent hook (reactive Osano consent state) and re-run identify() from app-provider when consent is granted, replacing the module-level identity cache. Centralize the analytics-consent check in hasAnalyticsConsent.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
studio/src/pages/_app.tsx (1)
71-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAnnotate the new consent helpers with explicit return types.
applyConsentandonOsanoReadyare new TypeScript functions, so they should declare: voidexplicitly to match the repo rule. As per coding guidelines, "Use explicit type annotations for function parameters and return types in TypeScript".Suggested fix
- const applyConsent = () => { + const applyConsent = (): void => { if (hasAnalyticsConsent(window.Osano?.cm?.getConsent?.())) { posthog.opt_in_capturing(); posthog.reloadFeatureFlags(); } else { posthog.opt_out_capturing(); } }; - const onOsanoReady = () => { + const onOsanoReady = (): void => { applyConsent(); window.Osano?.cm?.addEventListener('osano-cm-consent-changed', applyConsent); };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@studio/src/pages/_app.tsx` around lines 71 - 83, Add explicit void return types to the new TypeScript helpers in _app.tsx: annotate both applyConsent and onOsanoReady as returning void. Update the function declarations directly where these consent-handling helpers are defined so they follow the repo rule for explicit parameter and return type annotations.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@studio/src/hooks/use-analytics-consent.ts`:
- Around line 19-21: The consent gate in hasAnalyticsConsent is too broad
because it treats MARKETING-only acceptance as analytics consent. Update
hasAnalyticsConsent so it returns true only when ANALYTICS is ACCEPT, and remove
the MARKETING fallback; keep this predicate as the sole check used by _app.tsx
and app-provider.tsx for PostHog opt-in and identify replay.
---
Nitpick comments:
In `@studio/src/pages/_app.tsx`:
- Around line 71-83: Add explicit void return types to the new TypeScript
helpers in _app.tsx: annotate both applyConsent and onOsanoReady as returning
void. Update the function declarations directly where these consent-handling
helpers are defined so they follow the repo rule for explicit parameter and
return type annotations.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d7cb5840-aa1b-457c-8afc-7ec4864aa5f6
📒 Files selected for processing (4)
studio/src/components/app-provider.tsxstudio/src/hooks/use-analytics-consent.tsstudio/src/lib/track.tsstudio/src/pages/_app.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- studio/src/lib/track.ts
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3028 +/- ##
==========================================
+ Coverage 46.53% 47.64% +1.11%
==========================================
Files 1120 1141 +21
Lines 154966 159485 +4519
Branches 10060 11060 +1000
==========================================
+ Hits 72107 75987 +3880
- Misses 81025 81641 +616
- Partials 1834 1857 +23
🚀 New features to boost your workflow:
|
Router-nonroot image scan passed✅ No security vulnerabilities found in image: |
Summary by CodeRabbit
New Features
Bug Fixes
Chores
Summary
Adds PostHog cookieless tracking with consent gating to the studio (ENG-9790).
Previously PostHog initialized and captured everyone fully — cookies and PII via
identify()— and ignored Osano consent entirely (Osano was only wired to Google Tag Manager). This change brings PostHog in line with the existing consent model:cookieless_mode: 'on_reject'so users who reject analytics or have no prior consent are tracked anonymously (no cookies, privacy-preserving hash) instead of fully.opt_in_capturing()/opt_out_capturing()(vanillawindow.Osano, mirroring the existing GTM consent handler).identify()/group association behindposthog.has_opted_in_capturing()so no PII is attached for non-consenting users.posthog-js^1.240.6→^1.395.0(required forcookieless_mode).Resulting behavior:
Note: Osano only loads in production, so in dev PostHog stays cookieless/anonymous.
Checklist
Closes ENG-9790