Skip to content

Repository files navigation

amWeb Consent

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.

Why amWeb Consent?

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.

Compatibility

  • 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

Package Structure

assets/components/amwebconsent/
core/components/amwebconsent/

Development and package build files are stored in:

_build/

Installed Elements

Snippets:

  • amWebConsent
  • amWebConsentLink

Chunks:

  • amwebconsent.config
  • amwebconsent.head
  • amwebconsent.footer
  • amwebconsent.service.matomo
  • amwebconsent.service.recaptcha
  • amwebconsent.service.openstreetmap
  • amwebconsent.service.youtube
  • amwebconsent.example.matomo-cookieless
  • amwebconsent.example.recaptcha-v3
  • amwebconsent.example.openstreetmap
  • amwebconsent.example.youtube

System settings:

  • amwebconsent.enabled
  • amwebconsent.privacy_policy_url
  • amwebconsent.default_language
  • amwebconsent.must_consent
  • amwebconsent.accept_all
  • amwebconsent.hide_decline_all
  • amwebconsent.notice_as_modal
  • amwebconsent.storage_method
  • amwebconsent.cookie_name
  • amwebconsent.cookie_expires_after_days
  • amwebconsent.group_by_purpose
  • amwebconsent.load_css
  • amwebconsent.load_js
  • amwebconsent.debug
  • amwebconsent.assets_url
  • amwebconsent.core_path

Basic Installation

  1. Download the .transport.zip file from the latest GitHub release.
  2. Upload/install it in MODX Package Manager.
  3. Clear MODX cache.
  4. Adjust the system settings, especially amwebconsent.privacy_policy_url and amwebconsent.default_language.
  5. Add the snippet or chunks to your template.

Template Integration

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`
]]

Snippet Properties

amWebConsent

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`
]]

amWebConsentLink

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).

Purposes/Categories

The default config defines:

  • necessary
  • analytics
  • external_media
  • spam_protection
  • marketing

Predefined Services

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.

Script Blocking Pattern

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-type contains the original type, e.g. text/javascript or text/html.
  • data-name must match the Klaro service name.
  • data-src replaces src for 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:

  1. Before a decision: no optional remote request is sent.
  2. Decline: the service remains blocked after reload.
  3. Accept: the service loads and operates normally.
  4. Revoke through amWebConsentLink: subsequent loads remain blocked and service cookies listed in the Klaro configuration are removed.

Matomo Cookieless Example

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.

Matomo With Cookies

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>

Google reCAPTCHA v3 Example

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.

OpenStreetMap Example

[[$amwebconsent.example.openstreetmap]]

Replace the data-src URL with your OpenStreetMap embed URL.

YouTube iframe Blocking

[[$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.

Local/External Google Fonts

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.

Manager Page

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.

Building a Transport Package

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.php

The 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.

Updating Klaro Assets

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.

Legal Notice

amWeb Consent provides technical integration and examples. It does not determine which services require consent in your jurisdiction and does not replace legal review.

About

MODX 3 consent management Extra powered by Klaro

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages