---
title: "Blocking scripts and connections"
description: "Hold back tags, pixels, iframes, and network connections until the visitor's consent allows them."
url: "https://cookiebeam.com/docs/configure/blocking"
lang: "en"
---

# Blocking scripts and connections

Hold back tags, pixels, iframes, and network connections until the visitor's consent allows them.

CookieBeam blocks non-consented resources in two complementary ways: **automatic blocking** driven by your scan inventory, and **manual script gating** for tags you mark up yourself.

## Automatic blocking

The published banner includes a small interceptor that runs before your tags. It watches for script, iframe, and image insertion and neutralizes anything your configuration says needs consent:

- **Scripts** are rewritten in place — the `src` moves to a `data-cookieblock-src` attribute and the type becomes `text/plain`, so the browser downloads and executes nothing.
- **Iframes and images** have their `src` cleared, and blocked iframes can render a consent placeholder ("shield") the visitor can click to allow that embed.
- **Network connections** — `fetch`, `XMLHttpRequest`, `navigator.sendBeacon`, and WebSocket — are wrapped and checked against your connection rules, so a script that did load can't quietly phone home to a denied endpoint.

What gets blocked comes from the cookie scanner's inventory (detected scripts and connections with their categories) plus any blocking rules you add yourself, compiled into the published bundle. CookieBeam's own domains are never blocked.

When the visitor consents, blocked resources for the newly allowed categories are revived: a fresh script element is cloned from the placeholder and executed, and gated connections start passing. External scripts are re-inserted with forced in-order execution, so dependency chains (a library and the tag that uses it) load in the right sequence.

## Manual script gating

For tags you control in your own markup, gate them declaratively — no JavaScript required:

```html
<script type="text/plain" data-category="marketing" data-src="https://example.com/pixel.js"></script>
```

The `type="text/plain"` keeps the browser from executing the tag; `data-category` binds it to one of your consent categories. When the visitor accepts that category, the runtime clones and replaces the element (mutating `type` in place would not execute it) and the tag runs. Inline scripts work the same way without the `data-src` attribute.

The attribute names above are the defaults; self-hosted configurations can remap them via the script-gating configuration.

### Run-on-disable scripts

Some vendors expect an explicit "the user said no" beacon rather than silence. Add `data-cookiebeam-run-on-disable` to a gated script and it fires when the category is denied **in any valid consent record** — not only after an explicit rejection:

```html
<script type="text/plain" data-category="analytics" data-cookiebeam-run-on-disable data-src="https://example.com/opt-out-beacon.js"></script>
```

The exact firing rules, from the shipped runtime:

- **A valid consent record must exist.** The runtime checks that the current record is valid and that the category is not accepted in it; it does not distinguish an explicit "no" from a machine-written default. In **opt-out or notice mode**, the default record written at page load is already valid, so a run-on-disable script for any category outside the default set fires on that first load — before the visitor has touched the banner. Published bundles do not write an opt-in default at page load. In **opt-in mode**, a visitor with no existing valid record must first produce one before the script can fire.
- **Once per page load, not per browser session.** The fired-once registry lives in the page's runtime memory. A toggle off → on → off in the same page view fires the script only once, but a navigation or reload builds a fresh registry and the script can fire again for a still-denied category.

If you wire an external opt-out beacon to this attribute, expect it to represent "this category is currently denied for this visitor" — including visitors who never interacted — rather than "this visitor just said no".

## Choosing between the two

Use automatic blocking for third-party tags the scanner finds and classifies — it needs no markup changes for tags added by JavaScript (a tag manager, a plugin, or another script). A `<script src>` hardcoded in your page HTML is different: the browser starts fetching it while parsing the HTML, before any JavaScript can intercept it, so change it to `<script type="text/plain" data-category="…" data-src="…">` as shown under manual gating. Use manual gating when you want deterministic, reviewable control over a specific tag, or when you inline first-party scripts that set cookies. The two compose: a manually gated script is never double-activated by the automatic engine.

## Where blocking is configured

Automatic blocking rules come from the reviewed scan inventory and compile into the bundle on publish — there is no separate toggle per script. Engine-level overrides (behind the compliance-mode presets in the banner's settings) live at **Dashboard → Scanner → Settings**. Manual gating lives in your own markup, as shown above. After changing any of these, **Publish** from the banner header, then verify on a clean browser profile: open the network panel, confirm denied-category requests never fire before consent, and confirm they execute after the matching category is accepted.
