Consenti

UI Widget — Events

Consenti fires custom DOM events on window at every consent lifecycle step. All events are prefixed consenti: and carry a typed detail payload.

Event reference

EventFired when
consenti:bannerInitializedWidget initialises and determines whether to show the banner
consenti:bannerVisibilityBanner shows or hides
consenti:modalVisibilityPreference modal shows or hides
consenti:consentBeingSubmittedUser clicked a consent button (before API call)
consenti:consentSubmittedConsent saved (cookie written + API call if configured)

Typed API — on() / off()

The recommended way to subscribe to events is widget.on() / widget.off(). This API is typed, handles the CustomEvent unwrapping for you, and cleans up automatically when widget.destroy() is called. The consenti: prefix on the event name is optional.

ts
import type { ConsentEvent } from '@consenti/ui'

const handler = (data: ConsentEvent) => {
  console.log('Consent saved:', data.consent)
  console.log('Action:', data.consentAction)
  console.log('GPC detected:', data.gpcDetected)
}

widget.on('consentSubmitted', handler)      // 'consenti:' prefix is optional
widget.off('consentSubmitted', handler)     // must pass the same function reference

Raw DOM listeners

Raw window.addEventListener calls work too and can coexist with on():

ts
import type { ConsentEvent } from '@consenti/ui'

window.addEventListener('consenti:consentSubmitted', (e: Event) => {
  const detail = (e as CustomEvent<ConsentEvent>).detail
  console.log('Consent action:', detail.consentAction) // 'accept_all' | 'reject_all' | 'custom' | 'update'
  console.log('Consent values:', detail.consent)       // { analytics: 'granted', marketing: 'denied', ... }
  console.log('Page URL:', detail.pageUrl)
  console.log('GPC detected:', detail.gpcDetected)
})

Detail types

BannerInitializedDetail

ts
interface BannerInitializedDetail {
  profileId: string
  regulation: 'gdpr' | 'ccpa'
  hasExistingConsent: boolean  // true if valid consent cookie exists
  gpcDetected: boolean
  willShow: boolean            // true if banner will be rendered
}

BannerVisibilityDetail

ts
interface BannerVisibilityDetail {
  show: boolean               // true = banner appeared; false = banner hidden
  bannerType: 'main' | 'gpc' // which banner
  action: boolean             // true = triggered by user button click
}

ModalVisibilityDetail

ts
interface ModalVisibilityDetail {
  show: boolean               // true = modal opened; false = modal closed
  action: boolean             // true = triggered by user button click
}

ConsentSubmittedDetail

ts
interface ConsentSubmittedDetail {
  consentId: string                        // UUID per submission
  visitorId: string                        // visitor UUID (stable across sessions)
  profileId: string
  profileVersion: number
  consentJson: Record<string, ConsentStatus>  // { analytics: 'granted', ... }
  consentAction: 'accept_all' | 'reject_all' | 'custom' | 'update'
  gpcDetected: boolean
  pageUrl: string                          // window.location.href at submission time
  timestamp: string                        // ISO 8601
  apiResponse?: unknown                    // backend response if api.enabled: true
}

GTM dataLayer pushes

When utils.gtm.containerId is set, Consenti pushes to window.dataLayerin the standard Google Consent Mode v2 format:

js
// On initialization (default denied state)
dataLayer.push({
  'event': 'consent_default',
  'consent_type': 'analytics_storage',
  'consent_value': 'denied',
})

// On submission
dataLayer.push({
  'event': 'consent_update',
  'analytics_storage': 'granted',
  'ad_storage': 'denied',
  'ad_user_data': 'denied',
  'ad_personalization': 'denied',
  'functionality_storage': 'granted',
})
ℹ️Consenti automatically detects window.gtag and window.google_tag_managerbefore emitting cookieless pings — no-op pollution is prevented on non-Google sites.

ConsentScript — auto-load scripts on consent

ConsentScript watches consenti:consentSubmitted and injects or removes a <script> tag based on whether a specific cookie ID is granted. Consent is also evaluated immediately at construction time so existing consent is honoured without waiting for the next submission event.

ts
import { ConsentScript } from '@consenti/ui'

// bind: true (default) — auto-removes script on consent revoke, re-injects on re-grant
new ConsentScript({
  cookieId: 'analytics',
  src: 'https://cdn.example.com/analytics.js',
  onLoad: () => console.log('Analytics loaded'),
  onRevoke: () => console.log('Analytics removed'),
})

// bind: false — check consent once at construction; never attach a change listener
new ConsentScript({
  cookieId: 'analytics',
  src: 'https://cdn.example.com/analytics.js',
  bind: false,
})

CookieTrigger — open banner/modal from any element

Attach a trigger to any existing element or let Consenti auto-create a button:

ts
import { CookieTrigger } from '@consenti/ui'

// Attach to existing element
new CookieTrigger({ selector: '#cookie-settings', action: 'modal' })

// Or auto-create a button
new CookieTrigger({
  action: 'banner',
  label: 'Cookie Settings',
  appendTo: document.querySelector('#footer'),
})