> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# CMP sources

walkerOS provides ready-made source packages for popular Consent Management Platforms. Each source listens for CMP events and automatically calls `elb('walker consent', state)`, with no manual event listener code needed.

| CMP                                                                        | Package                                 |
| -------------------------------------------------------------------------- | --------------------------------------- |
| [CookieFirst](/preview/pr-749/docs/sources/web/cmps/cookiefirst.md)        | `@walkeros/web-source-cmp-cookiefirst`  |
| [CookiePro / OneTrust](/preview/pr-749/docs/sources/web/cmps/cookiepro.md) | `@walkeros/web-source-cmp-cookiepro`    |
| [Usercentrics](/preview/pr-749/docs/sources/web/cmps/usercentrics.md)      | `@walkeros/web-source-cmp-usercentrics` |

## Conditional activation with `require`[​](#conditional-activation-with-require "Direct link to conditional-activation-with-require")

Some sources and destinations shouldn't act on lifecycle events right away. They may depend on consent status being resolved first, or need information provided by other sources (like session IDs). The `require` option solves this by gating `on()` delivery (for sources) or initialization (for destinations) until specific collector events have fired.

Add `require` to any source or destination `config` to gate it on the listed events:

```json
{
  "sources": {
    "consent": {
      "package": "@walkeros/web-source-cmp-cookiefirst"
    },
    "dataLayer": {
      "package": "@walkeros/web-source-datalayer",
      "config": { "require": ["consent"] }
    }
  }
}
```

In this example the CMP source initializes immediately and calls `elb('walker consent', state)` once a consent state is known. Until then, the dataLayer source holds back its `run` delivery, so the dataLayer entries that existed before its `init()` ran are replayed only after a consent state is recorded. `require` does not stop a source from capturing: entries pushed to the dataLayer after its `init()` ran enter the flow at once. To drop a source's events without consent, set the source's `config.consent` (see the [consent guide](/preview/pr-749/docs/guides/consent.md#gate-a-source-with-consent)).

### How `require` works[​](#how-require-works "Direct link to how-require-works")

1. Sources are registered immediately and their `Instance.init()` runs eagerly after registration. `require` does not block init; it gates `on()` delivery. Lifecycle events targeted at a source with unmet `require` are buffered in `Instance.queueOn`.
2. Destinations with `require` are held as **pending** during initialization until their listed events fire.
3. A `require` entry is satisfied by the collector's **current recorded state**, not only by a future event. So order does not matter: a step activates whether the required state (such as a CMP applying consent) was recorded before or after the step registered. The collector reconciles every pending step against current state at each state change, at the run barrier, and once after all sources have registered.
4. Sources whose `require` just emptied have their queued lifecycle events replayed via `source.on(type, data)`. Destinations whose `require` just emptied are registered and receive the current run's events from the collector's replay buffer (bounded by the collector's `queueMax`), unless they set `queue: false`. The destination's `on()` handler receives the current state, including the consent state that activated it, before those events are delivered.

### Key points[​](#key-points "Direct link to Key points")

* **CMP sources need no `require`**: a CMP source reads and reports consent in `init()`, which `require` does not delay, and it has no `on()` to hold back
* **Accepted values**: any collector event type, such as `"consent"`, `"session"`, `"user"`, `"run"`, `"config"`, `"globals"`, etc.
* **AND logic**: `require: ["consent", "session"]` waits for **both** events
* **Chained activation**: a source still runs `init()` while it waits on `require`, so a command it sends can satisfy another step's `require`. The session source without `settings.consent`, for example, records `session` when the collector runs, which activates a step waiting for `["session"]`

## How CMP sources work[​](#how-cmp-sources-work "Direct link to How CMP sources work")

1. Detecting if the CMP is already loaded and reading existing consent
2. Listening for CMP-specific events on consent changes
3. Mapping CMP categories to walkerOS consent groups via `categoryMap`
4. Calling `elb('walker consent', state)` with the mapped state

CMP sources perform their initial consent read during `init()`, not in the source factory. The factory stays side-effect free; the consent emit happens once the collector runs the source's `init()`. Combined with the current-state `require` matching above, a `require: ["consent"]` step activates whichever source recorded the consent, and whenever it did.

When several CMP categories map to the same walkerOS group, the CookieFirst and CookiePro sources grant the group if any of them is granted, and the Usercentrics source grants it only if all of them are.

The CookiePro and Usercentrics sources support `explicitOnly` (default: `true`) to skip implicit or default consent and report only active user choices. The CookieFirst source reports nothing until the visitor has made a choice.

For more details on how consent works in walkerOS, see the [consent management guide](/preview/pr-749/docs/guides/consent.md).
