# Configuration

> All configuration options for Zest cookie consent

Source: https://zest.freshjuice.dev/docs/configuration/

## Configuration Methods

Zest can be configured in three ways (in order of priority):

1. **`window.ZestConfig` object** - Highest priority
2. **Data attributes** on the script tag
3. **Default values** - Lowest priority

### Using ZestConfig Object

```html
<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

```html
<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-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'` |
| `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 |

### 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](https://developers.google.com/tag-platform/security/concepts/consent-mode) integration |
| `consentModeMicrosoft` | boolean | `false` | Enable [Microsoft UET Consent Mode](https://help.ads.microsoft.com/#apex/ads/en/60119/1-500) integration |

When enabled, Zest automatically pushes a `'default'` denied state on initialization and sends `'update'` signals on every consent change. See [Consent Mode examples](/docs/examples/#google-consent-mode-v2) 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'` |

### 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 | `{}` | Custom category definitions |
| `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:

```javascript
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 |

```javascript
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:

```javascript
window.ZestConfig = {
  mode: 'safe',
  blockedDomains: [
    'custom-tracker.com',
    { domain: 'analytics-service.com', category: 'analytics' }
  ]
};
```

## Custom Labels

Override any UI text:

```javascript
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'
    }
  }
};
```

## Callbacks

React to consent lifecycle events:

```javascript
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);
    }
  }
};
```

## Full Example

```javascript
window.ZestConfig = {
  // UI
  position: 'bottom-right',
  theme: 'auto',
  accentColor: '#0071e3',
  showWidget: true,

  // Behavior
  autoInit: true,
  expiration: 365,
  mode: 'safe',

  // Consent Mode
  consentModeGoogle: true,
  consentModeMicrosoft: false,

  // Privacy
  respectDNT: true,
  dntBehavior: 'reject',

  // Links
  policyUrl: '/privacy-policy',
  imprintUrl: '/legal',

  // Language
  lang: 'auto',

  // Callbacks
  callbacks: {
    onAccept: (consent) => {
      if (consent.analytics) {
        // Initialize analytics
      }
    }
  }
};
```

