One Click Accessibility: Barrierefreiheit-Widget für WordPress

Info: Neue Version und Re-Branding

One Click Accessibility liegt seit Februar 2025 in der neuen Version 3 vor und hat durch das Update außerdem ein vollständiges Re-Branding erhalten. Das Plugin, welches ab sofort auf den Namen Ally – Web Accessibility & Usability hört, wird von Elementor (der Firma hinter dem Plugin – u.a. bekannt für den gleichnamigen Page Builder) als erster Schritt für eine Reihe von Weiterentwicklungen in Richtung Barrierefreiheit bezeichnet und scheint sich tiefer in das Ökosystem von Elementor zu integrieren. Unter anderem wird ab sofort auch ein Benutzerkonto bei Elementor für den Einsatz des Plugins nötig. Inwiefern das Plugin in Zukunft monetarisiert werden soll, ist aktuell noch ungewiss. Der letzte Stand der Version 2 von One Click Accessibility (Version 2.1.0) kann nach wie vor über das WordPress Plugin-Verzeichnis heruntergeladen werden.


Ausschnitt der Website für das WordPress Plugins One Click Accessibility
Ausschnitt der Website für das WordPress Plugin One Click Accessibility mit dem Accessibility Widget auf der rechten Seite

Was ist ein Accessibility Widget?

Mithilfe eines Accessibility Widgets können Websites in Ihrem Aussehen angepasst werden. So bringen diese Widgets eine ganze Reihe von Funktionen, mit denen der Websitebesucher designtechnische Aspekte einer Website modifizieren und an seine besonderen Bedürfnisse anpassen kann. Mit nur wenigen Klicks lassen sich so beispielsweise Farbkontraste anpassen, Schriftgrößen verändern oder auch Links hervorheben.

Accessibility Widgets sind inzwischen auf immer mehr Websites anzutreffen. Für WordPress gibt es ebenfalls einige Lösungen, mit denen sich die Darstellung des Internetauftritts hinsichtlich Design und Funktionalität mehr zu einer barrierefreien Darstellung bewegen lässt. One Click Accessibility ist eines der bekanntesten Widgets dieser Art. Das Plugin ist völlig kostenlos verfügbar. Es kann auf der Website von One Click Accessibility ausprobiert sowie im WordPress Plugin-Verzeichnis heruntergeladen werden.

Macht ein Accessibility Widget eine Website grundsätzlich barrierefrei?

Hier muss man ganz klar sagen: Nein! Denn auch die besten Widgets können nichts ausrichten, wenn grundlegende Strukturen der Website nicht von vornherein mit Barrierefreiheit im Blick entwickelt und implementiert wurden. Vielmehr sollten Accessibility Widgets nur als Zusatzfunktion verstanden werden.

Generell muss man allerdings auch sagen, dass viele eingeschränkte Nutzer die inzwischen immer häufiger auftretenden Accessibility Widgets der verschiedenen Anbieter teilweise sogar als störend erachten. Oft bringen sie einfach keinen Mehrwert, da eingeschränkte Nutzer meist bereits mit speziellen Geräten durch das Web navigieren und deshalb auf kein Widget angewiesen sind. Genauso wenig bringt einem blinden Nutzer mit Screenreader eine Funktion zur Schriftvergrößerung oder zur Anpassung des Farbschemas.

Nützlich können die Widgets dagegen für technisch weniger versierte Nutzer sein, die sich über eine schnelle Funktion zur Schriftvergrößerung freuen. Auch Menschen mit weniger drastischen Einschränkungen, wie einer Farbsehschwäche, können von einem Barrierefreiheit-Widget profitieren.

Man sollte sich im Vorfeld jedenfalls gut überlegen, wer die tatsächliche Zielgruppe der eigenen Website sein soll. Auf diese Weise kann man in der Entwicklungsphase abwägen, ob ein Accessibility Widget tatsächlich notwendig ist und Sinn macht, oder ob man stattdessen auf geltende Standards setzt und die Website an sich so barrierearm wie möglich plant und gestaltet. Gerade die Themen Tastatursteuerung, Farbkontraste und Links sind hier immer wieder eine Fehlerquelle und benötigen bei korrekter Umsetzung kein separates Widget zur Hilfestellung.

Die Funktionen von One Click Accessibility

Das Plugin bietet einerseits globale Einstellungen für die Website und andererseits verschiedene Funktionen, die über das Widget (auch Toolbar genannt) angeboten werden.

Globale Einstellungen:

  • Zum-Inhalt-Springen
  • Outline-Fokus zu fokussierbaren Elementen hinzufügen
  • Target-Attribut von Links entfernen
  • ARIA-Rollen zu Links hinzufügen

Widget-Funktionen:

  • Schriftgröße vergrößern und verkleinern
  • Graustufen-Farbschema
  • Negativer Kontrast
  • Hoher Kontrast
  • Heller Hintergrund
  • Links unterstreichen
  • Lesbare Schrift
  • Frei konfigurierbare Links zur Sitemap, sowie einer Feedback- oder Hilfe-Seite

Die Funktionen können in den Einstellungen jeweils aktiviert oder deaktiviert werden. Man muss dem Besucher also nicht zwingend alle Widget-Funktionen anbieten. Das Widget selbst lässt sich in seinem Aussehen ebenfalls genau anpassen und so sehr gut auf die eigene Website zuschneiden.

One Click Accessibility – Modifikationen und Fehlerbehebungen

Wie bereits erwähnt, ist ein Widget keine Garantie für eine barrierefreie Website. In manchen Fällen kann ein solches Widget sogar hinderlich sein. Auch One Click Accessibility selbst hat einige Eigenheiten, die man, je nach Projekt und Anforderung, modifizieren könnte. Mit ein paar programmiertechnischen Kenntnissen lässt sich das Widget in Aussehen und Funktion noch weiter anpassen, als in den Optionen möglich.

Schriftdicke anpassen

Die Schriftdicke des Widgets kann mit dem nachfolgenden Code modifiziert werden. Dies kann, je nach initialen CSS-Stilen, auch ein Flackern des Textes verhindern.

.pojo-a11y-toolbar-inner {
    font-weight: 400;
}

Offset der Unterstreichung für verschiedene Textgrößen anpassen

Hierdurch wird beispielhaft der Offset, also der Abstand der Unterstreichung zum Text der Widget-Menüpunkte für verschiedene Textvergrößerungsstufen angepasst.

body.pojo-a11y-resize-font-110 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a,
body.pojo-a11y-resize-font-120 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a,
body.pojo-a11y-resize-font-130 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a {
    text-underline-offset: 0.55em;
}

body.pojo-a11y-resize-font-140 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a,
body.pojo-a11y-resize-font-150 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a,
body.pojo-a11y-resize-font-160 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a,
body.pojo-a11y-resize-font-170 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a,
body.pojo-a11y-resize-font-180 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a,
body.pojo-a11y-resize-font-190 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a,
body.pojo-a11y-resize-font-200 #pojo-a11y-toolbar .pojo-a11y-toolbar-overlay ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a {
    text-underline-offset: 0.6em;
}

Widget-Größe anpassen

Prinzipiell kann die Widget-Größe auch in den Einstellungen bzw. im Customizer angepasst werden. Wer dies über Code erreichen möchte, kann den nachfolgenden Code-Schnippsel verwenden. In diesem Beispiel wird das Widget auf der rechten Seite der Website verwendet.

#pojo-a11y-toolbar .pojo-a11y-toolbar-overlay {
    width: 240px;
}

#pojo-a11y-toolbar.pojo-a11y-toolbar-right .pojo-a11y-toolbar-toggle {
    right: 240px;
}

#pojo-a11y-toolbar.pojo-a11y-toolbar-right {
    right: -240px;
}

Widget-Button mit Fokus-Stil ausstatten

Wer den Button des Widgets selbst mit einem sichtbaren Fokus-Stil aussstatten will, kann dies mit dem nächsten Code erreichen. Statt :focus wird hier :focus-visible verwendet, um den Stil nur bei Fokussierung mit der Tastatur zu aktivieren.

#pojo-a11y-toolbar .pojo-a11y-toolbar-link.pojo-a11y-toolbar-toggle-link:focus-visible {
    outline: 2px solid #333;
    outline-offset: 2px;
    outline-style: dashed;
}

So wie den Button des Widgets selbst lassen sich auch die Links der Widget-Funktionen mit einem Fokus-Stil ausstatten. Auch hier greifen wir auf :focus-visible zurück, um den Fokus-Status lediglich bei Tastaturwahl anzuzeigen. Dazu genügt dieser Code:

#pojo-a11y-toolbar ul.pojo-a11y-toolbar-items li.pojo-a11y-toolbar-item a.pojo-a11y-toolbar-link:focus-visible {
    outline-color: #333;
    outline-offset: -4px;
    outline-style: dashed;
    outline-width: 2px;
}

Das Widget ist in seinem Aufbau in manchen Teilen etwas eigenwillig. Die Links des Widgets bestehen sowohl aus a-Tags als auch aus span-Tags. Durch die aktivierte Option „Links unterstreichen“ kann es beim Widget selbst teilweise zu einer doppelten Unterstreichung der Links kommen, was mitunter eher merkwürdig aussieht. Um Abhilfe zu schaffen und die Unterstreichung der span-Tags innerhalb der Links generell zu unterbinden, eignet sich folgender Code:

body.pojo-a11y-links-underline .pojo-a11y-toolbar-link span {
    text-decoration: none !important;
}

Funktion Heller Hintergrund: Hintergrundfarbe vom Gutenberg Abstandshalter entfernen

Dieser Code sorgt dafür, dass beim Aktivieren des hellen Hintergrundes der Abstandshalter des Gutenberg Editors nicht mit einer weißen Hintergrundfarbe ausgestattet wird, was ihn unter bestimmten Voraussetzungen, je nach angrenzenden Elementen, sichtbar machen könnte:

body.pojo-a11y-light-background *:not(#pojo-a11y-toolbar):not(.pojo-a11y-toolbar-link) .wp-block-spacer {
    background: none !important;
}

Graustufen-Fehler beheben (fixierte Position des Widgets)

Die Version 2 von One Click Accessibility verfügt leider über einen Fehler, der das Widget in einigen Browsern bei Aktivierung der Graustufen wieder an den oberen Rand der Website positioniert und nicht mehr an der Seite mitscrollen lässt. Leider scheint dieser Bug schon längere Zeit vorzuliegen. Da das Plugin schon seit vielen Monaten nicht mehr aktualisiert wurde, ist es fraglich, ob es hier von offzieller Seite Abhilfe geben wird.

Der Hintergrund dieses Bugs ist, dass einige Browser (darunter Webkit-Browser wie Chrome) einen umschließenden Container für den Graustufen-Effekt generieren. Als Standard gilt, dass der Graustufen-Effekt auf das html-Tag der Website angewendet werden sollte. Stattdessen wird vom Plugin aber der body-Tag der Website verwendet. Dies kann bei vielen Themes zu einer defekten Layout-Struktur führen.

Durch eine kleine Modifikation können wir allerdings dafür sorgen, dass das Plugin nicht nur den body-Tag, sondern auch den html-Tag für die Anwendung der verschiedenen Farbschemata verwendet. Mit zusätzlichem CSS können wir im Anschluss den Graustufen-Effekt vom body-Tag entfernen und auf den html-Tag anwenden.

Schritt 1: Neues Plugin-Skript erstellen (JavaScript)

Im Plugin-Verzeichnis muss eine neue JavaScript-Datei erstellt werden. Der Name ist dabei prinzipiell unwichtig, wir benutzen im Beispiel app.custom.js.

Vollständiger Pfad zur neuen Datei: wp-content/plugins/pojo-accessibility/assets/js/app.custom.js

In der neuen Datei muss nun der folgende, recht lange Skript-Code eingefügt werden. Der Code beruht auf dem ursprünglichen Skript von One Click Accessibility. Die geänderten Stellen wurden im Code kenntlich gemacht.

/*! pojo-accessibility - v2.1.0 - 18-12-2022 */

/** 
 * This is a custom and modified file (based on the unminified version of /assets/js/app.min.js) to fix the grayscale container bug.
 * 
 * The grayscale bug occurs because some browsers (e.g. Webkit) create a surrounding container when using the grayscale filter
 * and therefore, depending on the theme's structure, may break the layout. It is best practice to apply the grayscale filter
 * to the site's <html> tag. Instead, this plugin only utilizes the site's <body> tag.
 *
 * The modification applies all schema classes to the <body> tag as well as the <html> tag.
 * Now we can use some custom CSS to apply the grayscale scheme to the <html> tag instead of the <body> tag.
 *
 * CSS needed to implement the grayscale fix:
 *
 * body.pojo-a11y-grayscale {   
 *    filter: none !important;   
 *    -webkit-filter: none !important;   
 *    -webkit-filter: none !important;   
 *    -moz-filter: none !important;   
 *    -ms-filter: none !important;   
 *    -o-filter: none !important;   
 *    filter: none !important;   
 * }   
 *
 * html.pojo-a11y-grayscale {
 *    filter: grayscale(100%);   
 *    -webkit-filter: grayscale(100%);   
 *    -webkit-filter: grayscale(1);   
 *    -moz-filter: grayscale(100%);   
 *    -ms-filter: grayscale(100%);   
 *    -o-filter: grayscale(100%);   
 *    filter: gray;   
 * } 
 */
 
!(function () {
    var t = -1 < navigator.userAgent.toLowerCase().indexOf("webkit"),
        e = -1 < navigator.userAgent.toLowerCase().indexOf("opera"),
        o = -1 < navigator.userAgent.toLowerCase().indexOf("msie");
    (t || e || o) &&
        document.getElementById &&
        window.addEventListener &&
        window.addEventListener(
            "hashchange",
            function () {
                var t,
                    e = location.hash.substring(1);
                /^[A-z0-9_-]+$/.test(e) && (t = document.getElementById(e)) && (/^(?:a|select|input|button|textarea)$/i.test(t.tagName) || (t.tabIndex = -1), t.focus());
            },
            !1
        );
})(),
    (function (n, t, o, e) {
        "use strict";
        var i = {
            cache: { $document: n(o), $window: n(t) },
            cacheElements: function () {
                (this.cache.$toolbar = n("#pojo-a11y-toolbar")),
                    (this.cache.$toolbarLinks = this.cache.$toolbar.find("a.pojo-a11y-toolbar-link")),
                    (this.cache.$toolbarToolsLinks = this.cache.$toolbar.find(".pojo-a11y-tools a.pojo-a11y-toolbar-link")),
                    (this.cache.$btnToolbarToggle = this.cache.$toolbar.find("div.pojo-a11y-toolbar-toggle > a")),
                    (this.cache.$skipToContent = n("#pojo-a11y-skip-content")),
                    (this.cache.$body = n("body"));
                    /* Custom: Initialize site's html tag variable. */
                    (this.cache.$html = n("html"));
            },
            settings: {
                minFontSize: 120,
                maxFontSize: 200,
                buttonsClassPrefix: "pojo-a11y-btn-",
                bodyClassPrefix: "pojo-a11y-",
                bodyFontClassPrefix: "pojo-a11y-resize-font-",
                storageKey: "pojo-a11y",
                expires: PojoA11yOptions.save_expiration ? 36e5 * PojoA11yOptions.save_expiration : 432e5,
            },
            variables: { currentFontSize: 120, currentSchema: null },
            activeActions: {},
            buildElements: function () {
                this.cache.$body.prepend(this.cache.$toolbar), this.cache.$body.prepend(this.cache.$skipToContent);
            },
            bindEvents: function () {
                var e = this;
                e.cache.$btnToolbarToggle.on("click", function (t) {
                    t.preventDefault(),
                        e.cache.$toolbar.toggleClass("pojo-a11y-toolbar-open"),
                        e.cache.$toolbar.hasClass("pojo-a11y-toolbar-open") ? e.cache.$toolbarLinks.attr("tabindex", "0") : e.cache.$toolbarLinks.attr("tabindex", "-1");
                }),
                    n(o).on("keyup", function (t) {
                        9 === t.which && e.cache.$btnToolbarToggle.is(":focus") && (e.cache.$toolbar.addClass("pojo-a11y-toolbar-open"), e.cache.$toolbarLinks.attr("tabindex", "0"));
                    }),
                    e.bindToolbarButtons();
            },
            bindToolbarButtons: function () {
                var s = this;
                s.cache.$toolbarToolsLinks.on("click", function (t) {
                    t.preventDefault();
                    var e = n(this),
                        o = e.data("action"),
                        i = e.data("action-group"),
                        a = !1;
                    "reset" !== o ? (-1 !== ["toggle", "schema"].indexOf(i) && (a = e.hasClass("active")), s.activateButton(o, a)) : s.reset();
                });
            },
            activateButton: function (t, e) {
                var o = this.getButtonByAction(t).data("action-group");
                (this.activeActions[t] = !e), this.actions[o].call(this, t, e), this.saveToLocalStorage();
            },
            getActiveButtons: function () {
                return this.cache.$toolbarToolsLinks.filter(".active");
            },
            getButtonByAction: function (t) {
                return this.cache.$toolbarToolsLinks.filter("." + this.settings.buttonsClassPrefix + t);
            },
            actions: {
                toggle: function (t, e) {
                    var o = this.getButtonByAction(t),
                        i = e ? "removeClass" : "addClass";
                    e ? o.removeClass("active") : o.addClass("active"), this.cache.$body[i](this.settings.bodyClassPrefix + t);
                },
                resize: function (t, e) {
                    var o = this.variables.currentFontSize;
                    "resize-plus" === t && this.settings.maxFontSize > o && (this.variables.currentFontSize += 10),
                        "resize-minus" === t && this.settings.minFontSize < o && (this.variables.currentFontSize -= 10),
                        e && (this.variables.currentFontSize = this.settings.minFontSize),
                        this.cache.$body.removeClass(this.settings.bodyFontClassPrefix + o);
                    var i = 120 < this.variables.currentFontSize,
                        a = i ? "addClass" : "removeClass";
                    this.getButtonByAction("resize-plus")[a]("active"),
                        i && this.cache.$body.addClass(this.settings.bodyFontClassPrefix + this.variables.currentFontSize),
                        (this.activeActions["resize-minus"] = !1),
                        (this.activeActions["resize-plus"] = i),
                        this.cache.$window.trigger("resize");
                },
                schema: function (t, e) {
                    var o = this.variables.currentSchema;
                    o && (this.cache.$body.removeClass(this.settings.bodyClassPrefix + o), this.getButtonByAction(o).removeClass("active"), (this.activeActions[o] = !1), this.saveToLocalStorage()),
                    /* Custom: Remove schema class from html tag. */
                    o && (this.cache.$html.removeClass(this.settings.bodyClassPrefix + o), this.getButtonByAction(o).removeClass("active"), (this.activeActions[o] = !1), this.saveToLocalStorage()),
                        e ? (this.variables.currentSchema = null) : ((o = this.variables.currentSchema = t), this.cache.$body.addClass(this.settings.bodyClassPrefix + o), this.getButtonByAction(o).addClass("active"));
                        /* Custom: Add schema class to html tag. */
                        e ? (this.variables.currentSchema = null) : ((o = this.variables.currentSchema = t), this.cache.$html.addClass(this.settings.bodyClassPrefix + o), this.getButtonByAction(o).addClass("active"));
                },
            },
            reset: function () {
                for (var t in this.activeActions) this.activeActions.hasOwnProperty(t) && this.activeActions[t] && this.activateButton(t, !0);
                localStorage.removeItem(this.settings.storageKey);
            },
            saveToLocalStorage: function () {
                if ("1" === PojoA11yOptions.enable_save) {
                    this.variables.expires || (this.variables.expires = new Date().getTime() + this.settings.expires);
                    var t = { actions: this.activeActions, variables: { currentFontSize: this.variables.currentFontSize, expires: this.variables.expires } };
                    localStorage.setItem(this.settings.storageKey, JSON.stringify(t));
                }
            },
            setFromLocalStorage: function () {
                if ("1" === PojoA11yOptions.enable_save) {
                    var t = JSON.parse(localStorage.getItem(this.settings.storageKey));
                    if (t) {
                        var e = new Date();
                        if (t.variables.expires < e) localStorage.removeItem(this.settings.storageKey);
                        else {
                            var o = t.actions;
                            for (var i in (120 < t.variables.currentFontSize && (t.variables.currentFontSize -= 10), n.extend(this.variables, t.variables), o)) o.hasOwnProperty(i) && o[i] && this.activateButton(i, !1);
                        }
                    }
                }
            },
            handleGlobalOptions: function () {
                "1" === PojoA11yOptions.focusable && this.cache.$body.addClass("pojo-a11y-focusable"),
                    "1" === PojoA11yOptions.remove_link_target && n('a[target="_blank"]').attr("target", ""),
                    "1" === PojoA11yOptions.add_role_links && n("a").attr("role", "link");
            },
            init: function () {
                this.cacheElements(), this.buildElements(), this.bindEvents(), this.handleGlobalOptions();
            },
        };
        n(o).ready(function (t) {
            i.init(), i.setFromLocalStorage();
        });
    })(jQuery, window, document);

Schritt 2: Neues Plugin-Skript einbinden (PHP)

Als nächstes muss das von uns erstellte neue Skript auch im Plugin eingebunden werden. Dafür müssen wir die folgende Datei öffnen und bearbeiten:

wp-content/plugins/pojo-accessibility/includes/pojo-a11y-frontend.php

Ab Zeile 26 beginnt die Registrierung des Skripts:

wp_register_script(
	'pojo-a11y',
	POJO_A11Y_ASSETS_URL . 'js/app.min.js',
	array(
		'jquery',
	),
	'1.0.0',
	true
);

Dieser Code bindet das ursprüngliche Skript ein. Wir können den Pfad darin nun zu unserem angelegten Skript ändern:

wp_register_script(
	'pojo-a11y',
	POJO_A11Y_ASSETS_URL . 'js/app.custom.js',
	array(
		'jquery',
	),
	'1.0.0',
	true
);

Schritt 3: Styling anpassen (CSS)

Im Skript ist das nötige CSS bereits im Einleitungskommentar erwähnt. Dieses muss nun zusätzlich in das Theme integriert werden. In den meisten Fällen wird hierfür die Datei style.css im Child-Theme verwendet. Im Zweifelsfall sollte die Dokumentation des Themes konsultiert werden. Mit folgendem CSS-Code entfernen wir den Graustufen-Effekt schließlich vom body-Tag und wenden ihn stattdessen auf den html-Tag an:

body.pojo-a11y-grayscale {   
    filter: none !important;   
    -webkit-filter: none !important;   
    -webkit-filter: none !important;   
    -moz-filter: none !important;   
    -ms-filter: none !important;   
    -o-filter: none !important;   
    filter: none !important;   
}
html.pojo-a11y-grayscale {
    filter: grayscale(100%);   
    -webkit-filter: grayscale(100%);   
    -webkit-filter: grayscale(1);   
    -moz-filter: grayscale(100%);   
    -ms-filter: grayscale(100%);   
    -o-filter: grayscale(100%);   
    filter: gray;   
}

Bücher zum Thema

Barrierefreiheit im Web ist nicht nur ein breites Feld, sondern ein immer größeres Thema. Für einen umfassenden Überblick gibt es beispielsweise auf Amazon (Partnerlinks) inzwischen eine ausgiebige Auswahl an Fachliteratur, sowohl zu WordPress als auch zur Barrierefreiheit:

Fachbücher zum Thema WordPress auf Amazon *
Fachbücher zum Thema Barrierefreiheit im Web auf Amazon *

Jetzt 20% Rabatt auf Real Cookie Banner sichern

Sichere dir 20% Rabatt im ersten Jahr auf den barrierefreien und besten Cookie Banner für WordPress.

Gehe zur Website von Real Cookie Banner * und benutze den Gutschein-Code: WPBARRIEREFREI