# Block scripts until consent: the four methods that work

> To block a tracker until consent, mark its script as text/plain with a category, swap embed URLs for data-cq-src, or let the auto-blocker hold known trackers.

Source: https://cookiequiet.com/guides/block-scripts-until-consent
Published: 2026-10-20
Publisher: Cookiequiet

## Steps

1. **Load the consent script first** Put the Cookiequiet snippet as the first script in the head, with Consent Mode and auto-blocking enabled, so defaults and the blocker exist before any tracker.
2. **List the trackers in your HTML** Find every script tag and iframe that loads analytics, advertising, chat, video or maps. The scanner and the developer tools give the list.
3. **Mark each script tag** Set type to text/plain and add data-cq-category with necessary, functional, analytics or marketing. Inline and external scripts are both supported.
4. **Swap embed URLs** Replace src with data-cq-src on iframes and add the category. Add a placeholder with a button that opens the preferences.
5. **Configure the tag manager** Let Consent Mode govern Google tags and trigger other vendors on the cq_consent event with the matching category flag.
6. **Leave the auto-blocker on for the rest** Dynamically created scripts and iframes of known trackers are held until consent. Mark by hand anything from a host the database does not know.
7. **Test the three paths** Before any click, after Reject all and after Accept all, check cookies and network requests in a private window. Repeat after each tag change.

A banner that does not stop the scripts is the most common failure in cookie compliance, and the most expensive: the CNIL's largest recent fines (Shein, €150 million; American Express, €1.5 million; Condé Nast, €750,000) all cite cookies placed before the visitor made a choice or after they refused. Blocking means that analytics, advertising and embedded content do not load until the visitor consents to their category. There are four ways to achieve it, and most sites use two of them together: mark the script tags, swap embed URLs, let an auto-blocker catch what tag managers and lazy loaders create at runtime, and make each tag in a tag manager wait for consent.

## Method 1: mark the script tag

Change the tag's type so the browser ignores it, and label it with its category:

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

<script type="text/plain" data-cq-category="analytics">
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXX');
</script>
```

A browser never executes a script whose type is `text/plain`. When the visitor grants the category, Cookiequiet creates a new script element with the same attributes and the same content, sets its type to JavaScript, and inserts it right after the original, so both external and inline scripts run in their original order. Scripts whose category is refused stay inert.

Category names accepted in the attribute: `necessary`, `functional`, `analytics`, `marketing`, plus the aliases other banners use (`statistics` and `performance` for analytics, `preferences` for functional, `advertisement`, `advertising` and `targeting` for marketing, `essential` for necessary). The attributes `data-cookieconsent`, `data-cookiecategory` and `data-category` are read as well, which is what makes [switching from Cookiebot](/guides/switch-from-cookiebot) a matter of replacing one script tag.

## Method 2: hold embeds with data-cq-src

Iframes contact their host as soon as the browser sees a `src`. Move the URL to `data-cq-src` and the iframe stays empty until consent:

```html
<iframe data-cq-src="https://www.youtube-nocookie.com/embed/VIDEO_ID"
  data-cq-category="marketing" width="560" height="315"
  title="Product demo" allowfullscreen></iframe>
```

When the category is granted, the `src` is set and the player loads. The category can come from the attribute, or from the provider database (a YouTube URL defaults to marketing, a Vimeo player to functional); when nothing is known, marketing is assumed. A placeholder with a "Load video" button that opens the preferences gives visitors a way to opt in on the spot; the [YouTube guide](/guides/youtube-embeds-and-consent) has the markup.

## Method 3: the auto-blocker

Tag managers, plugins and lazy loaders create script and iframe elements with JavaScript, after the page has loaded, where no markup of yours can catch them. The auto-blocker intercepts element creation: when a script or iframe is created and its `src` points to a known tracker whose category has not been granted, the element is held (its type set to `text/plain`, the URL kept aside) and released when consent arrives. The list of hosts comes from the site's configuration, built from a provider database of about 80 trackers; a short default list of the most common ones (Google Analytics, Google Ads, Meta, Hotjar, Clarity, TikTok, LinkedIn, Microsoft Advertising, Pinterest, YouTube embeds) is applied before the configuration even arrives, so there is no window at startup. Enable it in the dashboard, or with `data-auto-block="1"` on the snippet:

```html
<script src="https://cookiequiet.com/cq.js" data-site="KEY"
  data-consent-mode="1" data-auto-block="1" defer></script>
```

The honest limit: a tracker hard-coded in the HTML before this script, without the `text/plain` marking, runs before anything can stop it. Load the Cookiequiet script first in the head, and mark or move any tag that sits above it. The auto-blocker also cannot hold a tracker whose host is unknown to the database; mark those by hand.

## Method 4: let the tag manager decide

If every tracker goes through Google Tag Manager, you can leave the container loaded and make each tag wait. Google's Consent Mode handles Google tags: with `data-consent-mode="1"` the defaults are set to denied before the container runs and updated on every choice, as explained in [the Consent Mode guide](/guides/google-consent-mode-v2). For other vendors, Cookiequiet pushes a `cq_consent` event with `cq_functional`, `cq_analytics` and `cq_marketing` flags; a trigger on that event with the right flag equal to true fires the tag only after consent. The event is pushed on page load when a stored choice exists, so returning visitors are covered.

## What not to mark

Scripts the site needs in order to work (your framework bundle, a payment form's library on the checkout page, the search widget, the script that stores the consent choice itself) belong to the necessary category and should not be marked at all: they run for everyone, with or without consent, and the cookie policy explains why each is necessary. Marking them would make the site depend on the banner, and a visitor who refuses would get a broken page, which is a cookie wall in another form.

## Reacting to consent in your own code

Any script of yours can wait for consent without being marked:

```js
window.addEventListener('cq:consent', function (e) {
  if (e.detail.categories.indexOf('analytics') >= 0) {
    // start your analytics here
  }
});
```

The `window.Cookiequiet` API exposes `get()` for the stored choice, `on(callback)` for changes, `showPreferences()` to open the centre, and `acceptAll()`, `rejectAll()`, `save(categories)` and `withdraw()` for custom buttons. An element with `data-cq-show-preferences`, or a link to `#cq-preferences`, opens the preferences when clicked.

## Checking that nothing leaks

Open a private window with the developer tools, load the page and do not click. The Application tab should show only necessary cookies (the consent cookie, a session), and the Network tab no request to analytics or advertising hosts. Run `document.querySelectorAll('script[type="text/plain"]')` in the console to see the held tags. Click Reject all: nothing new should appear. Click Accept all: the tags run and the cookies arrive. Repeat on a page with embeds and on a page with a form, and after a tag manager change. The [cookie audit checklist](/guides/cookie-audit-checklist) turns this into a routine.

## Questions

### Does the auto-blocker catch every tracker?

No. It holds scripts and iframes created by JavaScript whose host is in the provider database, about 80 trackers. A tracker from an unknown host, or one hard-coded in the HTML above the consent script, is not caught; mark those tags yourself.

### What about scripts placed in the body or the footer?

They work the same way. The marking is per tag, wherever it sits, and the consent script only needs to be loaded before them. Scripts after it, marked or on a known host, wait for consent.

### What happens when a visitor accepts later in the session?

The held and marked tags are activated at once, without a page reload, in their original order. Embeds get their src and load. The next page applies the stored choice before the tags run.

### Will marking break my site if the consent script fails to load?

The marked tags stay inert, so analytics and advertising do not run, and the site itself keeps working. That is the safe failure for compliance. Scripts the site needs to function should not be marked at all.

## Sources

- [Directive 2002/58/EC (ePrivacy Directive), article 5(3)](https://eur-lex.europa.eu/eli/dir/2002/58/oj)
- [EDPB, Report of the work undertaken by the Cookie Banner Taskforce, paragraph 7 (PDF)](https://www.edpb.europa.eu/system/files/2023-01/edpb_20230118_report_cookie_banner_taskforce_en.pdf)
- [CNIL, Cookies placed without consent: SHEIN fined 150 million euros (decision of 1 September 2025, press release of 3 September 2025)](https://www.cnil.fr/en/cookies-placed-without-consent-shein-fined-150-million-euros-cnil)
- [CNIL, Cookies: AMERICAN EXPRESS fined €1.5 million by the CNIL (decision of 27 November 2025, press release of 3 December 2025)](https://www.cnil.fr/en/cookies-american-express-fined-eu15-million-cnil)
- [Google, Set up consent mode on websites](https://developers.google.com/tag-platform/security/guides/consent)
