OptinStack

Events

Subscribe to SDK lifecycle, consent, UI, and blocking events.

OptinStack emits events through two channels simultaneously:

  1. SDK events via OptinStack.events.on() / OptinStack.events.off()
  2. DOM CustomEvents on document.documentElement with the optinstack: prefix

Both fire for every event, so you can choose whichever approach fits your integration.

Subscribing to Events

SDK Event API

window.OptinStack.push(function (os) {
  os.events.on('consent-updated', function (detail) {
    console.log('Consent changed:', detail.choices);
  });
});

To unsubscribe, pass the same handler reference:

function handler(detail) {
  console.log(detail);
}

os.events.on('consent-updated', handler);
os.events.off('consent-updated', handler);

Wildcard Listener

Listen to all events with *:

os.events.on('*', function (eventName, detail) {
  console.log('Event:', eventName, detail);
});

DOM CustomEvents

Every SDK event also fires as a CustomEvent on document.documentElement:

document.documentElement.addEventListener('optinstack:consent-updated', function (e) {
  console.log('Consent changed:', e.detail.choices);
});

These events have bubbles: true and composed: true, so they propagate through Shadow DOM boundaries.

Lifecycle Events

ready

Fires after the SDK has fully initialized — blocking, analytics, and UI elements are all set up.

os.events.on('ready', function () {
  console.log('OptinStack is ready');
});

accept-all

Fires immediately before all categories are set to true (via banner, preferences panel, or API).

os.events.on('accept-all', function () {
  console.log('User accepted all categories');
});

reject-all

Fires immediately before optional categories are set to false.

os.events.on('reject-all', function () {
  console.log('User rejected optional categories');
});

Fires after consent choices change. This is the primary event for reacting to consent state changes.

os.events.on('consent-updated', function (detail) {
  console.log(detail.id); // Consent record ID
  console.log(detail.choices); // { necessary, analytics, marketing, preferences }
  console.log(detail.previousChoices); // Previous state (if available)
  console.log(detail.action); // "accept_all" | "reject_all" | "submit"
  console.log(detail.source); // "banner" | "preferences" | "api"
  console.log(detail.timestamp); // Unix timestamp
});
This event only fires when choices actually change — duplicate updates are deduplicated.

UI Visibility Events

These events fire when consent UI elements are shown or hidden:

EventWhen
banner-shownBanner becomes visible
banner-hiddenBanner becomes hidden
preferences-shownPreferences dialog becomes visible
preferences-hiddenPreferences dialog becomes hidden
fixed-preferences-shownFixed preferences button becomes visible
fixed-preferences-hiddenFixed preferences button becomes hidden
os.events.on('banner-shown', function () {
  // Track banner impressions
  analytics.track('consent_banner_shown');
});

os.events.on('preferences-shown', function () {
  // Track preference center opens
  analytics.track('preferences_opened');
});

Blocking Events

These events fire when the SDK blocks or unblocks third-party resources based on consent:

script-blocked / script-unblocked

os.events.on('script-blocked', function (detail) {
  console.log(detail.src); // Script URL
  console.log(detail.element); // The HTMLScriptElement
  console.log(detail.categories); // ["analytics", "marketing"]
});

os.events.on('script-unblocked', function (detail) {
  console.log('Script unblocked:', detail.src);
});

iframe-blocked / iframe-unblocked

os.events.on('iframe-blocked', function (detail) {
  console.log(detail.src); // Iframe URL
  console.log(detail.element); // The HTMLIFrameElement
  console.log(detail.categories); // ["marketing"]
});

map-blocked / map-unblocked

Specific to Webflow map embeds:

os.events.on('map-blocked', function (detail) {
  console.log(detail.element); // The map container element
  console.log(detail.categories); // ["marketing"]
});

Event Reference

EventPayloadDescription
readySDK fully initialized
accept-allAll categories accepted
reject-allOptional categories rejected
consent-updated{ id, choices, previousChoices, action, source, timestamp }Consent state changed
banner-shownBanner became visible
banner-hiddenBanner became hidden
preferences-shownPreferences dialog opened
preferences-hiddenPreferences dialog closed
fixed-preferences-shownFixed preferences button shown
fixed-preferences-hiddenFixed preferences button hidden
script-blocked{ src, element, categories }Script blocked
script-unblocked{ src, element, categories }Script unblocked
iframe-blocked{ src, element, categories }Iframe blocked
iframe-unblocked{ src, element, categories }Iframe unblocked
map-blocked{ element, categories }Map embed blocked
map-unblocked{ element, categories }Map embed unblocked

On this page