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

# Cookiebot

Integrates [Cookiebot](https://www.cookiebot.com/) consent management with walkerOS by mapping Cookiebot's categories `preferences`, `statistics` and `marketing` to walkerOS consent groups. Strictly necessary cookies are reported as `necessary`.

## Installation[​](#installation "Direct link to Installation")

```
npm install @walkeros/web-source-cmp-cookiebot
```

```
import { startFlow } from '@walkeros/collector';

import { sourceCookiebot } from '@walkeros/web-source-cmp-cookiebot';



await startFlow({

  sources: {

    consent: {

      code: sourceCookiebot,

    },

  },

});
```

## Configuration[​](#configuration "Direct link to Configuration")

This source uses the standard source config wrapper (consent, data, env, id, ...). For the shared fields see [source configuration](https://www.walkeros.io/docs/sources.md#configuration). Package-specific fields live under `config.settings` and are listed below.

## Settings[​](#settings "Direct link to Settings")

| Property       | Type                     | Description                                                                                                                                                                                                                                       | More |
| -------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| `categoryMap`  | `Record<string, string>` | Map the CMP's consent categories (keys) to walkerOS consent groups (values).                                                                                                                                                                      |      |
| `explicitOnly` | `boolean`                | Only process consent the visitor actively gave (Cookiebot consent.method 'explicit'). Implied consent, which Cookiebot sets on its own (outside a region that requires consent, an implied banner, or an old consent), is skipped. Default: true. |      |

## Mapping[​](#mapping "Direct link to Mapping")

This package does not define custom rule-level settings. For the standard rule fields (consent, condition, data, batch, name, policy) see [mapping](https://www.walkeros.io/docs/mapping.md).

## Examples

### Allow all

The visitor clicks "Allow all". Cookiebot fires CookiebotOnAccept and the source emits a walker consent command granting functional, analytics and marketing.

Event

```json
{
  "consented": true,
  "declined": false,
  "hasResponse": true,
  "consent": {
    "stamp": "example-stamp-full",
    "necessary": true,
    "preferences": true,
    "statistics": true,
    "marketing": true,
    "method": "explicit"
  }
}
```

Out

```javascript
elb("walker consent", {
  "necessary": true,
  "functional": true,
  "analytics": true,
  "marketing": true
})
```

### Category map override

A custom categoryMap reports Cookiebot statistics as a statistics group instead of analytics.

Event

```json
{
  "consented": true,
  "declined": false,
  "hasResponse": true,
  "consent": {
    "stamp": "example-stamp-partial",
    "necessary": true,
    "preferences": true,
    "statistics": true,
    "marketing": false,
    "method": "explicit"
  }
}
```

Mapping

```json
{
  "settings": {
    "categoryMap": {
      "statistics": "statistics"
    }
  }
}
```

Out

```javascript
elb("walker consent", {
  "necessary": true,
  "functional": true,
  "statistics": true,
  "marketing": false
})
```

### First visit

The banner is still open and Cookiebot holds no response, so the source emits no consent command until the visitor decides.

Event

```json
{
  "consented": false,
  "declined": false,
  "hasResponse": false,
  "consent": {
    "stamp": "0",
    "necessary": true,
    "preferences": false,
    "statistics": false,
    "marketing": false,
    "method": null
  }
}
```

Out

```javascript
// no output
```

### Implied consent (explicitOnly off)

With explicitOnly set to false the source follows the consent Cookiebot implied and grants every group.

Event

```json
{
  "consented": true,
  "declined": false,
  "hasResponse": true,
  "consent": {
    "stamp": "-1",
    "necessary": true,
    "preferences": true,
    "statistics": true,
    "marketing": true,
    "method": "implied"
  }
}
```

Mapping

```json
{
  "settings": {
    "explicitOnly": false
  }
}
```

Out

```javascript
elb("walker consent", {
  "necessary": true,
  "functional": true,
  "analytics": true,
  "marketing": true
})
```

### Implied consent (skipped)

Cookiebot consented on its own (consent.method implied), for example outside the regions where the site asks. The default explicitOnly publishes only an explicit decision, so no consent command is emitted, and a visitor Cookiebot never asks never sends one.

Event

```json
{
  "consented": true,
  "declined": false,
  "hasResponse": true,
  "consent": {
    "stamp": "-1",
    "necessary": true,
    "preferences": true,
    "statistics": true,
    "marketing": true,
    "method": "implied"
  }
}
```

Out

```javascript
// no output
```

### Necessary only

The visitor clicks "Use necessary cookies only". Cookiebot fires CookiebotOnDecline and the source emits functional, analytics and marketing as false.

Event

```json
{
  "consented": false,
  "declined": true,
  "hasResponse": true,
  "consent": {
    "stamp": "example-stamp-necessary",
    "necessary": true,
    "preferences": false,
    "statistics": false,
    "marketing": false,
    "method": "explicit"
  }
}
```

Out

```javascript
elb("walker consent", {
  "necessary": true,
  "functional": false,
  "analytics": false,
  "marketing": false
})
```

### Returning visitor

Cookiebot already restored a stored choice when the source starts, so the static read at init publishes it at once.

Event

```json
{
  "consented": true,
  "declined": false,
  "hasResponse": true,
  "consent": {
    "stamp": "example-stamp-partial",
    "necessary": true,
    "preferences": true,
    "statistics": true,
    "marketing": false,
    "method": "explicit"
  }
}
```

Out

```javascript
elb("walker consent", {
  "necessary": true,
  "functional": true,
  "analytics": true,
  "marketing": false
})
```

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

1. **Already loaded**: If `window.Cookiebot` already holds the visitor's choice when the source starts, the source publishes it at once.

2. **Decision events**: The source listens for Cookiebot's `CookiebotOnAccept` and `CookiebotOnDecline` window events. Cookiebot fires one of them on every page load with a stored choice and again after each new choice. Each time, the source reads `window.Cookiebot.consent`.

3. **Mapping**: The four Cookiebot categories are mapped through `categoryMap` and published with `elb('walker consent', state)`. Denied groups are published as `false`.

4. **One command per choice**: A stored choice is reported both by the read at start and by the event on page load. The source sends a state only when it differs from the last one it sent.

### Default category mapping[​](#default-category-mapping "Direct link to Default category mapping")

```
{

  preferences: 'functional',

  statistics: 'analytics',

  marketing: 'marketing',

}
```

`necessary` has no entry and is published as `necessary`. Cookiebot always grants it, so `functional` follows the visitor's `preferences` choice instead of being granted with every choice. Category names are compared case-insensitively, and any category without an entry keeps its own name.

When several categories map to the same group, the group is `true` only if every one of them is granted: any deny denies.

Custom entries are merged with the default mapping. Specify only the categories you want to override. All other defaults remain active.

### Custom mapping example[​](#custom-mapping-example "Direct link to Custom mapping example")

```
await startFlow({

  sources: {

    consent: {

      code: sourceCookiebot,

      config: {

        settings: {

          categoryMap: {

            statistics: 'statistics', // Use 'statistics' instead of 'analytics'

          },

        },

      },

    },

  },

});
```

### Implied consent[​](#implied-consent "Direct link to Implied consent")

Cookiebot records how consent was given in `consent.method`: `explicit` when the visitor chose, `implied` when Cookiebot consented on its own. Cookiebot implies consent for visitors outside the regions where your site asks for consent, for an implied-consent banner, and for old consents of unknown method.

With `explicitOnly: true` (the default) the source publishes only explicit consent. For a visitor with implied consent it sends no consent command: destinations gated with `config.consent` queue the visitor's events until the visitor makes an explicit choice, and sources gated with `config.consent` drop them. A visitor Cookiebot never asks, such as one outside the regions where your site asks for consent, makes no explicit choice, so those destinations never send their events (each push answers `queued` with the reason `consent`), and a destination with `require: ["consent"]` never starts. To follow the consent Cookiebot implied, set `explicitOnly: false`:

```
await startFlow({

  sources: {

    consent: {

      code: sourceCookiebot,

      config: { settings: { explicitOnly: false } },

    },

  },

});
```

### Google Consent Mode[​](#google-consent-mode "Direct link to Google Consent Mode")

Cookiebot sends Google Consent Mode updates itself unless its script tag carries `data-consentmode="disabled"`. The [gtag destination](https://www.walkeros.io/docs/destinations/web/gtag.md) does the same with its `como` setting, so with both on Google receives every update twice. Keep one of them: disable it on the Cookiebot script tag, or set `"como": false` on the gtag destination.

### Timing considerations[​](#timing-considerations "Direct link to Timing considerations")

The source handles both load orders:

* **Cookiebot loads before the source**: the read at start publishes the stored choice.
* **Source loads before Cookiebot**: the source publishes the choice when Cookiebot fires `CookiebotOnAccept` or `CookiebotOnDecline`.
* **First visit**: until the visitor answers the banner, Cookiebot holds no choice and the source sends nothing.

## Reference[​](#reference "Direct link to Reference")

* [Cookiebot JavaScript SDK](https://www.cookiebot.com/en/developer/)
* [Source code](https://github.com/elbwalker/walkerOS/tree/main/packages/web/sources/cmps/cookiebot)
