Skip to main content

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

PropertyTypeDescriptionMore
categoryMapRecord<string, string>Map the CMP's consent categories (keys) to walkerOS consent groups (values).
explicitOnlybooleanOnly 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.

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": true,
      "history": [
        {
          "type": "explicit",
          "status": true
        }
      ]
    }
  }
]
Mapping
{
  "settings": {
    "categoryMap": {
      "essential": "functional",
      "functional": "analytics"
    }
  }
}
Out
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.

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": true,
      "history": [
        {
          "type": "explicit",
          "status": true
        }
      ]
    }
  }
]
Out
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.

Event
[
  {
    "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
        }
      ]
    }
  }
]
Out
// no output

Full consent

Usercentrics reports every category accepted via an explicit decision; the source emits a walker consent command granting essential, functional, and marketing.

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": true,
      "history": [
        {
          "type": "explicit",
          "status": true
        }
      ]
    }
  }
]
Out
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.

Event
[
  {
    "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
        }
      ]
    }
  }
]
Out
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.

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
        }
      ]
    }
  }
]
Out
elb("walker consent", {
  "essential": true,
  "functional": true,
  "marketing": false
})
SettingTypeDefaultDescription
apiVersion'auto' | 'v2' | 'v3''auto'Which Usercentrics API to target (auto-detects by default)
categoryMapRecord<string, string>{}Maps Usercentrics categories to walkerOS consent groups
explicitOnlybooleantrueOnly publish when the user has actively decided
v3EventNamestring'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_INITIALIZED and 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:

  1. Already initialized: if the CMP loaded before the source, consent is read statically through the official getters (V2 UC_UI.getServicesBaseInfo(), V3 __ucCmp.getConsentDetails()).

  2. CMP loads after the source: the source listens for UC_UI_INITIALIZED and reads the current consent state once the CMP is ready.

  3. User decisions: the source listens for UC_UI_CMP_EVENT (consent actions ACCEPT_ALL, DENY_ALL, and SAVE) and republishes the updated state.

  4. Category mapping: maps categories via categoryMap and calls elb('walker consent', state) with the mapped consent state.

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.

Reference

💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)