Developer Hub › JavaScript
JavaScript Script Blocking for LGPD
How to block non-essential scripts before consent using MutationObserver and type rewriting — the two techniques every LGPD implementation requires.
How do you block scripts before consent under LGPD?
Two mechanisms work together. First, change non-essential <script> tags from type="text/javascript" to type="text/plain" and add a data-consent-category attribute — the browser ignores scripts with unknown MIME types, so they never execute. Second, install a MutationObserver that watches the document for dynamically injected scripts and rewrites them before the browser can execute them.
After the visitor consents, the consent manager re-injects the held scripts with type="text/javascript" restored, triggering normal browser execution. Essential scripts in the Necessary category are never blocked.
Technique 1 — Type rewriting
Mark your tracking scripts as text/plain before the page loads. The consent manager restores them after consent.
Before — script fires immediately (LGPD violation)
<!-- WRONG: fires before consent -->
<script async src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXX"></script>
After — blocked until consent granted
<!-- CORRECT: blocked until consent granted -->
<script
type="text/plain"
data-consent-category="analytics"
src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXX"></script>
Accepted values for data-consent-category: analytics, marketing, functional. Necessary scripts should never have this attribute — they always execute.
Technique 2 — MutationObserver
Type rewriting only blocks static HTML scripts. A MutationObserver intercepts scripts dynamically injected by tag managers, ad networks, and analytics libraries.
// Intercept dynamically injected scripts before they execute
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node.nodeName !== 'SCRIPT') return;
const src = node.src || '';
const isTracking = isTrackingScript(src);
if (isTracking && !hasConsent(node)) {
node.remove(); // remove before browser executes
queueScript(node); // re-inject after consent
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
The observer must be started before any tracking library loads — place it synchronously in the <head> before GTM, GA4, or any other tag.
Consent state management
Read and react to consent decisions using the CookieFácil consent API.
// Read current consent state
const consent = window.CookieFacil?.getConsent();
// Returns: { analytics: true/false, marketing: true/false, functional: true/false }
// Listen for consent changes
document.addEventListener('cf:consent', function(e) {
const { analytics, marketing, functional } = e.detail;
if (analytics) {
// Safe to fire analytics now
loadGoogleAnalytics();
}
if (marketing) {
// Safe to fire ad pixels now
loadMetaPixel();
}
});
// Check specific category
if (window.CookieFacil?.hasConsent('analytics')) {
// Analytics consent already granted on this visit
initAnalytics();
}
How CookieFácil handles this automatically
With the CookieFácil script installed as the first item in your <head>, all of the above is handled automatically. You do not need to write a MutationObserver, manage consent state, or re-inject scripts manually. The script intercepts GA4, GTM, Meta Pixel, Hotjar, TikTok Pixel, and hundreds of other known tracking libraries by pattern matching against their source URLs.
For custom scripts, add data-consent-category="analytics" (or marketing / functional) to your existing script tags — no other change needed.
Choose the right plan for your business
Start free and scale as your consent volume grows. Billed in BRL — no credit card required to start.
Free
Start collecting consent records
1 site · 1,000 visitors/month
Cookie consent banner — LGPD + GDPR ready
Basic consent reports
Basic
For growing businesses
2 sites · 5,000 visitors/month
CSV export of consent records
Remove CookieFácil branding
Professional
For multiple sites and agencies
5 sites · 50,000 visitors/month
CSV + PDF + advanced reports
Custom CSS and geo-targeting rules
Frequently asked questions
-
How do you block scripts before consent under LGPD?
Change non-essential script tags from
type="text/javascript"totype="text/plain"and add adata-consent-categoryattribute. A MutationObserver intercepts dynamically injected scripts. After consent, re-inject with the correct type restored. -
Can I use async or defer on the LGPD consent script?
No. The consent script must be synchronous and the first script in the HTML head. Using
asyncordefermeans tracking scripts may execute before the consent script loads — a direct LGPD violation. -
What is type rewriting in the context of LGPD cookie consent?
Type rewriting changes script tags from
type="text/javascript"totype="text/plain"so the browser ignores them. The consent manager restores the original type after the user accepts, causing the browser to execute them. -
How do I handle dynamically injected scripts for LGPD compliance?
Use a MutationObserver watching the document body for added script nodes. When a script with a tracked src is detected before consent, remove it immediately or rewrite its type before the browser can execute it.