lerni / klaro-cookie-consent
Klaro Silverstripe Integration
Installs: 4 892
Dependents: 0
Suggesters: 2
Security: 0
Stars: 6
Watchers: 3
Forks: 3
Open Issues: 0
Type:silverstripe-vendormodule
Requires
Suggests
- lerni/silverstripe-googleanalytics: Silverstripe Google Analytics & Tag Manager Module
This package is auto-updated.
Last update: 2025-06-25 14:21:35 UTC
README
Silverstripe Klaro! implements KIProtect/klaro. A consent manager that helps to be transparent about third-party applications and be compliant with GDPR and ePrivacy. This module is inspired by nomidi/kw-cookie-consent.
Requirements
- silverstripe/cms ^5
- silverstripe/siteconfig ^5
- symbiote/silverstripe-gridfieldextensions ^4
Compatibility Version
- There is a 3.x branch with a backport for Silverstripe 3.
- For Silverstripe 4.x & 5.x v2
- For Silverstripe 5.x supports consent-mode-v2 & resolves some long standing issues like default values, better fluent support, Consent Mode V2
- For Silverstripe 6.x provides compatibility with version 6.x
Suggested
- lerni/silverstripe-tracking
Google Consent Mode v2 Integration
This module includes support for Google Consent Mode v2, providing privacy-compliant tracking and enhanced conversion modeling capabilities.
Key Features
- Automatic Consent Updates: When users accept or decline services, Google's consent state is automatically updated
- Enhanced Conversion Modeling: Supports advanced consent mode for better data insights while respecting privacy
- All Consent Types: "Callback-functions" are maintained in CMS. Original, v2 consent parameters and also for other venders like Microsoft-Clarity are possible.
Setup
- Install the module and run
dev/build
- Go to Settings > Cookie Consent in the CMS
- Enable "Cookie Is Active"
- Configure your services with appropriate Google Consent Types
- Add custom JavaScript callbacks
Example Configuration
Service: Google Analytics
Consent Type: analytics_storage
Default State: denied
On Accept: gtag('consent', 'update', {'analytics_storage': 'granted'});
Installation
Composer is the recommended way installing Silverstripe modules.
composer require lerni/klaro-cookie-consent:dev-v2 composer require lerni/klaro-cookie-consent:dev-3.x composer require lerni/klaro-cookie-consent:dev-5.x composer require lerni/klaro-cookie-consent:dev-6.x
Run dev/build
KlaroDefaults Task
Populates SiteConfig with default translations from Klaro and applies custom translations from your language file.
php ./vendor/silverstripe/framework/cli-script.php dev/tasks/klaro-defaults
_config/klaro_defaults.yml
contains default-records for CookieCategory
& CookieEntry
in german. Those can can be nulled and overriden.
Getting started
The module loads klaro.js per KlaroInitExtension
which is applied to ContentController. The config is served with KlaroConfigController
and available per /_klaro-config
. Consent settings can be linked using <a href="#klaro" onClick="klaro.show();return false;">Cookie consent</a>
or by using a ShortCode in CMS. ShortCode [ConsentLink]
takes parameter beforeText
& afterText
and is shown conditionally of SiteConfig->CookieIsActive
.
Managing third-party apps/trackers
To manage third-party scripts and ensure they only run if the user consents with their use, simply replace the src
attribute with data-src
, change the type
attribute to text/plain
and add a data-type
attribute with the original type and add a data-name
field that matches the name of the app as given in config. Example:
<script type="text/plain" data-type="text/javascript" data-name="optimizely" data-src="https://cdn.optimizely.com/js/10196010078.js"> </script>
Klaro will manage script execution based on each service's consent settings and whether consent is required or if opt-out is the default behavior.
The same method also works for iframes, images, stylesheets and other elements with a src
or type
attribute.
Advanced Configuration
Custom Consent Callbacks
Custom JavaScript can be added that runs when users accept or decline services. This is where service-specific logic and Consent Mode updates are handled.
// Example: Analytics with Consent Mode v2 onAccept: ` if(typeof gtag === "function") { gtag("consent", "update", { analytics_storage: "granted" }); } console.log("Google Analytics accepted"); ` // Example: Microsoft Clarity (no gtag needed) onAccept: ` if (typeof clarity !== 'undefined') { clarity('consent'); } console.log("Microsoft Clarity accepted"); ` // Example: Custom tracking service onAccept: ` if(typeof customTracker !== 'undefined') { customTracker.enable(); } `
Each service can have its own specific callback logic. Google services typically use gtag('consent', 'update', ...)
while other services may have their own APIs.
Integration with Google Tag Manager
When using Google Tag Manager, the consent mode updates are automatically handled:
<!-- GTM script will automatically respect consent signals --> <script data-type="application/javascript" data-name="google-analytics"> gtag('config', 'GTM-XXXXXXX'); </script>
Styling
Example SCSS customisation
// !klaro html .klaro { --notice-max-width: 440px; .cookie-modal, .cookie-notice { z-index: 9100; a { color: lighten($link-color, 70%); } .cm-btn { cursor: pointer; font-size: 14px; border-radius: 0.1em; margin-right: 1.2em; } } .cookie-notice { .cn-body { // klaro sets font-size on block elements - we're calculating back to maintain horizontal spacing :-/ @media (max-width: 1023px) { padding-right: #{$lh * math.div($font-size, 14px)}em !important; padding-left: #{$lh * math.div($font-size, 14px)}em !important; @include breakpoint($Mneg) { padding-right: #{0.5 * $lh * math.div($font-size, 14px)}em !important; padding-left: #{0.5 * $lh * math.div($font-size, 14px)}em !important; } } } h2 { font-size: 1.1em; margin-top: 0.6em; } p { margin: 0.3em 0 !important; } .cn-ok { display: flex; flex-wrap: wrap; justify-content: flex-start !important; .cn-buttons { display: flex !important; order: 1; // decline .cm-btn.cn-decline { background-color: $gray; order: 1; } // accept all .cm-btn.cm-btn-success { background-color: $link-color; order: 0; } } // modal link .cn-learn-more { display: block; margin-right: 0; order: 2; flex: 0 0 auto; padding: 0.5em 0; } } } .cookie-modal { .cm-header a { @include bold; } .cm-app-title { font-size: 14px; } // switch disabled .cm-list-label .slider { background-color: $gray; } // slider-switches .cm-list-input:checked + .cm-list-label .slider { background-color: $link-color; } // required switch enabled .cm-list-input.required:checked + .cm-list-label .slider { background-color: darken($link-color, 10%); &::before { background-color: darken($white, 16%); } } // halve is used on parent if children are on & off .cm-list-input.half-checked:checked + .cm-list-label .slider { background-color: mix($link-color, $white, 71%); } .cm-list-description { color: $gray--light; } // accept all .cm-btn.cm-btn-accept-all { background-color: $link-color; } // save selection, decline .cm-btn.cm-btn-accept, .cm-btn.cm-btn-decline { background-color: $gray; } } } // klaro! contextual consent [data-type="placeholder"] { position: absolute; background-color: $gray--light; display: flex; justify-content: center; align-items: center; flex-direction: column; width: 100%; height: 100%; top: 0; right: 0; bottom: 0; left: 0; padding: #{$lh}em; .cm-as-context-notice { height: auto; } .context-notice { &:last-child { margin-bottom: 0; } .cm-buttons { display: flex; gap: 1em; } button.cm-btn { display: inline-block; padding: #{math.div($lh, 4)}em #{math.div($lh, 2)}em; border: none; text-transform: uppercase; color: $white; font-size: 1em; @include bold; border-radius: 0; margin: 0 !important; cursor: pointer; &:first-of-type { background-color: $link-color; } &:last-of-type { background-color: mix($link-color, $gray--light, 70%); } &:not(:last-of-type) { margin-right: #{$lh}em; } } } }
Todo
- add template-parser to add data-attributes