Skip to content
Documentation

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.

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 in data-src until consent is granted, so the embed’s own cookies never load before the visitor has agreed to them — assigning iframe.src is 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.