GenerateSaaS

Cookie consent

Gate cookie-dropping analytics, chat, and affiliate scripts behind a GDPR consent banner with config.cookieBanner and config.consentPolicy.

The consent banner is configured in @repo/config and rendered client-side. config.cookieBanner governs whether it shows and which scripts wait on it; config.consentPolicy governs which visitors must answer it.

The three banner modes

config.cookieBanner is a required key typed boolean | "auto"; generated projects ship "auto".

ValueBehavior
trueBanner always shows; consent-required scripts wait for it.
falseBanner never shows; every script loads freely, no consent.
"auto" (shipped)Banner shows only when a cookie-dropping provider is enabled and the visitor must consent.

Under "auto" a cookie-dropping third party must be enabled: consent-required analytics (config.analytics.google, posthog), support chat (config.support.crisp, chatwoot), or an affiliate tracker (config.affiliate.refgrow, affonso, promotekit). Privacy-focused analytics (umami, plausible, openpanel, datafast, ahrefs, vercel) drop no cookies and never trigger or wait on the banner.

Out of the box no cookie-dropping provider is enabled, so the banner stays hidden. In development a provider counts only when its enableInDev flag is set (config.analytics, config.support, config.affiliate); in production every enabled provider counts.

config.consentPolicy decides which visitors must answer explicitly; everyone else is granted automatically once geo detection settles, so US visitors never see a banner.

ValueBehavior
"gdpr-and-unknown" (default)GDPR-country visitors and visitors whose country can't be detected must consent - fail-safe.
"gdpr-only"Only visitors detected in a GDPR country must consent; undetected visitors are granted automatically.
"everyone"Every visitor must consent explicitly; nobody is granted automatically.
"never"Consent is implicit for everyone - the banner never shows and all analytics fire instantly (equivalent to cookieBanner: false).

isGdprCountry (@repo/utils/helpers) fails safe - an unknown location counts as GDPR, so undetected visitors see the banner under the default policy. Set consentPolicy: "gdpr-only" to auto-grant them instead.

The visitor's choice persists in a tri-state acceptedCookies cookie:

Cookie valueMeaning
"true"Consented - cookie-dropping scripts load.
"false"Declined - consent-required scripts stay off; support chat and affiliate pixels still load (they only surface the banner).
unsetNo choice yet - the banner shows when its surfacing conditions hold; consent-required scripts wait.
  • Google Analytics loads only on grant - gtag.js pings nothing and drops no cookie beforehand. Grants carry the full Consent Mode v2 signal set, ad_user_data / ad_personalization included.
  • Withdrawing consent also clears the identity held meanwhile (GA user_id: null, PostHog reset()); the withdrawal survives that clearing and a later sign-out.
  • Privacy-focused providers keep their identity on withdrawal - it never gated on consent.
  • Traits wait for consent: with a banner required, privacy-focused providers get the pseudonymous id at once, email/name and attribution only after consent.

cookieBanner: false (equivalent to consentPolicy: "never") loads every script with no consent gate - only for projects with no cookie-dropping providers or outside consent-law jurisdictions.

Other first-party cookies

CookiePurpose
first_touchFirst-visit attribution (UTM tags, referrer, landing page) - 90 days, no identifier, written independently of the banner. Full attribute table: Pageviews and attribution.

On this page