Events
Subscribe to SDK lifecycle, consent, UI, and blocking events.
OptinStack emits events through two channels simultaneously:
- SDK events via
OptinStack.events.on()/OptinStack.events.off() - DOM CustomEvents on
document.documentElementwith theoptinstack: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');
});Consent Events
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');
});consent-updated
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
});UI Visibility Events
These events fire when consent UI elements are shown or hidden:
| Event | When |
|---|---|
banner-shown | Banner becomes visible |
banner-hidden | Banner becomes hidden |
preferences-shown | Preferences dialog becomes visible |
preferences-hidden | Preferences dialog becomes hidden |
fixed-preferences-shown | Fixed preferences button becomes visible |
fixed-preferences-hidden | Fixed 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
| Event | Payload | Description |
|---|---|---|
ready | — | SDK fully initialized |
accept-all | — | All categories accepted |
reject-all | — | Optional categories rejected |
consent-updated | { id, choices, previousChoices, action, source, timestamp } | Consent state changed |
banner-shown | — | Banner became visible |
banner-hidden | — | Banner became hidden |
preferences-shown | — | Preferences dialog opened |
preferences-hidden | — | Preferences dialog closed |
fixed-preferences-shown | — | Fixed preferences button shown |
fixed-preferences-hidden | — | Fixed 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 |