Disabling individual widgets
gateScript is for loading a script tag. Sometimes what you actually want to gate is a piece of
your own UI — an embed, a chat bubble, a “manage cookies” link — without touching a script at
all. That’s a plain getConsent() / onConsentChange() pair.
Reacting to consent
Section titled “Reacting to consent”Read the current value on load, then subscribe to future changes — a visitor can change their mind later via the reopen button, so both are needed:
<div id="widget">Waiting for consent…</div>
<script> import { getConsent, onConsentChange } from 'astro-cookie-consent';
const widget = document.getElementById('widget');
function render(value: 'accept' | 'decline' | null) { if (!widget) return; widget.textContent = value === 'accept' ? 'Widget enabled' : 'Widget disabled'; }
render(getConsent('analytics')); onConsentChange(() => render(getConsent('analytics')));</script>This is the exact pattern behind the Analytics widget on the homepage — toggle the banner there and watch it react live.
Placeholder with an inline “Enable” button
Section titled “Placeholder with an inline “Enable” button”For a third-party embed (a map, a video, a chat widget), showing a bare “disabled” state is a dead end — give the visitor a way to turn just that one thing on, right where it lives, instead of sending them back to the banner:
<div id="map"> <div class="placeholder"> <p>This map needs the <strong>marketing</strong> category.</p> <button id="enable-map">Enable map</button> </div> <iframe data-src="https://maps.example.com/embed" hidden></iframe></div>
<script> import { getConsent, getConsentRecord, setConsent, onConsentChange } from 'astro-cookie-consent';
const placeholder = document.querySelector('#map .placeholder'); const iframe = document.querySelector('#map iframe'); const button = document.getElementById('enable-map');
function render(value: 'accept' | 'decline' | null) { const accepted = value === 'accept'; placeholder.hidden = accepted; iframe.hidden = !accepted; if (accepted && !iframe.src) iframe.src = iframe.dataset.src; // load once, lazily }
render(getConsent('marketing')); onConsentChange(() => render(getConsent('marketing')));
button.addEventListener('click', () => { // Merge with the existing record — setConsent replaces the whole // categories map, so pass the others through untouched instead of // only the one this button knows about. const current = getConsentRecord()?.categories ?? {}; setConsent({ ...current, marketing: true }); });</script>Two details that matter here:
- Merge, don’t overwrite.
setConsent()replaces the entire stored categories map — calling it with only{ marketing: true }would silently revert any other category (e.g.analytics) the visitor had already accepted. Read the current record first and spread it in. - Lazy
src. The iframe’s real URL sits indata-srcuntil consent is granted, so the embed’s own cookies never load before the visitor has agreed to them — assigningiframe.srcis the point where the request actually fires.
See the JS API reference for the full signature of each function, and Per-category consent for setting up the categories themselves.