GenerateSaaS

Integrations

Wire third-party analytics, support chat, and affiliate trackers behind a GDPR-aware cookie banner.

Third-party services are configured in @repo/config (packages/config/src/index.ts) and rendered entirely client-side - there is no backend package. Each provider turns on by the presence of its config sub-key; only consent-required scripts wait for the banner.

What this covers

Two distinct behaviors - don't conflate them. A provider can surface the banner (because it drops cookies) yet still load its script regardless of the visitor's choice. Only Google and PostHog actually wait for consent before tracking.

IntegrationConfig keyDrops cookiesSurfaces bannerWaits for consent
Google Analyticsconfig.analytics.googleYesYesYes
PostHogconfig.analytics.posthogYesYesYes
Privacy-focused analyticsconfig.analytics.{umami,plausible,openpanel,datafast,ahrefs,vercel}NoNoNo
Crisp chatconfig.support.crispYesYesNo - loads anyway
Affiliate trackersconfig.affiliate.{refgrow,affonso,promotekit}YesYesNo - pixels load anyway

Under the default cookieBanner: "auto", the banner appears only when a surfacing provider is enabled and the visitor is in a GDPR country (isGdprCountry from @repo/utils/helpers, which fails safe to true when geo is unknown). Out of the box no surfacing provider is enabled, so the banner stays hidden until you enable one (Crisp, a consent-required analytics provider, or an affiliate tracker).

All analytics and affiliate keys are public (publishable) and ship to the browser. Never paste a secret API key into config.

Frequently asked questions

Which integrations actually gate on consent? Only Google Analytics and PostHog hold their dispatch until consent. Crisp and the three affiliate pixels surface the banner (they drop cookies) but load regardless of the choice. Privacy-focused analytics (Umami, Plausible, OpenPanel, DataFast, Ahrefs, Vercel) never trigger the banner.

If I enable Crisp, why does the chat bubble appear before I accept cookies? Crisp surfaces the banner under "auto" because it drops cookies, but the widget is not held back - it loads as soon as config.support.crisp is set. Affiliate pixels behave the same way.

What does declining do? The choice persists in a tri-state acceptedCookies cookie. "false" keeps Google/PostHog tracking off; Crisp and affiliate pixels still load (their presence only surfaced the banner).

Do these run during local development? No. Each group has its own enableInDev flag (config.analytics.enableInDev, config.support.enableInDev, config.affiliate.enableInDev), all defaulting to false. The flag also gates the "auto" banner: a provider counts toward the trigger only when its script would actually load.

Next steps

On this page