Skip to main content

Menu

Choose a theme and configure high-contrast mode. Preferences are saved in your browser only.

User Preferences

Theme

Pick a palette or follow your system preference.

High Contrast

Sharper text and borders. System follows your OS setting.

API Reference

Global Object

All Zest methods are available on the global Zest object.

Zest.version reports the running bundle version (full and headless builds, v3.0.0+). Check it when debugging an unpinned CDN install.

Initialization

Zest.init(config)

Manually initialize Zest with a configuration object. Only needed if autoInit is set to false.

Zest.init({
  position: 'bottom-right',
  theme: 'dark'
});

UI Control

show(), hide(), showSettings(), and hideSettings() are full-build-only. The headless build has no built-in UI or window.Zest global; reset() is available in both builds, but only the full build re-shows the banner.

Zest.show()

Show the consent banner.

Zest.show();

Zest.hide()

Hide the consent banner.

Zest.hide();

Zest.showSettings()

Open the settings modal where users can customize their preferences.

Zest.showSettings();

Zest.hideSettings()

Close the settings modal.

Zest.hideSettings();

Zest.reset()

Clear all consent data and show the banner again. Useful for “reset preferences” buttons.

Zest.reset();

Zest.getConsent()

Get the current consent state for all categories.

const consent = Zest.getConsent();
// Returns: { essential: true, functional: false, analytics: false, marketing: false }

Zest.hasConsent(category)

Check if a specific category has consent.

if (Zest.hasConsent('analytics')) {
  // Initialize analytics tracking
  initAnalytics();
}

Zest.hasConsentDecision()

Check if the user has made any consent decision (accept or reject).

if (!Zest.hasConsentDecision()) {
  // User hasn't decided yet
  console.log('Waiting for consent...');
}

Zest.acceptAll()

Programmatically accept all consent categories. Returns { current, previous } after initialization or null before it (v3.0.0+ in the full build).

Zest.acceptAll();

Zest.rejectAll()

Programmatically reject all non-essential categories. Like acceptAll() and updateConsent(), returns { current, previous } after initialization or null before it (v3.0.0+ in the full build).

Zest.rejectAll();

Zest.getConsentProof()

Get consent proof data for compliance records.

const proof = Zest.getConsentProof();
// Returns: {
//   version: "1.0",
//   timestamp: 1234567890,
//   categories: { essential: true, ... }
// }

Zest.updateConsent(selections)

Since v2.0.0. Available on both the full and headless builds (full build since v2.8.0).

Save an arbitrary set of category selections. Useful when building a custom UI (especially with the headless entry) — pass the checkbox state from your own form.

Zest.updateConsent({
  analytics: true,
  marketing: false,
  functional: true
});

Categories you don’t include keep their previous state. Unknown keys are ignored. The cookie is written and the usual zest:change / zest:consent events are dispatched. Returns { current, previous } after initialization or null before it (v3.0.0+ in the full build).

Zest.activateEmbed(elementOrIndex)

Since v3.0.0. Full and headless builds.

Load one gated iframe without recording consent. Pass its element or its index in the gated embed queue; returns true if activated. Headless builds do not render the consent overlay.

Zest.activateEmbed(document.querySelector('iframe[data-consent-src]'));

See embed gating for markup and opt-out options.

Geo Targeting

Zest.resolveGeo()

Since v2.4.0. Available on both the full and headless builds (full build since v2.8.0).

Resolve the visitor’s jurisdiction and act on it, returning a Promise of { action, verdict }. Only meaningful when geo gating is configured — resolves null when geo isn’t set or a consent decision already exists. init() triggers resolution automatically; this method lets you await the result directly (the primary pattern for the headless build, which renders no UI):

import Zest from '@freshjuice/zest/headless';

Zest.init({ geo: true });

const result = await Zest.resolveGeo();
if (result) {
  const { action, verdict } = result;
  // action: 'consent' | 'notice' | 'allow' | 'block'
  // verdict: { isEU, isEEA, isGDPR, isCCPA, isUSPrivacy, regulations } or null on failure
}

The same result also reaches you via the onGeo(action, verdict) callback and the zest:geo DOM event. When geo is configured, the init() snapshot reports geoPending: true until resolution completes.

Privacy Detection

Zest.isDoNotTrackEnabled()

Check if Do Not Track (DNT) or Global Privacy Control (GPC) is enabled.

if (Zest.isDoNotTrackEnabled()) {
  console.log('User has privacy signals enabled');
}

Zest.getDNTDetails()

Get details about which privacy signal is enabled.

const dnt = Zest.getDNTDetails();
// Returns: { enabled: true, source: 'gpc' }
// source can be: 'dnt', 'gpc', or null

Configuration

Zest.getConfig()

Get the current Zest configuration.

const config = Zest.getConfig();
console.log(config.position); // 'bottom-right'

Events

Zest.on(event, callback)

Since v2.0.0.

Subscribe to a Zest event. Returns an unsubscribe function.

const unsubscribe = Zest.on('consent', (consent) => {
  if (consent.analytics) initAnalytics();
});

// Later — stop listening
unsubscribe();

The event name can be passed with or without the zest: prefix ('consent' and 'zest:consent' are equivalent). Use Zest.EVENTS for constants.

Zest.once(event, callback)

Since v2.0.0.

Same as Zest.on(), but the callback fires at most once and then auto-unsubscribes.

Zest.once('ready', (consent) => {
  console.log('Zest is ready with:', consent);
});

Zest.EVENTS

Object containing all event names for reference.

console.log(Zest.EVENTS);
// {
//   READY: 'zest:ready',
//   CONSENT: 'zest:consent',
//   REJECT: 'zest:reject',
//   CHANGE: 'zest:change',
//   SHOW: 'zest:show',
//   HIDE: 'zest:hide',
//   GEO: 'zest:geo',
//   EMBED: 'zest:embed'
// }

// Use constants with on()/once()
Zest.on(Zest.EVENTS.CHANGE, handleChange);

Practical Examples

Conditional Script Loading

document.addEventListener('zest:consent', (e) => {
  if (e.detail.consent.analytics) {
    // Load Google Analytics
    const script = document.createElement('script');
    script.src = 'https://www.googletagmanager.com/gtag/js?id=GA-XXXXX';
    document.head.appendChild(script);
  }
});
<button onclick="Zest.showSettings()">Cookie Preferences</button>
<a href="#" onclick="Zest.reset(); return false;">Reset Cookie Settings</a>

Check Before Tracking

function trackEvent(name, data) {
  if (Zest.hasConsent('analytics')) {
    gtag('event', name, data);
  }
}
async function waitForAnalyticsConsent() {
  return new Promise((resolve) => {
    if (Zest.hasConsent('analytics')) {
      resolve(true);
      return;
    }

    document.addEventListener('zest:consent', (e) => {
      if (e.detail.consent.analytics) {
        resolve(true);
      }
    });

    document.addEventListener('zest:reject', () => {
      resolve(false);
    });
  });
}

// Usage
const hasAnalytics = await waitForAnalyticsConsent();
if (hasAnalytics) {
  initAnalytics();
}