PHPackages                             kaufmanndigital/gdpr-cookieconsent - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. kaufmanndigital/gdpr-cookieconsent

ActiveNeos-package[Utility &amp; Helpers](/categories/utility)

kaufmanndigital/gdpr-cookieconsent
==================================

A ready-to-run package, that integrates an advanced cookie consent banner into your Neos CMS site.

6.1.1(2mo ago)2540.7k↓48.6%10[1 issues](https://github.com/KaufmannDigital/KaufmannDigital.GDPR.CookieConsent/issues)GPL-3.0-or-laterJavaScript

Since Mar 12Pushed 2mo ago2 watchersCompare

[ Source](https://github.com/KaufmannDigital/KaufmannDigital.GDPR.CookieConsent)[ Packagist](https://packagist.org/packages/kaufmanndigital/gdpr-cookieconsent)[ Docs](https://github.com/KaufmannDigital/KaufmannDigital.GDPR.CookieConsent)[ RSS](/packages/kaufmanndigital-gdpr-cookieconsent/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (2)Versions (143)Used By (0)

KaufmannDigital.GDPR.CookieConsent
==================================

[](#kaufmanndigitalgdprcookieconsent)

A ready-to-run package, that integrates an advanced cookie consent banner into your Neos CMS site.
This is a further development of our previous [cookie consent package](https://github.com/KaufmannDigital/KaufmannDigital.CookieConsent). Through the individual configuration per service (cookie), this package is a perfect basis for creating GDPR compliant websites.

Versions
--------

[](#versions)

This package is available in multiple Version. Here you can check compatibility and maintenance-state.

Composer-VersionNeos-CompatibilityMaintenance`^1.0`&lt; 5.0⛔`^2.0`&gt;= 5.0⛔`^3.0`&gt;= 5.0⛔`^4.0`&gt;= 5.0⛔`^5.0`5.0 - 8.3🐛 (⚠️ [Note changed rendering and Styling](#styling))`^6.0`9.0🐛 ✨Installation
------------

[](#installation)

It's easier than you probably think!
Just run `composer require kaufmanndigital/gdpr-cookieconsent` (or require one of the versions from above)

After the installation it's necessary to run doctrine migrations: `./flow doctrine:migrate`

Configuration
-------------

[](#configuration)

Since this package is ready-to-run, you can configure your cookie banner in just a few Steps.

1. Create a new **Cookie-Settings Page** (shipped inside the Package) somewhere inside your Site-Tree.
2. Switch to the newly created page and edit the cookie banner contents to your wishes.
3. Add cookie-groups and cookies to the banner.

### Consent per dimension

[](#consent-per-dimension)

If you've configured one or multiple dimensions in Neos and you need to save different consents per dimension(-combination), you can just configure it using Settings.yaml:

```
KaufmannDigital:
  GDPR:
    CookieConsent:
      consentDimensions:
        - country
```

This example would save different consents per country for each user. This means, the user will see the CookieConsent again the first time he switches to another country.
It also influences the [way the content is stored in the cookie](#read-cookie-identifiers-from-cookie). Instead of a key `"default" there are now multiple entries within `"consents"` for each dimension(-combination). A short example:

```
{
  "consents": {
    "deu": [
      "necessary",
      "analytics",
      "marketing"
    ],
    "dnk": [
      "necessary",
      "analytics",
      "marketing"
    ]
  },
  "consentDate": "Tue, 11 Feb 2020 11:35:23 GMT",
  "expireDate": "Wed, 10 Feb 2021 23:00:00 GMT"
}
```

If you configured multiple dimensions in `consentDimensions`, they get connected here using underscores. Example: `deu_de`

### Exclude special pages (like imprint)

[](#exclude-special-pages-like-imprint)

You have 2 options to exclude special pages from displaying the Cookie-Settings. If you have a special NodeType, you want to exclude, you can set it as general rule by Settings.yaml:

```
KaufmannDigital:
  GDPR:
    CookieConsent:
      excludeDocumentNodeTypes:
        - 'Vendor.Package:Document.Imprint'
```

Alternatively, you can choose all kind of Document-Nodes in the Backend:
[![excluded documents](Documentation/Images/exclude_documents.png)](Documentation/Images/exclude_documents.png)

### Show banner after first interaction

[](#show-banner-after-first-interaction)

For example in SEO-aspects it makes sense to show the banner after users first interaction. You can easily configure the Package to behave like this:

```
KaufmannDigital:
  GDPR:
    CookieConsent:
      hideBeforeInteraction: true
```

### Auto-Accept necessary cookies

[](#auto-accept-necessary-cookies)

In some cases, you may need to accept necessary cookies without an user-interaction. For such a case you can easily add the following to your HTML:

```
var KD_GDPR_CC_ACCEPT_NECESSARY = true;
```

This makes the Package to auto-accept necessary cookies without showing the consent-window. The user of course can open the window by hand anyways to adjust the decision.

### Accept by Headers

[](#accept-by-headers)

If you are loading site-contents from other websites or in apps, you already have your needed consent. If so, you can configure Headers, which should accept your consents by default.

```
KaufmannDigital:
  GRDPR:
    CookieConsent:
      headerConsent:
        acceptAll:
          'User-Agent': 'Accepting-All-Agent*'
        acceptNecessary:
          'User-Agent': 'Accepting-needed-Agent*'
```

Here you can use the syntax of [fnmatch()](https://www.php.net/manual/de/function.fnmatch.php) for wildcards or similar.

### Accept by URL-Params

[](#accept-by-url-params)

You can also accept all cookies or necessary ones by URL-parameters. See, how to configure:

```
KaufmannDigital:
  GRDPR:
    CookieConsent:
      parameterConsent:
        acceptAll:
          'gdpr': 'accept-all'
        acceptNecessary:
          'gdpr': 'accept-needed'
```

In this example, you can accept all cookies by calling every page you want with param `?gdpr=accept-all` and accept necessary with param `?gdpr=accept-needed`.
You can also define multiple param/value combinations for each case.

### React to the user's cookie decision

[](#react-to-the-users-cookie-decision)

You can use one of these Methods to react on the user's decision on which Cookies are accepted:

#### Load JavaScript dynamically

[](#load-javascript-dynamically)

You can paste your JavaScript-Code while adding Cookies to the banner. The package will evaluate the user's decision and merge the required JavaScript dynamically for each user on the fly. You don't have to take care of anything. JavaScript gets loaded completely automatic. Cool, isn't it? 😎
*Ah! And don't worry about performance. All JS gets minified and cached for every single visitor individually.*

#### Read cookie-identifiers from cookie

[](#read-cookie-identifiers-from-cookie)

If you are already using another way to include your JavaScript, you can depend on the value of the Choice-Cookie.
It's named `KD_GDPR_CC` and contains all identifiers of groups and cookies you defined in Backend while configuration. The payload of that cookie could look like this:

```
{
  "consents": {
    "default": [
      "necessary",
      "analytics",
      "marketing"
    ]
  },
  "consentDate": "Tue, 11 Feb 2020 11:35:23 GMT",
  "expireDate": "Wed, 10 Feb 2021 23:00:00 GMT"
}
```

*If you configured [Consent per Dimensions](#consent-per-dimension), there are entries per dimension in `"consents"`, instead of default. [See example](#consent-per-dimension).*

So just check *consents* and load the needed JavaScript.
*Pro-Tip: If you are using Google Tag Manager to add your JS-Tags, you can define a custom datalayer-variable of type `First-Party-Cookie`, which can be used as condition inside triggers then.*

#### Google Tag Manager Integration

[](#google-tag-manager-integration)

There are two ways to interact between CookieConsent and Google's Tag-Manager. Also the new "Consent Mode" is supported. [We provided a full Guide here.](Documentation/GoogleTagManager.md)You can use the "old" way (also described in the link above) in alternative Tag-Managers, too.

#### Add a Re-open link

[](#add-a-re-open-link)

To create a link for reopening the banner, you only have to place a link with `#GDPR-CC-open-settings` as target:

```
Cookie-Settings
```

After clicking on such a link, the cookie-banner will be loaded via API. Old settings are used as presets.

#### Custom cookie name

[](#custom-cookie-name)

In some usecases it's needed to change the name of the Configuration-Cookie. That can easily be archived by using the following Setting:

```
KaufmannDigital:
  GDPR:
    CookieConsent:
      cookieName: 'CUSTOM_COOKIENAME'
```

#### Cookie lifetime

[](#cookie-lifetime)

For GDPR(DSGVO) - Reasons it could be required, to have the Settings-Cookie (which holds the CookieConsent-Settings) expired after a shorter time-period. This is configurable by days via Settings.yaml:

```
KaufmannDigital:
  GDPR:
    CookieConsent:
      cookieLifetime: 365 #365 days
```

#### Versioning

[](#versioning)

In some cases, it may be necessary to show the cookie-banner to people who have already gave their consent. For example, if a new cookie has been added.
To do this, you only need to edit the version date. You can find it in the inspector of the cookie-settings NodeType:
[![version-date setting](Documentation/Images/version-date.png)](Documentation/Images/version-date.png)

After the date has been changed, the banner will be shown again to all visitors, who have submitted the cookie banner before this date. Old settings are used as presets.

#### Invalidating user-decisions after time

[](#invalidating-user-decisions-after-time)

Sometimes it is necessary or advantageous to remind the user of his decision and ask him to confirm it again. For this purpose, a TTL for the decision can be set in the backend:
[![decision-time setting](Documentation/Images/Decision_TTL.png)](Documentation/Images/Decision_TTL.png)
The unit is seconds. After the set time has expired, the banner appears again with the default settings of the last decision, so the user can easily accept the old decision with just one click.
The value `0` (default) disables the repeated display of the banner.

### Styling

[](#styling)

#### Custom Banner-Styles

[](#custom-banner-styles)

The banner comes with default styling that aims to be GDPR compliant and accessible.

You can customise the banner by either:

1. Set a theme color (for buttons), the background color, text color and maximum width of the banner via the input fields in the inspector.
2. Create a CSS-File with your own styling and include it using Settings.yaml:

```
KaufmannDigital:
  GDPR:
    CookieConsent:
      customCSSFilepath: 'resource://Vendor.Package/Private/Styles/cookie-consent.css' #You can also use the public-path, of course
```

To get an idea of the CSS-styling and class-names, you can have a look [into our SCSS](Resources/Private/Styles/Main.scss).

Instead of writing out all the selectors in your custom file, it might be enough to just overwrite the relevant custom properties. This example file shows the custom properties that can be used:

```
.gdpr-cookieconsent-container {
    --cookieconsent-theme-color: rgb(0 137 203);
    --cookieconsent-overlay-color: rgb(0 0 0 / .75);
    --cookieconsent-bg-color: rgb(255 255 255 / 0.95);

    --cookieconsent-group-bg-color: rgb(255 255 255);

    --cookieconsent-button-text-color: rgb(255 255 255);
    --cookieconsent-button-primary-color: var(--cookieconsent-theme-color);
    --cookieconsent-button-secondary-color: rgb(255 255 255);
    --cookieconsent-button-primary-text-color: var(--cookieconsent-button-text-color);
    --cookieconsent-button-secondary-text-color: rgb(0 0 0);
    --cookieconsent-button-borderradius: 4px;

    --cookieconsent-spacing: 1rem;
    --cookieconsent-width: 1200px;

    --cookieconsent-focus-outline: black solid 2px;
    --cookieconsent-focus-outline-offset: 2px;
}

/* Switches options */
.gdpr-cookieconsent-switch {
    --cookieconsent-switch-thumb-size: 1.5rem;
    --cookieconsent-switch-thumb-color: rgb(255 255 255);
    --cookieconsent-switch-thumb-highlight-color: rgba(0 0 0 / 0.25);
    --cookieconsent-switch-length: calc(var(--cookieconsent-switch-thumb-size) * 2);
    --cookieconsent-switch-padding: 4px;
    --cookieconsent-switch-inactive-color: rgb(204 204 204);
    --cookieconsent-switch-active-color: var(--cookieconsent-theme-color);
    --cookieconsent-switch-thumb-size-small: 1rem;
    --cookieconsent-switch-outline: var(--cookieconsent-focus-outline);
    --cookieconsent-switch-outline-offset: var(--cookieconsent-focus-outline-offset);
}
```

⚠️ **Please note that colors set in the inspector will overwrite values set in your custom css file. You might need to unset the color values in the inspector first.**

#### Use your own fusion components in the banner

[](#use-your-own-fusion-components-in-the-banner)

Sometimes adjusting CSS isn't enough, and you just want to use your own button or text components in the banner. Good news: You can by overwriting the `renderer`of the following components:

- `KaufmannDigital.GDPR.CookieConsent:Component.Atom.AcceptAllButton`
- `KaufmannDigital.GDPR.CookieConsent:Component.Atom.SaveButton`
- `KaufmannDigital.GDPR.CookieConsent:Component.Atom.AcceptNecessaryButton`
- `KaufmannDigital.GDPR.CookieConsent:Component.Atom.OpenIndividualSettingsButton`
- `KaufmannDigital.GDPR.CookieConsent:Component.Atom.CloseIndividualSettingsButton`
- `KaufmannDigital.GDPR.CookieConsent:Component.Atom.Headline`
- `KaufmannDigital.GDPR.CookieConsent:Component.Atom.Text`

Accessing the button labels is as easy as accessing `${props.label}`.

Here's an example how to use your own button as the "Accept all" button:

```
prototype(KaufmannDigital.GDPR.CookieConsent:Component.Atom.AcceptAllButton) {
    renderer = Vendor.Site:Component.PrimaryButton {
        myLabel = ${props.label}
    }
}

```

### Restrict CORS headers to specific domains

[](#restrict-cors-headers-to-specific-domains)

If you are using the cookie banner on multiple domains, you can restrict the CORS headers to specific domains. This is useful if you want to use the same cookie banner on multiple domains, but don't want to allow all domains to access the cookie banner API. To allow access to the cookie banner API only from specific domains, you can configure the allowed domains in the settings:

```
KaufmannDigital:
  GDPR:
    CookieConsent:
      allowedOrigins:
        - 'subdomain.example.com'
        - 'example.org'
```

Roadmap / Planned Features
--------------------------

[](#roadmap--planned-features)

- Presets for popular cookies. For example:
    - Google Analytics
    - Matomo (Piwik)
    - Intercom Support-Chat
    - ...

Sponsors
--------

[](#sponsors)

We would like to thank our sponsors, who supported us financially during the development:

[![Mittwald Logo](Documentation/Sponsors/Mittwald/logo-mittwald.png)](https://www.mittwald.de/?utm_source=github&utm_medium=banner&utm_campaign=cookie-consent-manager-package)

Are you missing a feature in our solution? You want to support the development of this Package? Please don't hesitate to contact us!
Email:

Maintainer
----------

[](#maintainer)

This package is maintained by the [Neos Agency Kaufmann Digital](https://www.kaufmann.digital).
Feel free to send us your questions or requests to

### Issues and Pull-Requests are welcome!

[](#issues-and-pull-requests-are-welcome)

You got stuck while installing or configuring? You are missing something? You found a bug?
No problem, just create an issue or open a pull request. We'll have a look at it ASAP.

License
-------

[](#license)

Licensed under GPL-3, see [LICENSE](LICENSE)

###  Health Score

59

—

FairBetter than 99% of packages

Maintenance86

Actively maintained with recent releases

Popularity40

Moderate usage in the ecosystem

Community21

Small or concentrated contributor base

Maturity74

Established project with proven stability

 Bus Factor1

Top contributor holds 71.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~17 days

Recently: every ~9 days

Total

131

Last Release

64d ago

Major Versions

v4.0.x-dev → 5.4.12024-04-22

5.4.7 → 6.0.02025-06-20

5.4.8 → 6.0.22025-08-09

v5.4.x-dev → 6.0.32025-10-27

5.5.0 → 6.0.42026-02-10

### Community

Maintainers

![](https://www.gravatar.com/avatar/1ec6c2ae665e40ee04396a70c824f37be27b5f98330b66c18256ebd21dfb52b5?d=identicon)[kaufmanndigital](/maintainers/kaufmanndigital)

---

Top Contributors

[![Nikdro](https://avatars.githubusercontent.com/u/9807101?v=4)](https://github.com/Nikdro "Nikdro (153 commits)")[![Andyyyyyy](https://avatars.githubusercontent.com/u/18618394?v=4)](https://github.com/Andyyyyyy "Andyyyyyy (29 commits)")[![hphoeksma](https://avatars.githubusercontent.com/u/250683?v=4)](https://github.com/hphoeksma "hphoeksma (12 commits)")[![patricekaufmann](https://avatars.githubusercontent.com/u/41791606?v=4)](https://github.com/patricekaufmann "patricekaufmann (7 commits)")[![andrehoffmann30](https://avatars.githubusercontent.com/u/23524251?v=4)](https://github.com/andrehoffmann30 "andrehoffmann30 (2 commits)")[![daniellienert](https://avatars.githubusercontent.com/u/642226?v=4)](https://github.com/daniellienert "daniellienert (2 commits)")[![ru3fu5z](https://avatars.githubusercontent.com/u/28354864?v=4)](https://github.com/ru3fu5z "ru3fu5z (2 commits)")[![kdambekalns](https://avatars.githubusercontent.com/u/95873?v=4)](https://github.com/kdambekalns "kdambekalns (1 commits)")[![markuspfeifenberger](https://avatars.githubusercontent.com/u/7107293?v=4)](https://github.com/markuspfeifenberger "markuspfeifenberger (1 commits)")[![franzkugelmann](https://avatars.githubusercontent.com/u/11320147?v=4)](https://github.com/franzkugelmann "franzkugelmann (1 commits)")[![anianweber](https://avatars.githubusercontent.com/u/18150589?v=4)](https://github.com/anianweber "anianweber (1 commits)")[![simonhir](https://avatars.githubusercontent.com/u/14137977?v=4)](https://github.com/simonhir "simonhir (1 commits)")[![gjwnc](https://avatars.githubusercontent.com/u/19683930?v=4)](https://github.com/gjwnc "gjwnc (1 commits)")

---

Tags

cookie-consentcookie-consent-plugincookieshacktoberfestneosneos-cmsneos-pluginneoscms

### Embed Badge

![Health badge](/badges/kaufmanndigital-gdpr-cookieconsent/health.svg)

```
[![Health](https://phpackages.com/badges/kaufmanndigital-gdpr-cookieconsent/health.svg)](https://phpackages.com/packages/kaufmanndigital-gdpr-cookieconsent)
```

###  Alternatives

[sitegeist/monocle

An living-styleguide for Neos that is based on the actual fusion-code

45315.9k10](/packages/sitegeist-monocle)[sitegeist/kaleidoscope

Responsive-images for Neos

29352.4k10](/packages/sitegeist-kaleidoscope)[flowpack/listable

Tiny extension for listing things

35209.0k7](/packages/flowpack-listable)[neos/seo

SEO configuration and tools for Neos

13990.5k24](/packages/neos-seo)[shel/neos-colorpicker

A plugin for Neos CMS which provides a colorpicker editor

1494.4k6](/packages/shel-neos-colorpicker)[yoast/yoast-seo-for-neos

Yoast SEO for Neos CMS

24164.8k](/packages/yoast-yoast-seo-for-neos)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
