Usercentrics
Integrates Usercentrics consent management with walkerOS using the official Usercentrics events and consent getters, mapping category or service consent state to walkerOS consent groups.
We recommend the source package below over a hand-written event listener: it handles version detection, returning-visitor restore, and explicit-consent gating for you.
Installation
npm install @walkeros/web-source-cmp-usercentrics
import { startFlow } from '@walkeros/collector';
import { sourceUsercentrics } from '@walkeros/web-source-cmp-usercentrics';
await startFlow({
sources: {
consent: {
code: sourceUsercentrics,
config: {
settings: {
categoryMap: {
essential: 'functional',
functional: 'functional',
marketing: 'marketing',
},
},
},
},
},
});
Configuration
This source uses the standard source config wrapper (consent, data, env, id, ...). For the shared fields see source configuration. Package-specific fields live under config.settings and are listed below.
Settings
| Property | Type | Description | More |
|---|---|---|---|
categoryMap | Record<string, string> | Map the CMP's consent categories (keys) to walkerOS consent groups (values). | |
explicitOnly | boolean | Only publish when the user has actively decided (V3: consent.type EXPLICIT; V2: an EXPLICIT entry in service consent history). Implicit/default page-load states are suppressed. Set false to publish any snapshot including implicit. Default: true. |
Mapping
This package does not define custom rule-level settings. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.
Examples
Category map override
A custom categoryMap remaps essential to functional and functional to analytics before emitting the walker consent command.
[
{
"categorySlug": "essential",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
},
{
"categorySlug": "functional",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
},
{
"categorySlug": "marketing",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
}
]{
"settings": {
"categoryMap": {
"essential": "functional",
"functional": "analytics"
}
}
}elb("walker consent", {
"functional": true,
"analytics": true,
"marketing": true
})Consent change via CMP event
An ACCEPT_ALL decision fires UC_UI_CMP_EVENT; the source re-reads the services and emits the updated consent.
[
{
"categorySlug": "essential",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
},
{
"categorySlug": "functional",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
},
{
"categorySlug": "marketing",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
}
]elb("walker consent", {
"essential": true,
"functional": true,
"marketing": true
})First visit implicit (suppressed)
A first-visit snapshot carrying only implicit history is suppressed by the default explicitOnly gate, so no consent command is emitted.
[
{
"categorySlug": "essential",
"consent": {
"status": true,
"history": [
{
"type": "implicit",
"status": true
}
]
}
},
{
"categorySlug": "functional",
"consent": {
"status": false,
"history": [
{
"type": "implicit",
"status": false
}
]
}
},
{
"categorySlug": "marketing",
"consent": {
"status": false,
"history": [
{
"type": "implicit",
"status": false
}
]
}
}
]// no outputFull consent
Usercentrics reports every category accepted via an explicit decision; the source emits a walker consent command granting essential, functional, and marketing.
[
{
"categorySlug": "essential",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
},
{
"categorySlug": "functional",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
},
{
"categorySlug": "marketing",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
}
]elb("walker consent", {
"essential": true,
"functional": true,
"marketing": true
})Minimal consent
A "Deny all" explicit decision leaves only essential granted; functional and marketing are emitted as false.
[
{
"categorySlug": "essential",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
},
{
"categorySlug": "functional",
"consent": {
"status": false,
"history": [
{
"type": "explicit",
"status": false
}
]
}
},
{
"categorySlug": "marketing",
"consent": {
"status": false,
"history": [
{
"type": "explicit",
"status": false
}
]
}
}
]elb("walker consent", {
"essential": true,
"functional": false,
"marketing": false
})Returning visitor static read
When the CMP is already initialized with a stored explicit decision, the static read at init re-publishes that choice without any further event.
[
{
"categorySlug": "essential",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
},
{
"categorySlug": "functional",
"consent": {
"status": true,
"history": [
{
"type": "explicit",
"status": true
}
]
}
},
{
"categorySlug": "marketing",
"consent": {
"status": false,
"history": [
{
"type": "explicit",
"status": false
}
]
}
}
]elb("walker consent", {
"essential": true,
"functional": true,
"marketing": false
})| Setting | Type | Default | Description |
|---|---|---|---|
apiVersion | 'auto' | 'v2' | 'v3' | 'auto' | Which Usercentrics API to target (auto-detects by default) |
categoryMap | Record<string, string> | {} | Maps Usercentrics categories to walkerOS consent groups |
explicitOnly | boolean | true | Only publish when the user has actively decided |
v3EventName | string | 'UC_UI_CMP_EVENT' | V3 event name, override only for a custom admin event |
There is no configurable data-layer event setting: the source listens to the
always-emitted official Usercentrics events, so no eventName configuration or
Usercentrics admin window-event setup is required.
V2 vs V3 support
The source supports both Usercentrics V2 (window.UC_UI) and V3
(window.__ucCmp) APIs. With the default apiVersion: 'auto', detection runs
at init:
- If the CMP is already initialized, consent is read statically through the
official getters (V2
UC_UI.getServicesBaseInfo(), V3__ucCmp.getConsentDetails()). - If no CMP is present yet, the source listens for
UC_UI_INITIALIZEDand reads the current state once the CMP signals it is ready, so late-loading CMPs are still caught. - When both APIs are available, V3 is preferred.
Set apiVersion: 'v2' or 'v3' to force a specific integration.
Custom mapping example
await startFlow({
sources: {
consent: {
code: sourceUsercentrics,
config: {
settings: {
categoryMap: {
essential: 'functional',
functional: 'functional',
marketing: 'marketing',
},
explicitOnly: true,
},
},
},
},
});
How it works
The source uses Usercentrics' official integration surface across both API versions:
-
Already initialized: if the CMP loaded before the source, consent is read statically through the official getters (V2
UC_UI.getServicesBaseInfo(), V3__ucCmp.getConsentDetails()). -
CMP loads after the source: the source listens for
UC_UI_INITIALIZEDand reads the current consent state once the CMP is ready. -
User decisions: the source listens for
UC_UI_CMP_EVENT(consent actionsACCEPT_ALL,DENY_ALL, andSAVE) and republishes the updated state. -
Category mapping: maps categories via
categoryMapand callselb('walker consent', state)with the mapped consent state.
Explicit consent
By default (explicitOnly: true), the source publishes only states the user has
actively decided. It reads this from the official consent metadata: V3
consent.type === EXPLICIT, and V2 an EXPLICIT entry in the service consent
history. First-visit defaults stay suppressed. Set explicitOnly: false to also
publish implicit/default consent.
Timing considerations
A returning visitor's prior choice is applied on page load, either from the
static getter read (CMP already initialized) or on UC_UI_INITIALIZED (CMP loads
later). First-visit defaults stay suppressed under the default
explicitOnly: true. Set explicitOnly: false to publish any snapshot,
including implicit defaults. Ensure the consent source has no require
constraints so it initializes immediately.