Skip to main content
This page explains how GDPR consent is captured, persisted, and enforced so analytics never run when consent is missing or denied.

How it works

This flow starts in the banner and ends with backend enforcement before tracking logic runs. When consent is unknown, the frontend treats tracking as denied by default. When consent is denied, backend middleware and resolver gates short-circuit analytics behavior. When consent is granted, normal analytics identity and event tracking continue.

Extending this system

Use this recipe when you add a new consent category or another analytics-related entry point.
  1. Add the new category flag in apps/portal/src/utils/gdprConsentCookie.ts.
  2. Render and wire that option in apps/portal/src/components/GdprConsentBanner.tsx.
  3. Parse and expose the new flag in apps/backend/src/utilities/gdprConsent.ts.
  4. Apply that flag to the relevant gate in apps/backend/src/middleware/analyticsSession.ts or apps/backend/src/gql/mutations/trackFrontendEvent.ts.
  5. Add tests in apps/backend/src/gql/mutations/__tests__/trackFrontendEvent.spec.ts, apps/backend/src/utilities/__tests__/analyticsIdentification.spec.ts, and apps/portal/src/components/__tests__/gdprConsentBanner.spec.tsx.
  6. Verify with:

What not to do

These anti-patterns are the most common ways consent enforcement drifts over time.
❌ Never default unknown consent to allowed. ❌ Never set analytics_aid when analytics consent is denied. ❌ Never skip consent checks in a new event mutation, webhook handler, or login identify flow.

File conventions

This keeps consent work predictable and easy for engineers and agents to extend.

What’s next?

These pages provide the closest implementation details for tracking and tooling integration.