Script blocking
Understand which scripts the banner blocks, restores, and cannot intercept.
The consent banner blocks scripts and iframes from the provider hosts you declare until the visitor allows their category. Blocking runs in the browser as part of banner.js and only covers resources it can intercept after installation.
Place the banner first in <head> without async or defer. Undeclared hosts, server-side requests and analytics bundled into your own app need separate handling.
What is blocked
A resource is blocked when all three conditions hold:
- It is a
<script src>or<iframe src>. - Its hostname matches a host declared on a provider.
- The visitor has not allowed that provider’s category.
Inline scripts, resources from your own origin, undeclared hosts and the necessary category pass through.
Host matching includes subdomains at a label boundary. For example, google-analytics.com matches www.google-analytics.com, but not notgoogle-analytics.com. Do not add wildcards; suffix matching already covers subdomains.
To allow additional hosts, set data-lepsto-allow-hosts on the banner snippet to a comma-separated list. This takes priority even when a host is also declared on a provider. To exempt one element, give it data-lepsto-category="necessary".
How a resource is made inert
The blocker intercepts resources through four browser mechanisms:
- The
HTMLScriptElementsrcsetter. document.createElement.- A document-wide
MutationObserver. document.writeanddocument.writeln.
It uses no polling or timer. For a blocked script, it saves the original src and type, changes the type to an inert MIME type, and removes src. For an iframe, it saves the source and substitutes about:blank. The element remains in the document for later restoration.
Newly created scripts are marked inert before their source is assigned. If several interceptors encounter the same element, only the first capture saves its original attributes.
How a resource comes back
When the visitor allows a category, its captured resources are restored in capture order. Non-async scripts load one at a time, with each awaited before the next starts. This preserves dependencies such as a tag manager loading before its tags. async scripts are replaced without waiting.
Restoration removes the blocking markers and restores the original type and src. Under a nonce-based Content Security Policy, the script keeps its own nonce if present; otherwise it receives the nonce used by banner.js.
A script captured before insertion is restored in place, preserving its identity and attached listeners. Once no categories remain blocked, the mutation observer disconnects. The patched setters remain installed and pass resources through.
Tightening a choice
Withdrawing a category blocks it again, reinstalls the observer and attempts to clear its storage. Storage cleanup is best effort.
Blocking cannot undo JavaScript that has already run. The runtime therefore reloads the page when a category becomes newly denied, unless you pass reload: false and handle the change yourself. See The banner runtime.
The necessary category always remains allowed.
It fails open
A blocker installation error does not prevent the banner from running. A banner failure likewise does not stop an installed blocker. Check both the visible banner and network activity when verifying installation.
An unresolved product id is handled separately: the blocker starts with all consentable categories blocked and keeps them blocked until a decision is submitted.
What this does not cover
Trackers that run before the banner. The blocker cannot intercept a tracker that ran before banner.js. Keep the banner first in <head> and synchronous.
Server-side requests. Calls from your server to a third party happen outside the browser.
Analytics bundled into your app. Code started through your own import() and fetch is not a third-party script element. Start and stop it according to Google Consent Mode or window.LepstoConsent.getDecision(), and subscribe to later changes. The runtime example handles both stored choices and new decisions.
Next steps
- Declare your providers and cookies: set the hosts and categories used by the blocker.
- The banner runtime: installation order and the browser API.