Die Ausgangslage
Ab dem 19. Juni 2026 braucht jeder B2C-Shop in der EU einen Widerrufsbutton. Die Rechtsgrundlage ist § 356a BGB, verkündet im BGBl. I Nr. 31 vom 5.2.2026, umgesetzt aus der EU-Richtlinie 2023/2673. Eine Übergangsfrist gibt es nicht.
Der Button braucht zwei Stufen: „Vertrag widerrufen“ als Einstieg, „Widerruf bestätigen“ am Ende des Formulars. Dazwischen ein kurzes Formular, danach eine Eingangsbestätigung per E-Mail auf einem dauerhaften Datenträger nach § 126b BGB.
Weg A: Script-Tag im Header
Der einfachste Weg. Du fügst ein Script-Tag in den Header-Bereich deiner WordPress-Installation ein. Das Script lädt das Widget, erkennt deinen Shop über den Widget-Key und rendert den Button in Shadow DOM, ohne mit deinem Theme-CSS zu kollidieren.
Dazu editierst du die header.php deines Child-Themes. Niemals die des Parent-Themes, sonst ist der Eintrag nach dem nächsten Update weg.
<!-- widget/header.php, im Child-Theme -->
<?php wp_head(); ?>
<script
src="https://widerrufbutton.net/widget/v1/wh.js"
data-shop-id="<?php echo esc_attr(get_option('wrb_shop_id')); ?>"
data-position="footer"
data-lang="de"
async
defer
></script>Wer keinen Zugriff auf das Theme hat, kann das gleiche Script per Plugin wie „Insert Headers and Footers“einbauen. Funktioniert identisch, aber du hast einen Abhängigkeitspunkt mehr.
Weg B: functions.php Filter
Sauberer als ein direkter Eingriff in die header.php ist ein Hook. Du registrierst eine Funktion, die das Script über den WordPress-eigenen wp_enqueue_scripts-Filter ausliefert. Vorteil: dein Theme bleibt unberührt, der Eintrag lässt sich sauber deaktivieren.
// functions.php deines Child-Themes
add_action('wp_footer', function () {
$shop_id = get_option('wrb_shop_id');
if (empty($shop_id)) {
return;
}
printf(
'<script src="https://widerrufbutton.net/widget/v1/wh.js" ' .
'data-shop-id="%s" data-position="footer" data-lang="de" async defer></script>',
esc_attr($shop_id)
);
}, 99);Der Priority-Wert 99 sorgt dafür, dass das Script nach allen anderen Footer-Scripts geladen wird. Das verhindert, dass Caching-Plugins es zu früh minifizieren.
Weg C: WordPress-Plugin
Für Händler ohne Entwickler-Background arbeiten wir an einem offiziellen WordPress-Plugin. Installieren, Shop-ID eintragen, speichern. Der Button erscheint im Footer. Das Plugin wird das Script wie in Weg B hooken, dazu eine Settings-Seite im WP-Admin bereitstellen und eine Prüfung einbauen, ob die konfigurierte Domain zur WordPress-Installation passt.
Wer heute schon live gehen will, nutzt Weg A oder B. Das Plugin ist eine Bequemlichkeit, keine Voraussetzung.
Page-Builder-Konflikte
WooCommerce-Shops laufen selten pur. Die meisten nutzen Elementor, Divi, Bricks oder WPBakery. Jeder dieser Builder rendert Footer-Templates eigenständig und umgeht manchmal den Standard-Hook-Flow.
Elementor: Prüfe, ob dein Footer ein „Theme Builder Footer“ ist. Wenn ja, füge das Widget über ein HTML-Element im Elementor-Footer ein, nicht in der functions.php. Sonst rendert Elementor darüber.
Divi: Die Divi Theme Options haben ein Feld „Code Integration“. Script-Tags dort einfügen, im Abschnitt „Body“.
Bricks: Nutzt einen eigenen Hook namens bricks_body_end. Dein Enqueue muss darauf zielen.
Cache- und Sicherheits-Plugins
WP Rocket, WP Super Cache, LiteSpeed Cache und Autoptimize fassen Script-Tags gerne an. Sie minifizieren, kombinieren, verzögern oder laden sie per JavaScript nach. Beim Widerrufsbutton ist das ein Problem, weil der Button potenziell zu spät erscheint oder gar nicht geladen wird.
Lösung: In den Cache-Einstellungen widerrufbutton.net von Minify und Combine ausnehmen. Bei WP Rocket heißt das „Never delay JavaScript“. Bei LiteSpeed „JS Excludes“. Bei Autoptimize „Exclude scripts from Autoptimize“.
Wordfence und iThemes Security können POST-Requests an externe Domains als verdächtig markieren. Das Widget sendet den Widerruf an unsere API, nicht von deinem Server aus. Der Request geht vom Browser des Kunden direkt zu uns, daher sollte kein Konflikt entstehen. Wenn doch:widerrufbutton.net whitelisten.
Prüfen, ob der Einbau wirklich funktioniert
Öffne deinen Shop im Inkognito-Modus. Scrolle nicht. Der Button muss in Navigation oder Footer sichtbar sein. Klicke ihn. Das Modal muss ohne Scroll-Sprung erscheinen. Tippe einen Testnamen, eine Test-E-Mail, klicke „Widerruf bestätigen“. Du solltest innerhalb von Sekunden eine E-Mail bekommen.
Im WiderrufButton-Dashboard erscheint der Test-Widerruf unter Widerrufe. Lösche den Test-Eintrag danach, um deine Statistik sauber zu halten.
Was das Gesetz technisch verlangt
Der Button muss ohne Scrollen erreichbar sein, was in der Praxis „above the fold“ in Navigation oder sichtbarem Footer bedeutet. Er muss während der gesamten Widerrufsfrist verfügbar sein, also mindestens vierzehn Tage ab Warenerhalt. Ein Login darf der Shop nicht verlangen.
Die Eingangsbestätigung muss unverzüglich folgen, den vollen Wortlaut der Widerrufserklärung enthalten, samt Datum und Uhrzeit, und auf einem dauerhaften Datenträger geliefert werden. Eine E-Mail genügt. Ein Toast-Popup nicht.
Alles, was dahinter technisch notwendig ist, übernimmt das Widget: Validierung, Rate-Limiting (10 Requests pro Minute pro IP), CORS-Gegencheck gegen deine registrierte Domain, Mail-Versand, Langzeit-Archivierung mit Hash-Kette. Details dazu in der Anleitung zu § 356a BGB.
Abmahn-Risiko und Widerrufs-Fristverlängerung
Fehlt der Button, greifen zwei Mechanismen. Wettbewerbsvereine schicken Abmahnungen, die nach RVG typischerweise 500 bis 2.000 € kosten. Und die Widerrufsfrist verlängert sich nach § 356 Abs. 3 BGB automatisch auf zwölf Monate und vierzehn Tage. Ein Kunde kann dann ein ganzes Jahr lang widerrufen.
Beide Risiken sind vermeidbar, indem du heute den Button einbaust.