Most "Magento 2 cookie consent" articles stop at installing a banner and toggling Cookie Restriction Mode. That’s fine for a single-locale store with one tracking pixel. It falls apart the moment you have multiple store views, a strict Content Security Policy, marketing scripts that must be gated on consent, and an auditor asking where your consent history lives.
DataReporter WebCare is an Austrian/EU consent management platform (CMP) with a first-party Magento 2 module (datareporter/module-webcare). The DataReporter WebCare Magento 2 integration generates and hosts the banner, imprint, and privacy-notice texts on WebCare’s side; the module’s job is to inject them into the storefront the Magento way — layout XML, blocks, widgets, store-scoped config.
The lead: the integration points that actually bite
This DataReporter WebCare Magento 2 guide skips the install checklist and goes straight to the configuration and code that trips up every multi-store, CSP-hardened Magento project: the layout containers nobody documents, the Loader Mode that makes the banner CSP-compatible, the consent API’s per-category state (and why drAllow alone is the wrong thing to key off), and the store-view redirect hook that only exists in the Magento plugin. It also makes the honest case for what it would cost to build the same thing yourself.
The baseline: install, config, and the multi-store-view trap
DataReporter WebCare Magento 2 is a hosted CMP. The module is a thin embedder:
- Cookie banner —
banner.css+banner.js(or the v5 Loader) served from WebCare’s EU CDN, initialised on every page. - Imprint and Privacy Notice — auto-generated legal texts injected into a target element.
- All three are toggled independently in store config and styled entirely in the WebCare GUI, not in your theme.
The consent state lives in two first-party cookies (cookieconsent_status, cookieconsent_mode), optionally in localStorage, and — on the PRO tier — in a server-side consent history keyed by a per-visitor _webcare_consentid. That history is the artefact you hand an auditor; it’s not something you build yourself.
Install
composer require datareporter/module-webcare
bin/magento module:enable DataReporter_Core
bin/magento module:enable DataReporter_WebCare
bin/magento setup:upgrade
bin/magento setup:static-content:deploy
DataReporter WebCare Magento 2 pulls in datareporter/module-core. Magento 101. | 102. | 103.* and PHP ≥ 7.0.13 are supported — runs on everything from 2.2 through current 2.4.x.
Demo credentials
You don’t need a paid account to test the integration. Under Stores → Configuration → DataReporter → Privacy / Settings:
- Client-Id:
33f002cc-2586-42b6-987d-548b2953c7b8 - Organisation-Id:
R5spy6ZYDqA
Config options worth understanding
Everything lives under Stores → Configuration → DataReporter → Settings → WebCare:
| Setting | Why it matters |
|---|---|
| Webcache URL | Defaults to https://webcache-eu.datareporter.eu/c/. Leave it unless you self-host the suite. |
| Add store language to external resource | On by default. Appends a 2-letter language code (?lang=de) so each store view gets the right banner language. See below. |
| Enable Imprint / Privacy Notice / Cookie Banner | Three independent toggles. |
| Enable Custom Cookie Banner Options | Off by default. Enable only if you need the allow/deny layout containers — and note these are suppressed in Loader Mode. |
| Enable Cookie Banner custom redirect after consent | The Magento-specific store-switch hook. Off by default. |
| Loader Mode (CSP/SRI compliant) | The modern injection path. Suppresses the custom-options block. |
The multi-store-view language trap
The setting "Add store language to external resource" is on by default. Two details in the implementation catch people out.
First: the format. AbstractWebCareBlock::getCurrentLocale() calls explode('_', $locale)[0] — only the first segment of the Magento locale is sent. de_DE becomes de, en_US becomes en, fr_FR becomes fr. It’s appended as a query parameter ?lang=, not as a path segment:
<!-- German store view (de_DE locale): 2-letter code, query param -->
<script src="https://webcache-eu.datareporter.eu/c/{client-id}/{org-id}/banner.js?lang=de"></script>
<!-- English store view (en_US locale) -->
<script src="https://webcache-eu.datareporter.eu/c/{client-id}/{org-id}/banner.js?lang=en"></script>
Without the setting enabled, all store views get the same URL and fall back to WebCare’s account default language.
Second: the WebCare side. Your WebCare account must have a banner configuration for each 2-letter language code that Magento sends. If you’ve configured German in WebCare as de_DE but the module sends de, they won’t match and you’ll silently get the default. Open the WebCare portal and verify the language codes align with what Magento sends.
A quick sanity check: open each store view in a private window, inspect the Network tab, and confirm the banner.js (or cmp-load.js in Loader Mode) request carries the expected ?lang= parameter.
Imprint and Privacy Notice
Two ways to place each. As a widget (Content → Pages/Blocks → Insert Widget): WebCare - Imprint and WebCare - Privacy Notice. Or directly as a block in layout:
<?= $block->getLayout()
->createBlock(\DataReporter\WebCare\Block\ImprintBlock::class)
->toHtml() ?>
In Loader Mode these blocks render only an empty target container (<div id="dr-imprint-div"></div> / <div id="dr-privacynotice-div"></div>) and the Loader injects the content client-side.
Working example: from layout containers to full consent gating
The layout containers nobody documents
The banner is injected via the module’s view/frontend/layout/default.xml. The interesting part is the set of empty reference containers DataReporter WebCare Magento 2 exposes so you can hook your own behaviour off consent transitions, without forking the module:
datareporter.webcare.cookiebanner.allow-handling— fires when consent moves to allowdatareporter.webcare.cookiebanner.deny-handling— fires when consent is denied / withdrawndatareporter.webcare.cookiebanner.redirect-after-consent— the store-switch redirect hookdatareporter.webcare.cookiebanner.storeswitch-redirect— the default redirect block (remove to replace it)
You contribute JS into these by adding a block to the container from your own module’s or theme’s default.xml. The "Enable Custom Cookie Banner Options" toggle must be on.
<!-- view/frontend/layout/default.xml in your own module -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="datareporter.webcare.cookiebanner.allow-handling">
<block name="my-cookiebanner-allow"
class="Magento\Framework\View\Element\Template"
template="MyVendor_CookieConsent::cookiebanner/allow.phtml"/>
</referenceContainer>
<referenceContainer name="datareporter.webcare.cookiebanner.deny-handling">
<block name="my-cookiebanner-deny"
class="Magento\Framework\View\Element\Template"
template="MyVendor_CookieConsent::cookiebanner/deny.phtml"/>
</referenceContainer>
</body>
</page>
CSP note. The init script that wraps the onStatusChange callback is emitted via Magento’s SecureHtmlRenderer::renderTag. It gets a CSP nonce automatically when Magento’s CSP module is active — no extra work needed from your side.
Critical: layout containers and Loader Mode are mutually exclusive. CookieBannerOptionsBlock::toHtml() returns an empty string when Loader Mode is active, so the init block and all its child containers are never rendered. If you need Loader Mode’s stable SRI hash and custom consent callbacks, wire them via the WebCare JavaScript API (dr_onEnableCookies) from a separate inline script.
The developer consent API
Once DataReporter WebCare Magento 2 is on the page, window.cookieconsent.currentConsentStatus() gives you per-category state synchronously:
const status = window.cookieconsent.currentConsentStatus();
/*
{
tech: true, // technically required — always true
preferences: true, // preferences / performance cookies
statistic: true, // analytics (Matomo, GA, ...)
marketing: false, // ad tracking / profiling
unknown: false, // unclassified cookies
drAllow: false, // true when cookieconsent_status === "allow"
drDeny: false // true when cookieconsent_status === "deny"
}
*/
A user who accepted only statistics is drDeny: true and statistic: true. If your code keys off drAllow alone you’ll wrongly suppress analytics for everyone who customised their choice.
Register the change callback before initialise() to fire on every consent change, including withdrawals:
dr_cookiebanner_options.dr_onEnableCookies = function (enable) {
if (enable) {
// consent granted — boot tag manager / pixels here
} else {
// consent denied or withdrawn
}
};
window.cookieconsent.initialise(dr_cookiebanner_options);
The GTM path. WebCare pushes named events to the dataLayer on both page load and on change: cookie_consent_statistic_enabled / cookie_consent_statistic_disabled, cookie_consent_marketing_enabled / cookie_consent_marketing_disabled. If your GTM container uses a renamed dataLayer, tell WebCare its name:
dr_cookiebanner_options.googleDataLayerName = "dl";
window.cookieconsent.initialise(dr_cookiebanner_options);
dr_cookiebanner_options.gtmInit();
If you’re centralising GA4, Meta, and other destinations from a single dataLayer source, the pattern in Ecommerce dataLayer: One Source, Many Destinations composes cleanly with WebCare’s consent gates.
Loader Mode: the CSP/SRI-safe injection
The classic integration injects banner.js and banner.css directly. Those files are regenerated daily, so you can’t pin a Subresource Integrity hash — it changes every night and the browser refuses to load the banner. A strict CSP that disallows unsafe-inline also chokes on the inline initialise() call.
DataReporter WebCare Magento 2’s Loader Mode solves both. It loads a single stable Loader script (cmp-load.js) that fetches and injects everything else in a CSP-compatible way. The Loader is versioned and immutable — when DataReporter ships a new Loader version they leave old versions untouched — so its SRI hash is stable and pinnable.
Enable it under Settings → WebCare → Loader Mode. The rendered tag:
<script src="https://webcachex-eu.datareporter.eu/loader/v5/cmp-load.js?url=<integration-key>"
defer
integrity="sha384-Yh6XuJwOlmI2r/DqXWGw4mGoFjpAsmouYCyW6xJV4te0MF+9PzMBsOXsDwvqSYUu"
crossorigin="anonymous"></script>
The module pre-fills the v5 SRI hash in config.xml. Verify it at deploy time — if DataReporter ships a v6 Loader, both the URL version segment and the hash change together. To compute the current hash from the live script:
curl -s https://webcachex-eu.datareporter.eu/loader/v5/cmp-load.js \
| openssl dgst -sha384 -binary | openssl base64 -A
Prefix the output with sha384- and compare to the configured value.
CSP: what the module handles. The module ships its own etc/csp_whitelist.xml that covers *.datareporter.eu across script-src, style-src, connect-src, and font-src. For standard Magento CSP you don’t need a custom whitelist. The exception is Hyvä (and any setup that manages CSP outside Magento’s whitelist mechanism, e.g. via Nginx headers directly) — add the WebCare hosts to those configurations separately. The suppressed inline init block in Loader Mode removes the need for an unsafe-inline exception, which is exactly why Loader Mode matters on Hyvä.
Redirect-on-consent across store views
This hook doesn’t exist in the WordPress or TYPO3 WebCare plugins — it’s specific to DataReporter WebCare Magento 2. When the banner offers a country/language picker and the user picks a different locale, you want to land them on the correct store view using Magento’s internal redirect (so cookies and store context transfer correctly). Enable Settings → WebCare → Enable Cookie Banner custom redirect after consent.
To replace the default redirect logic:
<referenceContainer name="datareporter.webcare.cookiebanner.redirect-after-consent">
<block name="my-cookiebanner-redirect"
class="Magento\Framework\View\Element\Template"
template="MyVendor_CookieConsent::cookiebanner/redirect.phtml"/>
</referenceContainer>
<referenceBlock name="datareporter.webcare.cookiebanner.storeswitch-redirect" remove="true"/>
The default block (store_switcher_redirect.phtml) decodes the store-switcher URL, appends the consent status as a URL parameter, and calls window.location.replace(). That store-switcher URL is the home page of the target store view — which is fine when the user landed on the homepage, but wrong when they followed a deeplink directly to a product or category page.
The deeplink problem. If a visitor navigates directly to /de/product-name.html, your banner appears, they pick the German store, and the default redirect drops them on the German store’s homepage instead of the equivalent product page. The default block has no knowledge of window.location.href; it only knows the store-switcher target URL.
To preserve the current page on redirect, replace the default block with one that captures the visitor’s actual URL and rewrites the path for the target store:
// In your custom redirect.phtml (rendered as inline JS via SecureHtmlRenderer)
window.dr_redirect_to_store = function (storeUrl) {
var currentPath = window.location.pathname + window.location.search;
// storeUrl is the base URL of the target store view (e.g. https://example.com/de/)
// Strip the current store's base path and append to the target base
var targetBase = storeUrl.replace(/\/$/, '');
window.location.replace(targetBase + currentPath);
};
Two caveats to handle in the server-side block: (1) product URL keys can differ per store view (red-shoes.html in English vs rote-schuhe.html in German) — a path-swap will land on a 404 unless you resolve the canonical URL per store view; (2) category paths are usually store-view-specific too. The safest fallback when path resolution is unavailable: redirect to the target store’s home page and accept the degraded experience only for deeplink visitors, not for the common case of navigating from the homepage.
Gate a marketing script on consent: a full recipe
Load a marketing pixel only after marketing consent, honour a statistics-only choice without blocking analytics, and re-evaluate when the user changes their mind:
(function () {
function applyConsent() {
var c = window.cookieconsent.currentConsentStatus();
// Marketing pixel — only with explicit marketing consent
if (c.marketing && !window.__myPixelLoaded) {
var s = document.createElement('script');
s.src = 'https://example-pixel.test/p.js';
s.async = true;
document.head.appendChild(s);
window.__myPixelLoaded = true;
}
// Analytics opt-out toggle for an already-present lib (e.g. Matomo)
if (window._paq) {
c.statistic ? window._paq.push(['forgetUserOptOut'])
: window._paq.push(['optUserOut']);
}
}
applyConsent();
if (window.dr_cookiebanner_options) {
window.dr_cookiebanner_options.dr_onEnableCookies = applyConsent;
}
})();
Read currentConsentStatus() per-category rather than branching on the coarse allow/deny. A deny status with ["statistic"] in cookieconsent_mode is a partial accept, and treating it as a blanket reject ignores a consent the user actually gave.
> This in-code approach works, but it’s not the preferred way. DataReporter WebCare has a built-in tag management feature where you add and configure custom tags directly inside the WebCare portal — specifying which consent categories gate each tag — without writing any code. The layout container approach is useful when you need Magento-side logic (toggling a Magento-managed analytics lib, firing a server-side event). For loading third-party pixels and marketing scripts, the WebCare tag manager is simpler and keeps configuration in one place.
The tradeoff: hosted CMP vs. a module you write yourself
There’s a real argument for not depending on a hosted CMP: full control of markup and styling, no recurring fee, no third-party CDN in your critical render path, and consent data that never leaves your database. The trade is that you take on every problem DataReporter WebCare Magento 2 quietly solves for you — and on Magento specifically, a few of those problems are nastier than they look.
- Cookie blocking, not just notifying. Magento’s built-in Cookie Restriction Mode only sets a flag; it blocks nothing. Third-party scripts must not execute until consent exists — retrofitting this onto a store full of vendor modules is the bulk of the effort.
- Full Page Cache / Varnish. Per-visitor consent state cannot be baked into cached HTML. It must be resolved client-side from a cookie or delivered via Magento’s private-content channel (
customer-data/sections.xml). Get this wrong and the banner never shows on cached pages. - The consent record is a compliance artefact, not a log line. You need a timestamped record of what was consented to, which policy version, scope (store view), and a stable visitor identifier — plus a re-prompt mechanism on policy changes.
- Google Consent Mode v2 ordering.
gtag('consent', 'default', {...denied})must fire before any Google tag, thenupdateon consent. The storage mapping is easy to get subtly wrong. - Theme duplication. Luma and Hyvä need different frontend implementations of the same logic.
- Cookie inventory and privacy notice maintenance. A legally correct privacy notice must list every cookie the site sets — name, purpose, duration, provider. That list changes with every new plugin, script tag, or vendor update. WebCare’s web crawler auto-detects cookies across your site and keeps the privacy notice in sync automatically; a self-built solution makes this a manual, recurring audit task.
- Legal correctness is a moving target. Reject must be as easy as accept, no pre-ticked boxes, a working withdrawal path, and divergent rules across GDPR, US state laws, and IAB TCF.
If you want to go down this road, there are open-source starting points worth studying. For Hyvä + Google Consent Mode v2, elgentos/magento2-consentmode-v2 covers the Hyvä-specific frontend layer and GCM v2 integration. For a broader Magento 2 GDPR framework (MIT-licensed), opengento/module-gdpr handles the consent record, cookie disclosure, and customer data erasure — a useful starting point to understand what the compliance scaffolding actually looks like.
Two structural points worth making explicit. WebCare is tech-stack agnostic; a self-built Magento module is not. A single WebCare account covers all your properties — Magento store, WordPress blog, Shopware B2B site, marketing microsite — each registered as a separate website ID. All of them share the same imprint and privacy-notice configuration; each website ID gets its own banner language and consent-category mapping but draws from the same legal texts. Any property that isn’t running a supported CMS can include WebCare with a plain <script> embed — no plugin, no framework required. A module you write inside Magento solves the problem for Magento only. That portability is often the deciding factor.
> This article covers the technical integration, not legal guidance — I’m not a lawyer, and nothing here is legal advice. Before settling on an approach, confirm with a privacy professional what your specific store actually needs.
Verification: debug tools and edge cases
Debug logging — DataReporter WebCare Magento 2 ships verbose console output for diagnosing why the banner won’t show or a callback won’t fire:
dr_cookiebanner_options.debugLogActive = true;
// or per-request without a code change:
// https://yourstore.test/?_webcare_debug=true
Deferred / manual banner display — useful when you need the page painted first, or want to trigger from a "Cookie settings" link:
<!-- wait 3 seconds -->
<script src="https://webcachex-eu.datareporter.eu/loader/v5/cmp-load.js?url=<key>&wait=3000" defer></script>
<!-- wait for an explicit signal -->
<script src="https://webcachex-eu.datareporter.eu/loader/v5/cmp-load.js?url=<key>&wait=manual" defer></script>
<a href="javascript:window.drShowWebCareBanner()">Cookie settings</a>
Dynamic privacy-policy URL — point the banner’s privacy link at a store-specific CMS page at runtime:
dr_cookiebanner_options.privacyLinkUrl = "https://yourstore.test/privacy-policy";
window.cookieconsent.initialise(dr_cookiebanner_options);
Ad-blocker reality check — WebCare is the single source of truth for all managed scripts: it controls whether GTM, pixels, and analytics tags load, not the other way around. If an ad blocker targets the WebCare CDN and blocks the banner script itself, consent is never captured and all managed tags won’t fire. This is another reason to use the module’s direct/Loader path: it’s less likely to be pattern-matched by a blocklist than a consent script injected through a third-party tag manager container.
Where DataReporter WebCare Magento 2 fits in the GDPR landscape
- DataReporter WebCare Magento 2 — hosted EU CMP, consent history on the PRO tier, strong CSP/SRI story via Loader Mode, store-view-aware. As the legal requirements shift, banner logic and consent handling get updated on the vendor side. Recurring cost; banner styling lives in WebCare’s GUI.
- Hyvä default cookie bar / elgentos Consent Mode v2 — fully in-theme, free, Google Consent Mode v2 wired in. You own the legal texts, the consent record, and tracking every legal change yourself.
- Magento’s built-in Cookie Restriction Mode — a notice, not real category consent. Fine only for the simplest, lowest-risk stores.
- A self-written Magento-native module — maximum control, no recurring cost, data stays in your DB. You inherit every challenge listed in the tradeoff section above.
For a multi-store-view, multi-language Magento install under a strict CSP — exactly where consent management is hardest — DataReporter WebCare Magento 2’s Loader Mode and store-view redirect earn it a slot in the comparison. Reach for it when "defensible, EU-hosted consent with an audit trail, across more than one tech stack" outranks "we want to style the banner in our own CSS."
Leave a Reply