Consenti

UI Widget — API Methods

After creating a ConsentiSetup instance, the returned object exposes these methods. Only methods the developer needs to call are public — internal state is protected.

Quick reference

MethodReturnsDescription
Consent state
hasConsent()booleanTrue if a valid consent record exists for the current profile
getConsent()ConsentValue | nullThe current consent values keyed by cookie ID
getGTMConsent()Record<string, string> | nullConsent in GTM / Google Consent Mode v2 format
getConsentDate()Date | falseDate of most recent consent submission, or false if none
isCookieGranted(cookieId, requestValue?)boolean | ConsentStatusCheck if a single cookie is granted. Pass true as second arg to get the raw status string instead of a boolean
isCategoryGranted(categoryId, requestValue?)boolean | {[id: string]: ConsentStatus}[]True when every cookie in the category is granted. Pass true to get an array of per-cookie status records
Bulk actions
grantAll(onlyMandatory?)Promise<void>Accept all cookies. Pass true to grant only mandatory and deny the rest
denyAll(includingMandatory?)Promise<void>Deny all non-mandatory cookies. Pass true to deny mandatory too (logs a warning)
Visibility
showBanner(gpc?)voidProgrammatically show the main (or GPC) banner
hideBanner()voidHide the banner
showModal()voidOpen the preference modal
hideModal()voidClose the preference modal
bannerVisibility()'main' | 'gpc' | falseCurrent banner state
modalVisibility()'preference' | falseCurrent modal state
Events
on(event, handler)voidSubscribe to a typed widget event. The consenti: prefix is optional
off(event, handler)voidUnsubscribe a previously registered handler (pass the same function reference)
Lifecycle
init()Promise<void>Manually start initialisation — required when autoInit: false
onReady(cb)voidRegister a callback fired when the widget is fully initialised
switchLocale(locale)voidSwitch the active locale and re-render the widget
submitConsent(consent)Promise<void>Submit consent programmatically
deleteConsent()Promise<void>Delete consent record (cookie + backend)
reConsent()Promise<void>Delete consent and re-open the banner
destroy()voidUnmount the widget and remove all event listeners
Runtime configuration
setDarkMode(enable?)voidToggle or set dark mode without re-initialising. Omit enable to toggle
setTheme(theme)voidMerge CSS token overrides into the current theme at runtime
setConfig(config)voidDeep-merge a partial config. Re-applies theme/dark mode side-effects; does not re-init
setProfile(override)voidMerge a partial profile override and re-render visible UI without a network call
Diagnostics
version(){ package, profileVersion, consentVersion }Package version and active profile/consent version numbers

Method details

init()

Manually triggers widget initialisation. Normally called automatically on construction. Set autoInit: false in ConsentiConfig to disable auto-start — for example when the mount point (rootEl) is rendered after the widget is created.

ts
const widget = new ConsentiSetup({
  core: {},
  rootEl: '#consent-mount',
  autoInit: false,
})

// Later, once #consent-mount is available in the DOM:
await widget.init()
widget.onReady(() => {
  console.log('Widget ready:', widget.hasConsent())
})

init() is also useful after destroy() to re-initialise the same instance rather than creating a new one.

ts
widget.destroy()

// Swap config or wait for a condition, then:
await widget.init()
ℹ️Calling init() while a previous call is still in progress is a no-op — only one initialisation can run at a time per instance.

switchLocale(locale)

Switches the active locale, re-resolves the profile, and re-renders the widget with the new language. The locale switcher UI calls this automatically when the user picks a language. You can also call it programmatically.

ts
widget.switchLocale('fr')   // switch to French
widget.switchLocale('de-AT') // switch to Austrian German

The profile must have multiple locales configured for the switcher to be useful. See ConfigurationLocale switcher for setup details.

onReady(callback)

Called once the profile has resolved and the banner state has been determined. Safe to call before or after the widget has initialised.

ts
widget.onReady(() => {
  console.log('Widget ready. Has consent:', widget.hasConsent())
})

hasConsent()

ts
if (!widget.hasConsent()) {
  widget.showBanner()
}

getConsent()

ts
const consent = widget.getConsent()
// { analytics: 'granted', marketing: 'denied', necessary: 'granted' }

if (consent?.analytics === 'granted') {
  initAnalytics()
}

getGTMConsent()

Returns consent in the exact shape Google Tag Manager expects for Consent Mode v2:

ts
const gtm = widget.getGTMConsent()
// {
//   analytics_storage: 'granted',
//   ad_storage: 'denied',
//   ad_user_data: 'denied',
//   ad_personalization: 'denied',
//   functionality_storage: 'granted',
// }

submitConsent(consent)

Programmatically submit consent — useful for custom UI flows:

ts
await widget.submitConsent({
  analytics: 'granted',
  marketing: 'denied',
  necessary: 'granted',
})
⚠️Mandatory cookies (mandatory: true) are always 'granted' regardless of what you pass. Passing 'denied' for a mandatory cookie is silently ignored.

reConsent()

Deletes the existing consent record and re-opens the banner. Use for "Change cookie settings" buttons:

ts
document.querySelector('#change-cookie-settings')?.addEventListener('click', () => {
  widget.reConsent()
})

isCookieGranted(cookieId, requestValue?)

The most common gating pattern — check whether a single cookie is 'granted'without manually inspecting getConsent().

ts
// Boolean mode (default) — true if granted
if (widget.isCookieGranted('analytics_storage')) {
  initAnalytics()
}

// Value mode — returns the raw ConsentStatus string, or false if not in the consent map
const status = widget.isCookieGranted('marketing', true)
// 'granted' | 'denied' | 'objected' | false

During SSR or before init() completes, always returns false.

isCategoryGranted(categoryId, requestValue?)

Category-level consent check. The categoryId must match a Category.idin the profile's preference modal.

ts
// Boolean mode — true only when ALL cookies in the category are 'granted'
if (widget.isCategoryGranted('cat-analytics')) {
  loadHeatmaps()
}

// Value mode — one record per cookie in the category
const statuses = widget.isCategoryGranted('cat-marketing', true)
// [{ ad_storage: 'granted' }, { ad_personalization: 'denied' }]

Returns false / [] if the category ID is not found or the widget is not yet initialised.

grantAll(onlyMandatory?)

Programmatically accept cookies without the user interacting with the banner. Dismisses the banner after submitting.

ts
// Accept everything
await widget.grantAll()

// Accept only mandatory cookies — deny the rest (useful for "Reject all" variants)
await widget.grantAll(true)

denyAll(includingMandatory?)

Programmatically deny all non-mandatory cookies. Dismisses the banner after submitting.

ts
// Deny non-mandatory; mandatory cookies stay 'granted'
await widget.denyAll()

// Deny everything including mandatory — use with caution
await widget.denyAll(true)
⚠️Passing true to denyAll denies mandatory cookies. This is intentionally allowed for testing and special integrations, but will log a console.warn as a reminder.

on(event, handler) / off(event, handler)

Typed event subscription API — a cleaner alternative to window.addEventListener. The consenti: prefix on the event name is optional; both forms are accepted.

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

const handler = (data: ConsentEvent) => {
  console.log('Consent saved:', data.consent)
  console.log('Action:', data.consentAction) // 'accept_all' | 'reject_all' | 'custom' | 'update'
}

// Subscribe — both are equivalent
widget.on('consentSubmitted', handler)
widget.on('consenti:consentSubmitted', handler)

// Unsubscribe — must pass the same function reference
widget.off('consentSubmitted', handler)

// All supported event names:
// 'bannerInitialized'       — widget initialised; hasExistingConsent is in the detail
// 'bannerVisibility'        — banner showed or hid; show / action flags in detail
// 'modalVisibility'         — modal opened or closed
// 'consentBeingSubmitted'   — user clicked a button (before API call)
// 'consentSubmitted'        — consent saved (cookie written + API call if configured)
ℹ️on() / off() use the same underlying DOM events as raw window.addEventListener calls. Both can coexist in the same page. Registered handlers are automatically cleaned up when destroy() is called.

setDarkMode(enable?)

Toggle or set dark mode at runtime without re-initialising the widget. The dark class is applied to both the banner root and the preference modal.

ts
widget.setDarkMode()       // toggle current state
widget.setDarkMode(true)  // force dark
widget.setDarkMode(false) // force light

// Typical use: follow the OS preference and update live
const mq = window.matchMedia('(prefers-color-scheme: dark)')
widget.setDarkMode(mq.matches)
mq.addEventListener('change', (e) => widget.setDarkMode(e.matches))

setTheme(theme)

Merge CSS token overrides into the current theme at runtime. CSS custom properties on the root element update immediately — no page reload required.

ts
// Switch primary colour on the fly (e.g. white-label tenant switch)
widget.setTheme({ primaryColor: '#d32f2f', primaryTextColor: '#ffffff' })

// Only the provided keys are updated — other theme values are preserved
widget.setTheme({ borderRadius: '0px' })

setConfig(config)

Deep-merges a partial ConsentiConfig into the current config without re-initialising. Theme and dark mode side-effects are re-applied immediately. For locale or profile changes, follow up with switchLocale() or init().

ts
// Update theme and dark mode together
widget.setConfig({
  darkMode: true,
  core: { theme: { primaryColor: '#1a73e8' } },
})

// Disable powered-by branding at runtime
widget.setConfig({ hidePoweredBy: true })

setProfile(override)

Merges a partial profile override into the active profile and re-renders any currently visible banner or modal — no network call is made. Useful for A/B testing copy or dynamically adjusting the banner text after init.

ts
// Change the banner heading live
widget.setProfile({
  mainBanner: { heading: 'We care about your privacy' },
})

// Swap the modal position
widget.setProfile({
  preferenceModal: { position: 'left' },
})
ℹ️setProfile is a no-op before init() completes — the resolved base profile must exist for the merge to run.

version()

Returns the package version and the currently active profile and consent version numbers. Useful for support diagnostics and feature flags.

ts
const info = widget.version()
// {
//   package: '0.1.1',       — npm package version
//   profileVersion: 3,      — profile.version from the API or local profile
//   consentVersion: 1,      — consent schema version (increments on breaking cookie format changes)
// }
console.log(`Consenti ${info.package} | profile v${info.profileVersion}`)

destroy()

Removes the banner DOM, modal DOM, BroadcastChannel listener, and all event listeners (including those registered via on()). Call when unmounting in SPA route changes if you manage the lifecycle manually.

ts
// In a SPA router's cleanup callback:
widget.destroy()