Appearance
Get started with ConsentLeaf
Cookie consent, beautifully simple. ConsentLeaf is a fork of CookieConsent v3.1.0 by Orest Bida, with a new visual identity and a warm teal theme.
Preview the design
From the repository root:
sh
pnpm install
pnpm build
pnpm docs:build
pnpm brand:devOpen http://localhost:4173 for the website, or http://localhost:4173/brand/ for the logo, colours, and live light and dark previews.
Add ConsentLeaf to your website
Manage website checks in the dashboard
The Websites list combines banner status with each site's latest check, observed cookie and recognised service totals, and its automatic check schedule. Use Check now to run another check, View report to review the findings, or Crawl settings to choose manual, weekly or monthly checks. Add website & start first check creates the site, starts its initial check, and opens Setup. Setup shows live progress, retry controls if the check cannot finish, and the remaining steps: review the draft, save and publish, then install and test the banner. The check continues in the background; recurring checks remain optional. Existing unpublished sites also open Setup, with a Start first check button when no check has run yet. The former /app/scans overview redirects to Websites; existing report URLs still work and recent reports remain linked from each site.
Detailed reports expire after seven days. The last check's date, status and aggregate totals remain with the website until that check is explicitly deleted, a new check replaces the summary, or the website is removed. Checks never publish banner changes automatically.
The initial check also imports the existing banner's colours, typography, corners and position when supported. Otherwise it suggests the website's styling. A retry can apply these suggestions to an untouched draft; your saved or manually edited design stays protected.
To delete a site, open Installation → Remove website. A confirmation dialog lists the data that will be permanently deleted, including all consent records, drafts, publication history, scan reports and crawl schedules. Download any records you need first, then enter the exact domain to confirm. Stored publication files are removed too; a failed storage cleanup retries automatically. Remove the installation snippet from the website. Re-adding the domain starts a fresh check.
Install the library
Copy this fork's dist folder into your public assets. The bundle filenames and API stay compatible with CookieConsent. The following example assumes the files are available at /dist/.
html
<link rel="stylesheet" href="/dist/cookieconsent.css">
<button type="button" data-cc="show-preferencesModal">
Cookie preferences
</button>
<script type="module">
import * as ConsentLeaf from '/dist/cookieconsent.esm.js';
ConsentLeaf.run({
guiOptions: {
consentModal: {
layout: 'box inline',
position: 'bottom right',
equalWeightButtons: true
},
preferencesModal: {
layout: 'box',
equalWeightButtons: true
}
},
categories: {
necessary: { enabled: true, readOnly: true },
analytics: {}
},
language: {
default: 'en',
translations: {
en: {
consentModal: {
title: 'A little note on cookies',
description: 'We use essential cookies to keep things running. With your permission, analytics help us improve the site.',
acceptAllBtn: 'Accept all',
acceptNecessaryBtn: 'Reject optional',
showPreferencesBtn: 'Choose preferences'
},
preferencesModal: {
title: 'Cookie preferences',
acceptAllBtn: 'Accept all',
acceptNecessaryBtn: 'Reject optional',
savePreferencesBtn: 'Save my choices',
closeIconLabel: 'Close preferences',
sections: [
{
title: 'Essential',
description: 'Required to run the site and remember your choices.',
linkedCategory: 'necessary'
},
{
title: 'Analytics',
description: 'Help us understand how the site is used.',
linkedCategory: 'analytics'
}
]
}
}
}
}
});
</script>Connect optional scripts using type="text/plain" and data-category, as described in script management. Update the copy, cookie information, and policy links to match your site.
Dark mode
Add cc--darkmode to your page's html element. Light mode uses white labels on teal buttons; dark mode uses dark labels on mint buttons.
js
document.documentElement.classList.toggle('cc--darkmode', useDarkTheme);The embedded widget uses system fonts and makes no font requests. See UI customization for CSS variables and layout options.
Distribution and attribution
ConsentLeaf uses private source and direct distribution of its built assets. Public npm publication is not planned. An authenticated private registry can be configured later for internal package distribution; npm publication is currently blocked in the package manifests.
Instructions elsewhere in the inherited documentation that install vanilla-cookieconsent or load the upstream CDN refer to the original project, which does not include this theme. Use this repository's built files for ConsentLeaf.
The consent engine and public API come from the upstream MIT-licensed project. Keep the included LICENSE when redistributing the library.
Hosted platform: what the banner controls
In the ConsentLeaf app, Integrations can manage scripts, pixels and embedded frames that you explicitly register. Remove their old installation and use the provided markup for frames. Cookie descriptions alone do not block requests; unmarked resources and server-side tracking still need developer integration. For existing scripts, use script management.
The hosted GA4 integration offers Basic (loads after analytics consent) and Advanced (allows cookieless requests before consent) modes. Install the generated tag before optional scripts, without async or defer. Tag Manager tags still need their own consent checks. The hosted settings button lets visitors change choices; withdrawing consent from an already loaded script reloads the page.
Published versions retain policy snapshots. Appearance changes preserve existing choices; policy changes request a new choice. Account members can inspect publication history. Central consent recording is off by default for each website. Enable Integrations → Consent recording → Store consent records centrally, then save and publish to record future choices and changes. Without recording, choices are remembered in the visitor’s browser and no receipts are sent or queued. Enabling recording is a policy change and requests a new choice; earlier choices are not backfilled. Turning it off also clears pending browser receipts on the next load and stops accepting receipts from older publications. Existing records remain available until they expire.
When recording is enabled, account members can download CSV or JSON from Consent records. Receipts link to the exact published configuration and are retained for 365 days. They do not verify visitor identity, and delivery may fail when requests or storage are blocked.
Connect application services
Prepare blocking rules from a scan
Open Integrations → Detected services, review the category, and choose Prepare blocking rules where standalone resource paths were observed. These rules control that individual service; they do not automatically install anything on the customer website. Unknown categories require your choice.
Matching script, iframe and image URLs assigned through supported JavaScript DOM APIs are held by the synchronous ConsentLeaf bootstrap until consent. Install its tag in the document head, before optional integrations, without async or defer. The shared engine/configuration can then download without releasing those resources prematurely.
For resources already written into HTML, replace their original markup. For example, given an approved script rule for https://metrics.example.org/sdk.js:
html
<script type="text/plain"
data-consentleaf-service="metrics"
data-consentleaf-src="https://metrics.example.org/sdk.js?id=YOUR_EXISTING_ID"></script>Use the real service ID and complete original URL, including its parameters. The dashboard generates this snippet when you paste the original URL. Keep the element's required nonce, integrity and other attributes. For modules also add data-consentleaf-type="module". Remove the original element and associated preloads/preconnects; do not install both copies. Gate any inline initialization code separately so it does not run before its library becomes available.
Rules match exact HTTPS hosts and paths, regardless of query parameters. Requests made through fetch, beacons, srcset, workers, application bundles, HTML parsing or other documents are not universally intercepted. A normal <script src> already processed by the HTML parser can be too early to block; use the inert markup above. The same applies to frames and pixels: use data-consentleaf-src with no src and the matching service ID.
Check Consent enforcement in Setup and Installation. It distinguishes missing connections, pending website changes and your own confirmations. A rescan can observe ConsentLeaf choices and report resource bypasses. It does not prove coverage of every service or replace testing rejection, granular choices, return visits and withdrawal on the actual site. Publishing creates testable files; it does not declare the installation verified.
For diagnostics, inspect window.ConsentLeaf.getDiagnostics(). Bypass results contain service IDs and reasons, never visitor cookie values. Existing CookieScript/Cookiebot API calls must be migrated to ConsentLeaf subscriptions; their consent cookies are not automatically imported.
Connect your application's SDK
The Integrations tab can add detected services as Connected by your site. This adds an individual choice to the banner. It does not install the vendor SDK. Connect your application to the public API before starting the service.
js
function connectConsent() {
const consent = window.ConsentLeaf;
if (!consent) return;
return consent.subscribe(state => {
if (!state.ready) return;
if (consent.acceptedService('posthog')) {
// Initialize your SDK once. Use the same service ID as the editor.
startAnalyticsOnce();
} else {
// Stop capture and send withdrawal to your own server, if needed.
stopAnalytics();
}
});
}
if (window.ConsentLeaf) connectConsent();
else window.addEventListener('consentleaf:ready', connectConsent, { once: true });The returned function unsubscribes. subscribe immediately sends the current state and then sends subsequent choices. getState() returns a new snapshot:
js
{
ready: true,
hasChoice: true,
siteId: 'your-site-id',
revision: 2,
categories: { necessary: true, analytics: true },
services: { posthog: false, 'sentry-replay': true }
}Use acceptedService(id) for a registered service. Category acceptance alone can be true while that service is rejected. Missing, expired or renewed consent returns false for optional services. Do not fall back to an older accepted choice from another CMP. Visitors make a fresh choice after migration.
acceptedCategory(category) reads a category, and showPreferences() opens the settings. Both consentleaf:ready and consentleaf:change window events contain a current snapshot in event.detail. Read the API on setup as well, so late listeners do not miss a choice. The API is version 1.
Withdrawal from an application service sends its change event and then reloads the page. This stops code and timers already loaded by that application. Make server withdrawal calls with an unload-safe transport. These client events are not proof of identity or authorization for your server.
Reviewed inventory linked to a service uses that individual choice for cleanup. Other reviewed inventory uses its category. Only exact first-party cookie names and same-origin storage keys can be removed. HttpOnly and third-party cookies need separate handling.
Leave the GA4 measurement ID empty to emit Google's consent signals without loading GA4. This supports sites with an existing tag setup. Configure consent checks inside GTM and connect its loader separately. Google documents the consent signal sequence.
Scan suggestions
Known cookies and browser storage can receive a draft category, service link and purpose. These are suggestions, not approval. Unknown entries remain incomplete. Persistent local storage has no browser expiry, so the scanner leaves its retention blank unless it has an explicit declaration. Review how the site actually removes that data.
Apply suggestions fills missing fields without replacing reviewed entries or existing text. The banner displays the saved, reviewed inventory after publication. Service choices and storage descriptions come from the same saved configuration, but the website still needs the matching integration code.
Banner languages
The standard consent dialog, preferences and cookie-table labels support 42 languages: Arabic, Basque, Bulgarian, Catalan, Chinese (Simplified and Traditional), Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, German, Greek, Hindi, Hungarian, Icelandic, Indonesian, Irish, Italian, Japanese, Korean, Latvian, Lithuanian, Malay, Maltese, Norwegian Bokmål, Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovenian, Spanish, Swedish, Thai, Turkish, Ukrainian and Vietnamese.
Automatic selection follows the page language, then browser preferences, then English. Chinese script and regional tags select the corresponding variant; Norwegian nb/nn tags fall back to the available Bokmål translation. Arabic uses a right-to-left dialog without changing the direction of the website. Each visitor downloads one saved language configuration. Default text does not consume the site's custom-translation allowance. Drafts and publications support up to 2 MB of custom text and inventory combined.
In Appearance, select Edit translation to edit the message, buttons, category explanations and message links for a language. Changing the language selects saved text; it does not translate custom text automatically. Imported wording and manual edits are preserved on subsequent imports.
Translate inventory details
In Cookies & categories, use Inventory text language to edit purpose and retention in any of the 42 supported banner languages. Default text keeps the original descriptions. An empty translated field falls back to its default; use Use default text for this language to remove that entry's override. The translation count shows how many entries have both fields filled in.
The preview and published banner use the same saved translations. With automatic banner language enabled, choosing an inventory language also selects the preview language. Public descriptions captured from an existing CookieScript or Cookiebot dialog retain their original language. Other custom translations are written and reviewed by the owner; selecting a language does not machine-translate them. Review all versions before marking an entry reviewed. Editing a translation resets that entry's review; publishing changed purpose or retention text requests fresh consent, including changes to translated text. Rescanning preserves existing translations.
Privacy framework scope
ConsentLeaf provides website consent and opt-out tools. A framework label describes those tools; it is not a certification of an organisation's legal compliance.
| Scope | Available controls | Website owner's work |
|---|---|---|
| GDPR / ePrivacy consent flows | Optional categories disabled initially, equally visible accept/reject, service preferences, purpose disclosures, withdrawal and optional receipts | Identify purposes and lawful bases, supply notices, connect and test tracking |
| LGPD consent-based cookie flows | The same opt-in and withdrawal controls; Portuguese banner and privacy-control text | Review purposes, necessary-cookie classification, notices and data-subject rights |
| POPIA consent-based cookie flows | Specific category/service choices, withdrawal and optional records; English text | Review lawful processing grounds, notices, proof requirements and rights processes |
| CCPA/CPRA sale/sharing opt-outs | Separate browser opt-out, GPC, visible applied status and mapped-category blocking | Map every affected category; propagate requests to accounts, backend systems and offline data where required |
The LGPD feature review follows the ANPD cookie guide. The POPIA review covers consent and withdrawal under section 11 of the Act. These reviews cover the listed consent-based website flows, not every obligation under either law.
Enable sale and sharing controls
In Consent integrations, enable Sale and sharing controls (CCPA/CPRA). Select every category containing sale of personal information or sharing for cross-site advertising. The suggested categories are Analytics and Marketing; review the mapping for your website. Save and publish to activate it. The setting applies to all visitors and does not use IP geolocation.
Visitors receive a permanent privacy control, an entry in the preferences panel and a visible status when an opt-out is applied. Browser navigator.globalPrivacyControl === true applies the opt-out without a click. It takes precedence over previously accepted cookies. Accept-all, removing GPC, changing the banner revision or disabling the controls do not erase an existing opt-out. Clearing the browser's storage can remove its remembered choice.
All 42 standard banner languages include privacy-control text. The opt-out is stored separately in a first-party cookie and local storage where available. It does not require an account or a request to ConsentLeaf. Existing opt-in behaviour continues for categories outside the selected mapping.
Add a visible control to your footer and privacy policy too:
html
<button type="button" data-consentleaf-privacy>
Do not sell or share my personal information
</button>Application integrations can read the independent preference and subscribe to changes. Always check ready before starting optional processing:
js
window.ConsentLeaf.subscribe(state => {
// Pass the preference to your own account/backend integration when applicable.
const optedOut = state.privacy.saleSharingOptOut;
const mayStart = state.ready && !optedOut && state.services['your-service'];
// Start/stop your integration using these values.
});
window.ConsentLeaf.showPrivacyChoices();The control restricts connected resources and marked scripts before they run. Withdrawing an already running integration reloads the page. Other scripts, server-set cookies, HTTP-only GPC signals, account data and offline processing require the website's own integration. There are no GPP strings, sensitive-data limitation flows, age verification or automated access/deletion-request workflows. The controls cannot currently be combined with TCF mode.
When central recording is enabled, privacy events include the applied opt-out, the observed GPC signal and its source in CSV/JSON exports. Recording is optional and off by default; requests are client-submitted. Hosted receipts expire after 365 days. CCPA request logs can require longer retention: export and retain the necessary records in your own process. The implementation review references sections 7025, 7026 and 7101 of the 2026 California regulations.
Consent Mode v2 is available for connected Google tags. Google-certified TCF CMP status, GPP and complete DMA coverage are not included.
Publisher advertising (TCF preview)
The publisher preview uses a separate TCF language catalog; the 42-language standard-banner expansion does not translate its official IAB purpose texts.
The app can configure and preview IAB TCF publisher consent, with separate purpose and partner choices, legitimate-interest objections, special-feature opt-ins, official vendor disclosures and Google Additional Consent partners. These choices are independent of ordinary cookie categories and managed services.
Live TCF publication is currently disabled pending Consentleaf's own IAB registration/validation and the applicable Google certification. Preview does not create a CMP API or consent strings. It overlays the draft on the original website; it does not replace that website's existing CMP or intercept its calls.
The implemented publisher runtime exposes the standard __tcfapi event API and ConsentLeaf.tcf.canProcess(vendorId, purposeIds, specialFeatureIds) for explicit application checks. Integrations must wait for usable consent state and respond to changes. ConsentLeaf.showPreferences() opens the publisher dialog in TCF mode. Ordinary acceptedService() checks continue to control managed services; accepting marketing alone does not grant TCF vendor/purpose consent.
Publisher choices and changes can be included in client-submitted consent records and their JSON/CSV exports. A stored receipt is not authenticated proof of a visitor's identity or a guarantee of compliance.