Examples
Real-world examples of using Zest cookie consent
Basic Setup
Minimal configuration to get started:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/@freshjuice/zest"></script>
</head>
<body>
<h1>My Website</h1>
</body>
</html>With Configuration
Common configuration options:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
position: 'bottom-right',
theme: 'auto',
accentColor: '#0071e3',
policyUrl: '/privacy-policy',
mode: 'safe'
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
</head>
<body>
<h1>My Website</h1>
</body>
</html>Google Analytics 4
Block GA4 until consent:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
mode: 'safe',
callbacks: {
onAccept: (consent) => {
if (consent.analytics) {
// GA4 initialization
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
}
}
}
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
<!-- This will be auto-blocked in safe mode -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
</head>
<body>
<h1>My Website</h1>
</body>
</html>Google Consent Mode v2
Integrate with Google Consent Mode v2 so Google tags automatically respect user consent:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
mode: 'safe',
consentModeGoogle: true,
policyUrl: '/privacy-policy'
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
<!-- GA4 / GTM - blocked until consent, then Consent Mode signals are sent automatically -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>
</head>
<body>
<h1>My Website</h1>
</body>
</html>Zest will automatically:
- Push a
'default'denied state for all consent types on initialization - Push an
'update'signal whenever the user changes their preferences
The following Google Consent Mode signals are mapped:
| Google Signal | Zest Category |
|---|---|
ad_storage | marketing |
ad_user_data | marketing |
ad_personalization | marketing |
analytics_storage | analytics |
functionality_storage | Always 'granted' (essential) |
personalization_storage | functional |
Microsoft UET Consent Mode
Integrate with Microsoft UET Consent Mode for Microsoft Advertising:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
mode: 'safe',
consentModeMicrosoft: true
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
</head>
<body>
<h1>My Website</h1>
</body>
</html>Microsoft UET maps ad_storage to the Zest marketing category.
Both Consent Modes Together
You can enable both Google and Microsoft consent modes simultaneously:
<script>
window.ZestConfig = {
mode: 'safe',
consentModeGoogle: true,
consentModeMicrosoft: true
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>Or via data attributes:
<script
src="https://unpkg.com/@freshjuice/zest"
data-consent-mode-google
data-consent-mode-microsoft
></script>Google Tag Manager
Block GTM until consent:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
mode: 'safe'
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
<!-- GTM will be blocked until analytics consent -->
<script data-consent-category="analytics">
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');
</script>
</head>
<body>
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<h1>My Website</h1>
</body>
</html>Facebook Pixel
Block Facebook Pixel until marketing consent:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
mode: 'safe'
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
<!-- Facebook Pixel - blocked by default in safe mode -->
<script data-consent-category="marketing">
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'PIXEL_ID');
fbq('track', 'PageView');
</script>
</head>
<body>
<h1>My Website</h1>
</body>
</html>Multi-language Site
Auto-detect language from HTML:
<!DOCTYPE html>
<html lang="de">
<head>
<script>
window.ZestConfig = {
lang: 'auto' // Will use 'de' from html lang attribute
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
</head>
<body>
<h1>Meine Webseite</h1>
</body>
</html>Or specify explicitly:
<script>
window.ZestConfig = {
lang: 'fr' // Force French
};
</script>Cookie Preferences Button
Add a footer link to reopen settings:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/@freshjuice/zest"></script>
</head>
<body>
<main>
<h1>My Website</h1>
</main>
<footer>
<a href="#" onclick="Zest.showSettings(); return false;">
Cookie Settings
</a>
<a href="/privacy-policy">Privacy Policy</a>
</footer>
</body>
</html>Custom Styling
Match your brand:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
theme: 'dark',
accentColor: '#10b981',
position: 'bottom-left',
customStyles: `
.zest-banner {
border-radius: 16px;
margin: 16px;
max-width: 400px;
}
.zest-btn--primary {
border-radius: 9999px;
}
`
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
</head>
<body>
<h1>My Website</h1>
</body>
</html>Consent-Based Feature Toggle
Show/hide features based on consent:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
callbacks: {
onReady: updateUI,
onChange: updateUI
}
};
function updateUI(consent) {
const chatWidget = document.getElementById('chat-widget');
const analyticsInfo = document.getElementById('analytics-info');
if (consent.functional) {
chatWidget.style.display = 'block';
} else {
chatWidget.style.display = 'none';
}
if (consent.analytics) {
analyticsInfo.textContent = 'Analytics enabled';
} else {
analyticsInfo.textContent = 'Analytics disabled';
}
}
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
</head>
<body>
<h1>My Website</h1>
<p id="analytics-info">Loading...</p>
<div id="chat-widget" style="display: none;">Chat Widget Here</div>
</body>
</html>Strict Privacy Mode
Block all trackers and respect DNT:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
mode: 'strict',
respectDNT: true,
dntBehavior: 'reject',
showWidget: true
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
</head>
<body>
<h1>Privacy-First Website</h1>
</body>
</html>Manual Initialization
Control when Zest initializes:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.ZestConfig = {
autoInit: false
};
</script>
<script src="https://unpkg.com/@freshjuice/zest"></script>
</head>
<body>
<h1>My Website</h1>
<script>
// Initialize later, e.g., after user interaction
document.getElementById('start-btn').addEventListener('click', () => {
Zest.init();
});
</script>
<button id="start-btn">Enter Site</button>
</body>
</html>Headless (bring your own UI)
Since v2.0.0, Zest ships a headless entry that runs the consent engine without any built-in UI, translations, or auto-init. Perfect when you want to render the banner in your own framework with your own CSS.
import Zest from '@freshjuice/zest/headless';
// Initialize explicitly — no auto-init, no window.Zest
Zest.init({
mode: 'safe',
respectDNT: true,
policyUrl: '/privacy-policy'
});
// React to consent changes with the subscriber API
Zest.on('change', (consent) => {
renderMyBanner(consent);
});
// Later, when your custom form submits:
function handleSave(formData) {
Zest.updateConsent({
analytics: formData.has('analytics'),
marketing: formData.has('marketing'),
functional: formData.has('functional')
});
}The headless build is ESM-only (~11 KB gzipped) and exposes the same API as the full build except for show / hide / showSettings / hideSettings — you render your own surface and call Zest.updateConsent() / Zest.acceptAll() / Zest.rejectAll() from your own handlers.
React example
import { useEffect, useState } from 'react';
import Zest from '@freshjuice/zest/headless';
function ConsentBanner() {
const [consent, setConsent] = useState(null);
const [decided, setDecided] = useState(false);
useEffect(() => {
Zest.init({ mode: 'safe' });
setConsent(Zest.getConsent());
setDecided(Zest.hasConsentDecision());
const off = Zest.on('change', (next) => {
setConsent(next);
setDecided(true);
});
return off;
}, []);
if (decided) return null;
return (
<div className="my-banner">
<p>We use cookies. <a href="/privacy-policy">Privacy policy</a>.</p>
<button onClick={() => Zest.acceptAll()}>Accept all</button>
<button onClick={() => Zest.rejectAll()}>Reject all</button>
<button onClick={() => Zest.updateConsent({ analytics: true })}>
Analytics only
</button>
</div>
);
}SPA Integration (React/Vue/etc)
Initialize once and control via API:
// In your main App component
import { useEffect } from 'react';
function App() {
useEffect(() => {
// Listen for consent changes
const handleConsent = (e) => {
if (e.detail.consent.analytics) {
// Initialize analytics
}
};
document.addEventListener('zest:consent', handleConsent);
return () => {
document.removeEventListener('zest:consent', handleConsent);
};
}, []);
return (
<div>
<button onClick={() => Zest.showSettings()}>
Cookie Preferences
</button>
</div>
);
} 