← Knowledge-Base · Code-Snippets

AGB und Datenschutz als PDF an die WooCommerce-Bestellbestätigung anhängen

Aktualisiert 20.08.2026 · 9 Min Lesezeit

WooCommerce verschickt Bestellmails ohne Anhänge. Der Filter, um AGB und Datenschutzerklärung als PDF mitzuschicken, ist ein Dutzend Zeilen lang. Der Fallstrick steckt woanders: „Die Bestellbestätigung" ist je nach Zahlungsart eine andere E-Mail - wer nur eine davon einhängt, verschickt bei Vorkasse-Bestellungen gar keine Rechtstexte.

Dazu kommt eine Frage, die vor dem Code steht: Welches PDF ist überhaupt Pflicht, und welches ist nur gut gemeint?

Warum man das macht

Bei Fernabsatzverträgen mit Verbrauchern reicht es nicht, die Vertragsbedingungen auf der Website anzuzeigen. Sie müssen dem Kunden auf einem dauerhaften Datenträger übermittelt werden - also so, dass er sie unverändert speichern und später wieder aufrufen kann. Eine E-Mail oder ein PDF erfüllt das, eine Unterseite im Shop nicht.

Praktisch gibt es zwei Wege: Man schreibt die Texte in den Fließtext der Bestellbestätigung, oder man hängt sie als PDF an. Der zweite Weg ist übersichtlicher und der Grund, warum die meisten Shops ihn wählen.

Was Pflicht ist - und was nicht

Hier lohnt eine Unterscheidung, die in der Praxis oft untergeht:

  • AGB und Widerrufsbelehrung: gehören auf den dauerhaften Datenträger. Das ist der eigentliche Grund für die ganze Übung.
  • Muster-Widerrufsformular: gehört dazu und wird am häufigsten vergessen. Es ist ein eigenes Dokument, nicht Teil der Belehrung.
  • Datenschutzerklärung: Die Informationspflicht nach Art. 13 DSGVO ist zum Zeitpunkt der Datenerhebung zu erfüllen - also im Checkout, nicht danach. Ein PDF in der Bestätigung ist ein netter Service und schadet nicht. Es ersetzt aber nicht den Hinweis im Bestellprozess.

Wer also die Datenschutz-PDF anhängt, weil er glaubt, damit die DSGVO-Informationspflicht abzuhaken, hat sie trotzdem noch offen.

Erste Frage: Brauchst du überhaupt Code?

Bevor du etwas baust, prüf zwei Dinge:

  • Dein Rechtstexte-Dienst. Anbieter wie Trusted Shops oder die IT-Recht Kanzlei liefern die Texte teils samt Schnittstelle, die Aktualisierungen automatisch einspielt. Dann willst du kein PDF von Hand pflegen.
  • Deine vorhandenen Plugins. Germanized bringt für Rechtstexte eigene Funktionen mit, und auch manche Rechnungs-Plugins können Dateien anhängen. Schau nach, bevor du parallel etwas Zweites baust - zwei Systeme, die dieselbe Datei anhängen, führen zu doppelten Anhängen.

Der Code unten lohnt, wenn du fertige PDFs hast und sie einfach mitschicken willst.

Schritt 1: Wohin die PDFs

Nicht ins Theme-Verzeichnis - beim Theme-Wechsel wären sie weg. Leg einen eigenen Ordner im Upload-Verzeichnis an, etwa /wp-content/uploads/rechtstexte/, und ermittle den Pfad im Code, statt ihn fest einzutragen:

function shop_rechtstexte_verzeichnis() {
    $uploads = wp_upload_dir();
    return trailingslashit($uploads['basedir']) . 'rechtstexte/';
}

/**
 * Welche Dateien angehaengt werden.
 * Der Schluessel steuert spaeter, ob eine Datei fuer alle
 * Kunden gilt oder nur fuer Verbraucher.
 */
function shop_rechtstexte_dateien() {
    return [
        'agb.pdf'                 => 'alle',
        'datenschutz.pdf'         => 'alle',
        'widerrufsbelehrung.pdf'  => 'nur_verbraucher',
        'widerrufsformular.pdf'   => 'nur_verbraucher',
    ];
}

wp_upload_dir() statt eines festen Pfads ist kein Perfektionismus: Beim Umzug auf einen anderen Server oder in eine Staging-Umgebung ändert sich der absolute Pfad, und ein hart eingetragener bricht still.

Schritt 2: Der Filter

WooCommerce fragt vor dem Versand jeder E-Mail, ob Anhänge dazukommen. Erwartet wird ein Array mit absoluten Dateipfaden - keine URLs:

add_filter('woocommerce_email_attachments', 'shop_rechtstexte_anhaengen', 10, 3);

function shop_rechtstexte_anhaengen($anhaenge, $email_id, $order) {
    if (!in_array($email_id, shop_rechtstexte_mails(), true)) {
        return $anhaenge;
    }
    // Bei manchen Mails ist das dritte Argument keine Bestellung
    // (etwa bei "Neues Konto"), deshalb pruefen.
    if (!$order instanceof WC_Order) {
        return $anhaenge;
    }

    $ordner      = shop_rechtstexte_verzeichnis();
    $ist_b2b     = shop_bestellung_ist_b2b($order);

    foreach (shop_rechtstexte_dateien() as $datei => $fuer_wen) {
        if ($fuer_wen === 'nur_verbraucher' && $ist_b2b) {
            continue;
        }
        $pfad = $ordner . $datei;
        if (file_exists($pfad) && is_readable($pfad)) {
            $anhaenge[] = $pfad;
        } else {
            // Nicht still scheitern lassen - sonst faellt es erst auf,
            // wenn ein Kunde nachfragt.
            wc_get_logger()->warning(
                'Rechtstext fehlt oder ist nicht lesbar: ' . $pfad,
                ['source' => 'rechtstexte-anhang']
            );
        }
    }
    return $anhaenge;
}

Registriert wird der Filter bewusst mit drei Argumenten. WooCommerce übergibt inzwischen ein viertes - das E-Mail-Objekt -, aber wer vier Argumente anfordert und sie in einer älteren Version nicht bekommt, handelt sich einen Fatal Error ein. Drei reichen hier.

Schritt 3: An welche E-Mails - der Fallstrick

Das ist der Punkt, an dem die meisten Umsetzungen unvollständig bleiben. „Die Bestellbestätigung" ist in WooCommerce keine einzelne E-Mail, sondern hängt davon ab, in welchem Status die Bestellung landet:

  • customer_processing_order - „In Bearbeitung". Die übliche Bestätigung bei sofort bezahlten Bestellungen, etwa per Karte oder PayPal.
  • customer_on_hold_order - „In Wartestellung". Das ist die Bestätigung bei Vorkasse und Überweisung.
  • customer_completed_order - „Abgeschlossen". Bei digitalen Produkten oft die einzige Mail, die der Kunde bekommt.

Wer nur customer_processing_order einhängt, verschickt an alle Vorkasse-Kunden keine Rechtstexte - und merkt es nicht, weil im eigenen Test meist mit einer sofort bezahlenden Methode geprüft wird. Welche Mail bei welcher Zahlungsart greift, hängt an derselben Mechanik wie der Hinweis je nach Zahlungsart.

function shop_rechtstexte_mails() {
    return [
        'customer_processing_order',  // bezahlt, in Bearbeitung
        'customer_on_hold_order',     // Vorkasse / Ueberweisung
        'customer_completed_order',   // abgeschlossen
    ];
}

Bewusst nicht dabei: new_order. Das ist die Mail an dich selbst - deine eigenen AGB brauchst du nicht im Postfach.

Schritt 4: Im B2B keine Widerrufsbelehrung

Ein Detail mit Folgen. Wer im B2B-Geschäft eine Widerrufsbelehrung mitschickt, obwohl dort kein Widerrufsrecht besteht, kann das so verstanden werden, dass er freiwillig eines einräumt - mehr dazu in Widerruf im B2B.

Deshalb die Unterscheidung aus Schritt 1. Die Erkennung baut auf der Rolle auf, die auch die Nettopreise für B2B-Kunden steuert:

function shop_bestellung_ist_b2b($order) {
    $kunden_id = $order->get_customer_id();
    if (!$kunden_id) {
        return false;   // Gastbestellung: im Zweifel Verbraucher
    }
    $nutzer = get_userdata($kunden_id);
    return $nutzer && in_array('b2b_kunde', (array) $nutzer->roles, true);
}

Gastbestellungen gelten hier als Verbraucher. Das ist die sichere Richtung: Eine überflüssige Widerrufsbelehrung an einen Unternehmer ist ärgerlich, eine fehlende an einen Verbraucher ist ein Fehler.

Wohin der Code gehört

In ein Mini-Plugin, nicht in die functions.php des Themes:

<?php
/**
 * Plugin Name: Rechtstexte an Bestellmails anhaengen
 * Description: Haengt AGB, Datenschutz und Widerrufsunterlagen als PDF an
 *              die Bestellmails an Kunden an.
 * Version:     1.0.0
 */

if (!defined('ABSPATH')) {
    exit; // Direktaufruf verhindern
}

// ... hier der Code aus den Schritten 1 bis 4

Datei nach /wp-content/plugins/rechtstexte-anhang/rechtstexte-anhang.php, dann unter Plugins aktivieren.

Was der Code nicht löst

Den Nachweis, welche Fassung der Kunde bekommen hat

Der unterschätzte Punkt. Ändern sich deine AGB, überschreibst du agb.pdf - und ab dann lässt sich nicht mehr belegen, welche Fassung ein Kunde vor zwei Jahren erhalten hat. Genau darum geht es aber im Streitfall.

Der einfache Umgang damit: Die Datei bekommt eine Version im Namen, etwa agb-2026-08.pdf, und bei jeder Änderung entsteht eine neue Datei statt einer überschriebenen. Im Code passt du dann einen Dateinamen an. Die alten Fassungen bleiben liegen - sie kosten ein paar Kilobyte und sind im Zweifel Gold wert.

Die Zustellbarkeit

Jedes zusätzliche PDF vergrößert die Mail und erhöht die Wahrscheinlichkeit, dass sie in einem Spam-Ordner landet. Vier Anhänge zu je 800 Kilobyte sind kein Problem, vier zu je fünf Megabyte schon.

Wenn deine PDFs groß sind, liegt es meist an eingebetteten Schriften oder Bildern in Druckauflösung. Einmal für den Bildschirm exportieren reicht.

Die Anzeige im Bestellprozess

Die Texte müssen dem Kunden auch vor dem Kauf zugänglich sein. Das PDF danach ist die Bestätigung, nicht die Information. Was im Bestellprozess zu stehen hat, steht in Die Button-Lösung richtig umsetzen.

Häufige Fehler

  • Nur eine E-Mail eingehängt. Der Vorkasse-Fall bleibt übrig. Siehe Schritt 3.
  • Das Widerrufsformular vergessen. Es ist ein eigenes Dokument, nicht Teil der Belehrung.
  • URL statt Pfad. Der Filter erwartet einen absoluten Dateipfad. Mit einer URL kommt der Anhang nicht an - je nach Mailer stillschweigend.
  • Kein file_exists(). Fehlt die Datei, kann der Versand fehlschlagen. Und zwar der ganze, nicht nur der Anhang.
  • PDFs im Theme-Ordner. Beim nächsten Theme-Wechsel sind sie weg - und der Code hängt ins Leere.
  • Doppelte Anhänge. Wenn ein Plugin dieselbe Datei schon anhängt, bekommt der Kunde sie zweimal. Nach dem Einbau eine echte Bestellmail ansehen.
  • Alte Fassungen überschrieben. Siehe oben - kostet nichts, wenn man vorher daran denkt.

Testliste

  1. Testbestellung mit sofortiger Zahlung: Sind alle PDFs an der Bestätigung?
  2. Testbestellung mit Vorkasse: Kommen sie dort ebenfalls an?
  3. Bestellung auf „Abgeschlossen" setzen: Wieder alle dabei?
  4. Lassen sich die Anhänge öffnen und sind es die aktuellen Fassungen?
  5. Deine Admin-Mail ansehen: Hängen dort keine PDFs dran?
  6. Mit einem B2B-Testkonto bestellen: Fehlen Widerrufsbelehrung und -formular?
  7. Eine Datei umbenennen und erneut bestellen: Kommt die Mail trotzdem an, und steht die Warnung im WooCommerce-Protokoll unter Status → Protokolle?
  8. Gesamtgröße der Mail prüfen - landet sie bei Gmail und Outlook im Posteingang?

Punkt sieben ist der, der später Zeit spart: Wenn die Datei einmal fehlt, willst du es im Protokoll sehen und nicht aus einer Kundenbeschwerde erfahren.

Weiterlesen

Wir sind Praktiker aus der Shop-Entwicklung und keine Rechtsanwälte - welche Unterlagen dein Shop übermitteln muss, hängt vom Sortiment und von deinen Kunden ab. Für verbindliche Auskünfte und geprüfte Rechtstexte empfehlen wir Trusted Shops oder die IT-Recht Kanzlei. Test den Code auf einer Staging-Umgebung, bevor er in den Live-Shop geht. Stand: August 2026.

Hat dir dieser Artikel weitergeholfen?

Dann weißt du jetzt, wie wir arbeiten: ehrlich, direkt und ohne Abkürzungen. Wenn dich das überzeugt, freuen wir uns riesig über eine kurze Google-Bewertung. Das dauert keine Minute und hilft uns enorm.

Jetzt auf Google bewerten

Ehrlich verdient statt manipuliert - so muss das.

War diese Anleitung hilfreich?

Fehlt dir etwas oder können wir den Artikel verbessern? Sag es uns.