Cookie consent
Nobody loves cookie popups, but in a lot of countries they’re a legal must. This guide shows you how to add or remove cookies dynamically using the built-in Cookie Consent modal, specifically for non-essential cookies (e.g., analytics, marketing) that aren’t needed for core app functionality.
Cookie Consent Modal — files & edits
Path: app/src/client/components/cookie-consent/
Files:
Banner.tsx
shows the banner at the bottom of the pageConfig.ts
defines which cookies or scripts are injected
Banner.tsx
is imported in app/src/client/App.tsx
. All behavior and content changes are done in Config.ts
.
Library choice
We use the vanilla-cookieconsent
library with mostly default settings. For advanced options, refer to the library’s documentation.
Setup flow
- Decide which tools set non-essential cookies (for example Google Analytics or any marketing tags).
- Configure those scripts in
Config.ts
so the banner can inject or remove them on accept or reject. - Test in your browser by toggling consent and watching cookies appear or disappear.
Google Analytics
In this template we rely on the onAccept callbacks to inject or remove GA scripts. For it to work, set your GA ID in .env.client.
REACT_APP_GOOGLE_ANALYTICS_ID=G-1234567890
All set. The consent modal now toggles Google Analytics cookies according to the user’s choice.
To verify, open your browser dev tools → Cookies tab; you should see the cookies below appear/disappear based on consent.
_ga
_ga... # Google Analytics cookies.
cc_cookie # Cookie Consent cookie. The name can be changed in Config.ts.
Plausible Analytics
Plausible does not use cookies. You do not need consent for Plausible. It collects anonymous, aggregate usage data without personally identifiable information. By avoiding cookies, you avoid the banner requirement for analytics.
Add your policy links
Add links to your terms and privacy policy in the consent modal footer. Edit consentModal
in config.language
inside Config.ts
.
language: {
default: 'en',
translations: {
en: {
consentModal: {
title: 'We use cookies',
// ...
// TODO: Add your own privacy policy and terms and conditions links
footer: `
Privacy Policy
Terms and Conditions
`,
},
},
},
}
Allow users to choose specific Cookies (optional)
Added more than Google Analytics? Give users a choice. You might, for instance, let them reject marketing cookies but keep analytics on.
Use preferencesModal.sections
in config.language
, and ensure each section’s linkedCategory
matches a category in config.categories
. Also add showPreferencesBtn
to consentModal
to open the preferences panel.
language: {
default: 'en',
translations: {
en: {
consentModal: {
// ...
showPreferencesBtn: 'Manage Individual preferences', // This opens the preferences panel
},
preferencesModal: {
title: 'Manage cookie preferences',
acceptAllBtn: 'Accept all',
acceptNecessaryBtn: 'Reject all',
savePreferencesBtn: 'Accept current selection',
closeIconLabel: 'Close modal',
serviceCounterLabel: 'Service|Services',
sections: [
{
title: 'Your Privacy Choices',
description: `In this panel you can express some preferences related to the processing of your personal information.`,
},
{
title: 'Strictly Necessary',
description: 'These cookies are essential for the proper functioning of the website and cannot be disabled.',
linkedCategory: 'necessary',
},
{
title: 'Performance and Analytics',
description: 'These cookies collect information about how you use our website.',
linkedCategory: 'analytics',
cookieTable: {
caption: 'Cookie table',
headers: {
name: 'Cookie',
domain: 'Domain',
desc: 'Description',
},
body: [
{
name: '_ga',
domain: location.hostname,
desc: 'Description 1',
},
{
name: '_gid',
domain: location.hostname,
desc: 'Description 2',
},
],
},
},
{
title: 'YouTube',
description: 'This service is used to display video content.',
linkedCategory: 'youtube',
cookieTable: {
// ...
}
},
{
title: 'More information',
description: 'For any queries in relation to my policy on cookies and your choices, please contact us.',
},
],
},
},
},
}
What’s next?
Now it’s time to head over to the Deploying section.