The Rule That Makes This Necessary
Article 5(3) of the ePrivacy Directive says you need consent before storing or reading non-essential information on a visitor's device. "Before" is the operative word. If Google Analytics, the Meta pixel, or a chat widget runs while the banner is still on screen, the cookie is already set and consent came too late. The CJEU's Planet49 ruling (C-673/17) confirmed consent must be a prior, active choice, not something you infer after the fact.
So the technical requirement is blunt: hold every non-essential script until its category is granted. This is called prior blocking, and it's the part most broken banners get wrong. Here's how it actually works.
The Core Pattern: type="text/plain" + data-category
Browsers only execute a <script> whose type they recognize. Give a script an unknown MIME type and the browser parses it, then skips it. That's the lever. You mark a script as blocked by setting its type to a placeholder and tagging it with the category it belongs to:
<script type="text/plain" data-category="analytics"
src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXX"></script>At page load the browser sees text/plain, decides this isn't JavaScript, and leaves it alone. No request to Google, no cookie, nothing. The tag sits inert in the DOM with a label saying "run me only if analytics is granted." CookieBeam uses data-category as the canonical attribute and text/plain as the default placeholder type, and it also accepts a few compatibility aliases so you can migrate from another CMP without re-tagging everything at once.
Re-Running the Script on Consent
Here's the catch that trips up hand-rolled solutions. You can't just find the blocked tag and flip its type back to text/javascript. Once the browser has parsed a script element, changing its type attribute does nothing, the browser won't re-evaluate it. To actually run a blocked script after consent, the CMP has to clone the node into a fresh element with the correct type and insert that, which the browser treats as new and executes.
So when a visitor grants a category, a CMP walks every element tagged with that category, creates a real <script> copy (preserving src, inline body, and attributes), and injects it in place. Inline scripts run immediately; external ones fire their request and execute on load. Do this in tag order so dependencies (a library before the code that calls it) still line up. Getting this right by hand is fiddly, which is the main reason to let a CMP own it.
Auto-Blocking: Catching What You Didn't Tag
Manual tagging assumes you know every script on the page. You don't, because marketing adds tags, plugins inject their own, and third parties load more scripts from inside the ones you allowed. Auto-blocking handles this. The CMP watches the DOM and intercepts scripts and network requests to known tracker domains before they execute, matching against a maintained database, and holds them under the right category even though nobody tagged them. CookieBeam supports both paths: explicit data-category tagging for scripts you control, and automatic blocking of known third parties you missed. Tag what you can, auto-block the rest, and reconcile the two with a cookie audit.
The Google Tag Manager Route
If all your tags live in Google Tag Manager, you have a second option that pairs with prior blocking: gate tags with Consent Mode instead of stripping them from the page. GTM tags can be set to wait for consent signals and fire in a limited, cookieless mode until granted. This is a different mechanism (the tag loads but restrains itself) and it's how Google's own products expect to be handled. Most real sites use both: prior blocking for scripts hard-coded in the page, and Consent Mode for anything routed through GTM. Walk through the wiring in setting up Google Consent Mode with a CMP and the deeper GTM setup in Google Tag Manager and consent.
Embeds and iframes
A YouTube embed, a Google Map, or a social post is an <iframe> that sets its own cookies the moment it loads, and you can't retype an iframe the way you retype a script. The pattern here is a placeholder: swap the iframe for a lightweight "click to load" box until the relevant category is granted, then insert the real embed. This keeps marketing cookies off the page while still showing the visitor that content exists. See click-to-load consent for embeds and consent for YouTube and Vimeo embeds.
Prior-blocking checklist
Non-essential scripts use a placeholder type at load
text/plain (or equivalent) so the browser skips them until consent.
Each blocked script declares its category
A data-category attribute the CMP can read.
Scripts are re-run by cloning, not by re-typing in place
Changing a parsed script's type doesn't re-execute it.
Re-injection preserves tag order
Libraries run before the code that depends on them.
Auto-blocking covers untagged known trackers
You will miss some by hand; a maintained blocklist catches them.
iframes/embeds use click-to-load placeholders
You can't retype an iframe; replace it until consent.
Network tab shows zero non-essential requests pre-consent
The only test that proves blocking actually works.
Async Loaders Defeat Naive Blocking
Many third parties don't ship a simple script tag. They inject their own scripts at runtime (tag managers, ad loaders, A/B tools), so retyping the one tag you can see won't stop the ten it spawns. This is why domain-level auto-blocking and request interception matter alongside attribute tagging: the target is everything the visible script goes on to load, beyond the tag you can see.