# Banner JavaScript and Google Consent Mode

The banner script holds back tracking until a visitor agrees, tells your own code what they chose, and sets Google Consent Mode for your Google tags. This page is for whoever looks after your website's code.

## Load the script first

Paste the banner code as the first item inside `<head>` on every page, without `async` or `defer`. It must run before any tag it controls, so nothing loads early.

```html
<script src="https://cdn.complyzero.com/widget.js" data-id="cz_widget_your_banner_id"></script>
```

- `data-id` is your banner's public ID. Copy the whole line from the **Embed** tab of **Consent Banner**.
- `data-lang` is optional and picks the language the banner opens in, such as `data-lang="hi"` for Hindi.
- If your site uses a Content Security Policy with nonces, give the tag your nonce. The banner uses it for every script it releases.

**Check installation** on the **Embed** tab warns you if the tag loads late, or if a tool on the page can never run because your banner has no purpose for its category.

## What the banner holds by itself

The banner recognises about 50 well-known tools, such as Google Analytics, Microsoft Clarity, Hotjar, Meta, LinkedIn, Reddit, YouTube, Vimeo, Google Maps and the common chat tools. Each one waits until the visitor allows it, then runs without a reload. Your **Cookies** page decides how:

- A rule you set for the tool's address decides first.
- Then how you classified the tool's cookies. If they're all **Necessary**, it always runs. If they're mapped to a purpose, it waits for that purpose.
- A tool you haven't classified waits for every purpose of its usual category.

Some tools are handled in their own way:

- **Google:** the Tag Manager container always loads, and what it adds to the page is held like anything else. `gtag.js` follows the product its ID names: `G-` waits for Analytics, `AW-` and `DC-` for Marketing.
- **Chats:** a chat waits like any other tool, and its own chat button appears once the visitor allows it. If your chat must be there for every visitor, classify its cookies as **Necessary**.
- **Videos and maps:** a held frame the visitor can see gets a box in its place, naming where it comes from, with a button that opens their privacy choices and a link to open it in a new tab.
- **Requests:** a held request fails the way an unreachable server does, so your page's own error handling runs.

Tools the banner doesn't recognise run as usual, until you classify them on the **Cookies** page or tag them as below.

## Hold a script or frame yourself

A script written into your page's HTML starts loading before any script can stop it. For one that must not run before consent, change its type to `text/plain` and say which category it belongs to:

```html
<script type="text/plain" data-czcat="analytics"
        src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"></script>
```

For a frame or image written into your HTML, put its address in `data-cz-src` instead of `src`:

```html
<iframe data-cz-src="https://www.youtube-nocookie.com/embed/VIDEO_ID" data-czcat="marketing"
        width="560" height="315" title="Our product tour"></iframe>
```

- The categories are `functional`, `analytics` and `marketing`. The script or frame runs once every purpose in that category is on.
- `data-czcat="essential"` marks something your site needs to work, such as a sign-in or payment script. It always runs.
- To tie it to one purpose instead, use `data-cz-choice` with the purpose's ID, which is in the address bar when the purpose is open in **Purposes**.

## Read the visitor's choice

The script adds `window.ComplyZero`:

```js
ComplyZero.getConsent();            // { state, purposes, receiptReference }
ComplyZero.hasConsent("analytics"); // a category, or a purpose's ID
ComplyZero.openPreferences();       // opens the banner's settings, for a "Cookie settings" link
ComplyZero.status();                // in the browser console: what's held on this page, and why
```

`hasConsent` is true when the visitor's latest choice says yes: to that purpose, or to every purpose of that category. A choice applies the moment the visitor makes it.

`purposes` maps each purpose's ID to whether it's on right now. `state` is one of:

- `accepted`: the choice is recorded with us, and `receiptReference` names its record.
- `pending`: the choice already applies, and its receipt is on its way to us. If the connection drops, it's sent again on the next page.
- `not_accepted`: we couldn't record the latest choice, so the visitor is asked again and the safe defaults stay in place.
- `local_restriction`: there's no choice yet, or the browser blocks storage, so only purposes that need no consent run.

## React when the choice changes

Each time the choice changes, the script fires a `complyzero:consent` event on `window`, with the same object as `getConsent()`:

```js
window.addEventListener("complyzero:consent", (event) => {
  if (ComplyZero.hasConsent("analytics")) startAnalytics();
});
```

## Google Tag Manager

The script also pushes the choice to the data layer as the event `complyzero_consent_update`, with the same object under `complyzero`. In Tag Manager, use a **Custom Event** trigger with that name, and read values with a Data Layer Variable such as `complyzero.state`.

## Google Consent Mode

Before any Google tag runs, the script sets Consent Mode defaults: `ad_storage`, `ad_user_data`, `ad_personalization`, `analytics_storage`, `functionality_storage` and `personalization_storage` are denied, and `security_storage` is granted. Google tags wait up to half a second for the visitor's stored choice, so a returning visitor's first page is measured correctly. It works with `gtag` and with the data layer queue.

When the visitor chooses, the script sends an update. Each purpose says which Google types it covers, under **Google Consent Mode types** in **Purposes**. A type is granted only when every purpose that covers it is on, and a type no purpose covers stays denied.

> **If no banner is published**
> If the website has no published banner, the script steps aside and grants Consent Mode, so your Google tags behave as if it weren't there.

Last checked against the ComplyZero dashboard on 2026-10-26. Source: https://www.complyzero.com/docs/developers/banner-javascript
