amWeb Consent (powered by Klaro) is a MODX 3 Extra that integrates the open source Klaro! Consent Manager with locally hosted assets.
Klaro source: https://github.com/kiprotect/klaro
The package ships Klaro JavaScript and CSS from the official compiled dist
folder. No CDN request and no Composer dependency are required at runtime.
The bundled Klaro version is v0.7.22.
Source repository: https://github.com/amWeb-DevTeam/amweb-consent
This Extra helps with technical consent handling. It does not replace legal advice.
amWeb Consent is designed for MODX projects that want consent management without handing configuration or consent data to a mandatory external CMP.
- Fully self-hosted: Klaro JavaScript and CSS are bundled locally; no CDN is required.
- No cloud account or site key: configuration remains in MODX system settings, chunks and snippet properties.
- No subscription or runtime vendor lock-in: the Extra is open source and continues to work independently of an external dashboard.
- Privacy by default: the global Klaro default and every bundled optional
service use
default: false. Optional services require an explicit choice. - MODX-native integration: use ordinary snippets and chunks in templates, content and reusable elements.
- Practical examples included: Matomo, reCAPTCHA v3, OpenStreetMap and YouTube examples demonstrate consent-controlled loading.
- Consent stays local: amWeb Consent itself does not upload consent records to a third-party CMP. Klaro stores the visitor's choice using the configured local browser storage method.
Unlike a hosted consent platform, amWeb Consent does not provide a cloud dashboard, automatic cookie scanner, geo-based rule engine or server-side consent audit log. It focuses on transparent, developer-controlled enforcement inside MODX.
- MODX 3 only
- Tested with MODX
3.2.3-pl - Tested with PHP
8.5 - PHP code uses MODX 3 namespaces and the MODX Composer autoloader
- No Composer dependency is required for this Extra itself at runtime
assets/components/amwebconsent/
core/components/amwebconsent/
Development and package build files are stored in:
_build/
Snippets:
amWebConsentamWebConsentLink
Chunks:
amwebconsent.configamwebconsent.headamwebconsent.footeramwebconsent.service.matomoamwebconsent.service.recaptchaamwebconsent.service.openstreetmapamwebconsent.service.youtubeamwebconsent.example.matomo-cookielessamwebconsent.example.recaptcha-v3amwebconsent.example.openstreetmapamwebconsent.example.youtube
System settings:
amwebconsent.enabledamwebconsent.privacy_policy_urlamwebconsent.default_languageamwebconsent.must_consentamwebconsent.accept_allamwebconsent.hide_decline_allamwebconsent.notice_as_modalamwebconsent.storage_methodamwebconsent.cookie_nameamwebconsent.cookie_expires_after_daysamwebconsent.group_by_purposeamwebconsent.load_cssamwebconsent.load_jsamwebconsent.debugamwebconsent.assets_urlamwebconsent.core_path
- Download the
.transport.zipfile from the latest GitHub release. - Upload/install it in MODX Package Manager.
- Clear MODX cache.
- Adjust the system settings, especially
amwebconsent.privacy_policy_urlandamwebconsent.default_language. - Add the snippet or chunks to your template.
Single call, suitable for the document head or before </body>:
[[!amWebConsent]]Split head/footer integration:
<!-- in <head> -->
[[$amwebconsent.head]]
<!-- before </body> -->
[[$amwebconsent.footer]]Manual consent settings link:
[[!amWebConsentLink?
&text=`Cookie-Einstellungen ändern`
&class=`btn btn-link p-0`
]]The link reopens the full settings modal. Visitors can review, grant or revoke individual service permissions at any time. Add it to a persistent location such as the footer or privacy policy.
Button variant:
[[!amWebConsentLink?
&tag=`button`
&text=`Change cookie settings`
&class=`btn btn-primary`
]]| Property | Default | Description |
|---|---|---|
configChunk |
amwebconsent.config |
Chunk that returns window.klaroConfig. |
loadCss |
system setting | Load local Klaro CSS. |
loadJs |
system setting | Load local Klaro JS. |
autoLoad |
1 |
If 0, writes noAutoLoad: true to the config. |
debug |
system setting | Adds a small HTML comment and logs empty config output. |
Example:
[[!amWebConsent?
&configChunk=`my.klaro.config`
&loadCss=`1`
&loadJs=`1`
&autoLoad=`1`
]]| Property | Default | Description |
|---|---|---|
text |
lexicon text | Visible link/button text. |
class |
amwebconsent-link |
CSS class. |
tag |
a |
a or button. |
forceModal |
1 |
Calls klaro.show(undefined, true). |
The default config defines:
necessaryanalyticsexternal_mediaspam_protectionmarketing
The default config includes examples for:
- Matomo cookieless
- Matomo with cookies
- Google reCAPTCHA v3
- OpenStreetMap Embed
- YouTube Embed
- Vimeo Embed
- Google Fonts
- Facebook Pixel
- Google Analytics
Remove services you do not use from amwebconsent.config.
Klaro executes blocked scripts/elements only after consent when these attributes are used:
<script
type="text/plain"
data-type="text/javascript"
data-name="service-name"
data-src="https://example.com/script.js">
</script>Rules:
type="text/plain"prevents direct browser execution.data-typecontains the original type, e.g.text/javascriptortext/html.data-namemust match the Klaro servicename.data-srcreplacessrcfor external scripts, iframes and images.
External script:
<script
type="text/plain"
data-type="text/javascript"
data-name="analytics-service"
data-src="https://example.com/analytics.js">
</script>Inline script:
<script type="text/plain" data-type="text/javascript" data-name="analytics-service">
window.exampleAnalytics.start();
</script>Blocked iframe:
<iframe
data-name="external-media-service"
data-src="https://example.com/embed/123"
title="External media"
loading="lazy">
</iframe>Do not leave a real src on consent-controlled scripts, iframes or images: the
browser may request it before Klaro can enforce the visitor's choice. The
data-name value must exactly match one service name in
amwebconsent.config.
After integration, test at least these states in a fresh browser profile:
- Before a decision: no optional remote request is sent.
- Decline: the service remains blocked after reload.
- Accept: the service loads and operates normally.
- Revoke through
amWebConsentLink: subsequent loads remain blocked and service cookies listed in the Klaro configuration are removed.
Enable the matomo-cookieless service in amwebconsent.config and add:
[[$amwebconsent.example.matomo-cookieless]]Inside that chunk, replace:
var u = 'https://matomo.example.com/';
_paq.push(['setSiteId', '1']);with your own Matomo URL and site ID.
Use the service:
name: 'matomo'and remove disableCookies from your Matomo tracking script. Use:
<script type="text/plain" data-type="text/javascript" data-name="matomo">
// Matomo tracking code with cookies enabled.
</script>Add the example chunk near the form that needs reCAPTCHA:
[[$amwebconsent.example.recaptcha-v3]]The chunk uses the service name:
google-recaptcha
Make sure your backend validation handles the case where consent is missing.
[[$amwebconsent.example.openstreetmap]]Replace the data-src URL with your OpenStreetMap embed URL.
[[$amwebconsent.example.youtube]]Replace VIDEO_ID with the actual YouTube video ID. The example uses youtube-nocookie.com, but the iframe is still blocked until consent is given.
Best option: host fonts locally and do not add a consent service.
If fonts are loaded externally from Google, keep the google-fonts service in amwebconsent.config and block the stylesheet:
<link
rel="stylesheet"
type="text/plain"
data-type="text/css"
data-name="google-fonts"
data-href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap">Depending on the browser/Klaro version, stylesheets may require testing in your concrete frontend. Prefer local font hosting for production.
This first implementation uses system settings and chunks for configuration. A future Custom Manager Page can be added under:
core/components/amwebconsent/controllers/mgr/
assets/components/amwebconsent/mgr/
The controller and manager asset placeholders already exist so the structure can grow without moving files.
From the MODX project root:
cp _build/build.config.sample.php _build/build.config.php
MODX_BASE_PATH=/absolute/path/to/modx/ php _build/build.transport.phpThe package will be written to MODX core/packages/, for example:
core/packages/amwebconsent-1.0.0-rc1.transport.zip
Install it through the MODX Package Manager.
Replace these files with compiled files from the official Klaro dist folder:
assets/components/amwebconsent/js/lib/klaro/klaro-no-css.js
assets/components/amwebconsent/js/lib/klaro/klaro.js
assets/components/amwebconsent/css/klaro.min.css
Do not use uncompiled files from Klaro src/ directly in the browser.
Update THIRD_PARTY_NOTICES.md and its checksums whenever these assets change.
amWeb Consent provides technical integration and examples. It does not determine which services require consent in your jurisdiction and does not replace legal review.