Configuration
All configuration options for Zest cookie consent
Configuration Methods
Zest can be configured in three ways (in order of priority):
window.ZestConfigobject - Highest priority- Data attributes on the script tag
- Default values - Lowest priority
Using ZestConfig Object
<script>
window.ZestConfig = {
position: 'bottom-right',
theme: 'auto',
accentColor: '#0071e3',
policyUrl: '/privacy-policy',
mode: 'safe',
expiration: 365
};
</script>
<script src="https://cdn.jsdelivr.net/npm/@freshjuice/zest"></script>
Using Data Attributes
<script
src="https://cdn.jsdelivr.net/npm/@freshjuice/zest"
data-position="bottom-right"
data-theme="auto"
data-accent-color="#0071e3"
data-policy-url="/privacy-policy"
data-mode="safe"
data-expiration="365"
data-geo="on"
data-branding="false"
data-button-style="outline"
data-button-layout="split"
data-backdrop-blur="8"
data-hard-wall="on"
data-hide-categories="analytics,marketing"
data-consent-mode-google
data-consent-mode-microsoft
></script>
Complete Options Reference
UI Options
| Option | Type | Default | Description |
|---|---|---|---|
position |
string | 'bottom' |
Banner position: 'bottom', 'bottom-left', 'bottom-right', 'top', 'top-left', 'top-right', 'center' (v2.6.0+) |
theme |
string | 'auto' |
Color theme: 'light', 'dark', 'auto' (follows system preference) |
accentColor |
string | '#0071e3' |
Primary button color. Validated — hex, named, rgb(), rgba(), hsl(), hsla() |
showWidget |
boolean | true |
Show floating widget after consent is given |
branding |
boolean | true |
Show a small “Powered by Zest” attribution link on the banner and settings modal. Set false (or data-branding="false") to remove it. Full build only (v2.4.0+) |
buttonStyle |
string | 'fill' |
Button style: 'fill' (solid) or 'outline' (accent-bordered transparent). Also accepted via data-button-style (v2.5.0+) |
buttonLayout |
string | 'row' |
Button arrangement: 'row' (all in one line), 'split' (settings on left, accept+reject on right), 'split-modern' (settings as primary, accept+reject as secondary). Also accepted via data-button-layout (v2.6.0+) |
backdropBlur |
number | 0 |
Blur radius in pixels for the page content behind the modal and hard wall overlay. 0 disables. Also accepted via data-backdrop-blur (v2.6.0+) |
hardWall |
boolean | false |
Full-viewport overlay behind the banner that blocks all page interaction until the visitor accepts or rejects. The banner becomes aria-modal when active. Also accepted via data-hard-wall (v2.6.0+) |
Behavior Options
| Option | Type | Default | Description |
|---|---|---|---|
autoInit |
boolean | true |
Automatically initialize on page load |
expiration |
number | 365 |
Consent cookie expiration in days (1-365) |
mode |
string | 'safe' |
Script blocking mode (see below) |
blockedDomains |
array | [] |
Additional domains to block |
Consent Mode Integrations
| Option | Type | Default | Description |
|---|---|---|---|
consentModeGoogle |
boolean | false |
Enable Google Consent Mode v2 integration |
consentModeMicrosoft |
boolean | false |
Enable Microsoft UET Consent Mode integration |
When enabled, Zest automatically pushes a 'default' denied state on initialization and sends 'update' signals on every consent change. See Consent Mode examples for usage.
Privacy Options
| Option | Type | Default | Description |
|---|---|---|---|
respectDNT |
boolean | true |
Respect Do Not Track and Global Privacy Control signals |
dntBehavior |
string | 'reject' |
DNT behavior: 'reject', 'preselect', 'ignore' |
geo |
boolean | object | null |
Opt-in geo / jurisdiction gating. true uses the hosted gateway; an object accepts provider, endpoint, resolver, decide, timeout, fallback. data-geo="on" is the attribute equivalent (v2.4.0+) |
Links
| Option | Type | Default | Description |
|---|---|---|---|
policyUrl |
string | null |
URL to privacy policy page. Validated — allowlist: http:, https:, mailto:, tel:, or relative |
imprintUrl |
string | null |
URL to imprint/legal page. Same validation as policyUrl |
Language Options
| Option | Type | Default | Description |
|---|---|---|---|
lang |
string | 'auto' |
Language code or 'auto' for detection |
Available languages: en, de, es, fr, it, pt, nl, pl, uk, ru, ja, zh
Advanced Options
| Option | Type | Default | Description |
|---|---|---|---|
customStyles |
string | '' |
Custom CSS to inject into Shadow DOM. Sanitized (20 KB cap; strips @import, @charset, expression(), -moz-binding, external url(), accept/reject-button selectors) |
labels |
object | {} |
Custom UI text labels. All interpolated values are HTML-escaped |
categories |
object | {} |
Per-category overrides. Set hidden: true to remove a category from the settings modal — hidden categories are forced to false (rejected). Essential cannot be hidden. Also accepted via data-hide-categories="analytics,marketing" (v2.6.0+) |
callbacks |
object | {} |
Lifecycle callbacks. Exceptions are logged and swallowed |
intercept |
object | { cookies: true, storage: true, scripts: true, network: true } |
Disable individual interceptor channels. scripts covers both the MutationObserver-based blocker AND (since v2.3.0) the synchronous element-level setter patches on HTMLScriptElement.src, HTMLLinkElement.href, HTMLImageElement.src, HTMLIFrameElement.src, Element.setAttribute, and window.Image. The network channel (added in v2.3.0) intercepts fetch / XMLHttpRequest / navigator.sendBeacon and catches trackers that ship via CMS first-party proxies (HubSpot, Cloudflare Zaraz, server-side GTM). Headless integrations that gate optional scripts / storage / network calls themselves can opt out per channel (v2.2.0+, network added v2.3.0) |
essentialKeys |
array | [] |
Exact storage / cookie names to treat as strictly-necessary. Each is anchored as ^name$ and appended to the essential category — built-in essential patterns stay intact (v2.2.0+) |
essentialPatterns |
array | [] |
Regex source strings appended to the essential category. Validated via safeRegExp; 500-char cap (v2.2.0+) |
patterns |
object | {} |
Custom regex patterns for cookie categorization. Replaces the patterns for any category passed in. Prefer essentialKeys / essentialPatterns when you only want to add to the essential category. 500-char cap; catastrophic-backtracking patterns rejected |
Headless integration example
When you bring your own UI and want Zest only for the consent state machine:
import Zest from '@freshjuice/zest/headless';
Zest.init({
// Disable script blocking — you handle gating yourself
intercept: { scripts: false },
// Tell Zest your app's storage keys are strictly-necessary,
// so the storage interceptor doesn't classify them as marketing
// and block the user's explicit setItem() calls.
essentialKeys: ['my_app_settings', 'theme_pref'],
respectDNT: true,
expiration: 365
});
Blocking Modes
Zest supports four script blocking modes:
| Mode | Description |
|---|---|
manual |
Only blocks scripts with explicit data-consent-category attribute |
safe |
Manual + known major trackers (Google Analytics, Facebook, GTM) |
strict |
Safe + extended trackers (Hotjar, Mixpanel, Segment, etc.) |
doomsday |
Block ALL third-party scripts |
window.ZestConfig = {
mode: 'safe' // Recommended for most sites
};
DNT Behavior Options
When respectDNT is true, the dntBehavior option controls what happens:
| Behavior | Description |
|---|---|
'reject' |
Auto-reject all non-essential cookies, don’t show banner |
'preselect' |
Show banner with non-essential categories unchecked |
'ignore' |
Ignore DNT/GPC signals completely |
Custom Blocked Domains
Add additional domains to block:
window.ZestConfig = {
mode: 'safe',
blockedDomains: [
'custom-tracker.com',
{ domain: 'analytics-service.com', category: 'analytics' }
]
};
Custom Labels
Override any UI text:
window.ZestConfig = {
labels: {
banner: {
title: 'Cookie Settings',
description: 'We use cookies to improve your experience.',
acceptAll: 'Accept All',
rejectAll: 'Reject All',
settings: 'Customize'
},
modal: {
title: 'Privacy Preferences',
save: 'Save Preferences',
acceptAll: 'Accept All',
rejectAll: 'Reject All'
},
widget: {
label: 'Cookie Settings'
},
notice: {
title: 'Your Privacy Choices',
optOut: 'Do Not Sell or Share My Personal Information',
dismiss: 'Dismiss'
}
}
};
The notice labels apply to the “Do Not Sell” notice shown for the geo 'notice' action (v2.4.0+).
Callbacks
React to consent lifecycle events:
window.ZestConfig = {
callbacks: {
onReady: (consent) => {
console.log('Zest initialized:', consent);
},
onAccept: (consent) => {
console.log('User accepted:', consent);
},
onReject: () => {
console.log('User rejected all');
},
onChange: (consent) => {
console.log('Consent changed:', consent);
},
onGeo: (action, verdict) => {
// v2.4.0+ — fires once geo resolution completes (when geo is enabled)
console.log('Geo action:', action, verdict);
}
}
};
Full Example
window.ZestConfig = {
// UI
position: 'bottom-right',
theme: 'auto',
accentColor: '#0071e3',
showWidget: true,
buttonStyle: 'fill', // 'fill' or 'outline' (v2.5.0+)
buttonLayout: 'row', // 'row', 'split', 'split-modern' (v2.6.0+)
backdropBlur: 0, // blur radius in px, 0 disables (v2.6.0+)
hardWall: false, // block page until decided (v2.6.0+)
// Behavior
autoInit: true,
expiration: 365,
mode: 'safe',
// Consent Mode
consentModeGoogle: true,
consentModeMicrosoft: false,
// Privacy
respectDNT: true,
dntBehavior: 'reject',
geo: true, // opt-in jurisdiction gating (v2.4.0+)
// Links
policyUrl: '/privacy-policy',
imprintUrl: '/legal',
// Language
lang: 'auto',
// Categories — hide unused categories from the modal (v2.6.0+)
categories: {
marketing: { hidden: true }
},
// Callbacks
callbacks: {
onAccept: (consent) => {
if (consent.analytics) {
// Initialize analytics
}
}
}
};