Cookie-Banner gehoeren zu den am haeufigsten falsch implementierten UI-Elementen im deutschen Web. Fast jede zweite Seite, die ich auditiere, verstoesst gegen das TDDDG (Telekommunikation-Digitale-Dienste-Datenschutz-Gesetz) — meist ohne dass der Betreiber es weiss. Dieser Artikel erklaert, was die Norm verlangt, welche Fehler ich am haeufigsten sehe und wie ein DSGVO-konformer Banner technisch aufgebaut wird.
Worum es geht: § 25 TDDDG
Seit dem 14. Mai 2024 heisst das frueher als TTDSG bekannte Gesetz TDDDG. Inhaltlich blieb der entscheidende Paragraph aber gleich: § 25 TDDDG verlangt eine aktive Einwilligung des Nutzers, bevor Informationen in seinem Endgeraet gespeichert werden duerfen — egal ob klassische Cookies, Local Storage, Session Storage oder Fingerprinting-Verfahren. Ausnahme sind nur technisch zwingend erforderliche Speichervorgaenge wie Session-Cookies fuer den Login oder ein CSRF-Token zum Schutz vor Cross-Site-Request-Forgery.
Die Rechtsgrundlage fuer das TDDDG ist die ePrivacy-Richtlinie der EU, ergaenzt durch die DSGVO. Dazu kommen zwei wichtige Gerichts- bzw. Behoerdenentscheidungen, die in der Praxis oft uebersehen werden:
- EuGH "Planet49" (C-673/17, 2019): Vorab-angekreuzte Checkboxen sind keine wirksame Einwilligung. Der Nutzer muss aktiv klicken.
- DSK-Beschluss vom 22.08.2024: Die Ablehnung muss mit demselben Aufwand und mindestens der gleichen Prominenz wie die Annahme moeglich sein. Wenn "Akzeptieren" als auffaelliger Primaer-Button gestaltet ist und "Ablehnen" sich in einem grauen Sekundaer-Button versteckt, ist die Einwilligung als nicht freiwillig erteilt anzusehen — und damit unwirksam.
Die fuenf haeufigsten Verstoesse
1. UX-Ungleichheit zwischen Akzeptieren und Ablehnen
Das ist der eindeutigste und am haeufigsten dokumentierte Verstoss. Ein klassischer Fall: "Alle akzeptieren" leuchtet in Markenfarbe, "Ablehnen" ist ein dezenter Text-Link in grau. Loesung: Beide Buttons gleich gewichtet, gleicher Background, gleicher Hover. Keine Dark Patterns.
// Schlecht — Dark Pattern
<button className="bg-orange-500 ...">Alle akzeptieren</button>
<button className="bg-slate-700 ...">Nur notwendige</button>
// Gut — UX-gleich, DSK-konform
<button className="bg-orange-500 ...">Nur notwendige</button>
<button className="bg-orange-500 ...">Alle akzeptieren</button>
2. Banner laedt Tracker bevor der Nutzer entscheidet
Wenn das CMP zwar fragt, aber Google Analytics, Facebook Pixel oder eingebettete YouTube-Frames bereits beim ersten Page-Load aktiv sind, ist das eine schwere Verletzung. Ich pruefe das in jedem Audit mit Playwright: Browser frisch oeffnen, Seite laden, Cookies und Drittanbieter-Requests vor jeder Interaktion auswerten. Sind Tracker-URLs darunter? → Verstoss.
3. Granularitaet fehlt
Es muss mindestens drei Kategorien geben: Notwendig, Statistik, Marketing. Wer alles in eine "Akzeptieren"-Schaltflaeche zusammenfasst, hat keine echte Einwilligung — der Nutzer kann nicht entscheiden, was er erlauben will.
4. Kein Widerruf
Die Einwilligung muss jederzeit mit demselben Aufwand widerrufen werden koennen, mit dem sie erteilt wurde. Ein Cookie-Banner, das nach Akzeptieren nie wieder erscheint und keinen "Cookie-Einstellungen aendern"-Link in Footer oder Datenschutzerklaerung anbietet, ist nicht konform.
5. Re-Consent fehlt bei Aenderungen
Wenn neue Drittanbieter dazukommen oder bestehende ihre Zwecke aendern, muss erneut um Einwilligung gebeten werden. Ein einmal vor zwei Jahren erteiltes Consent fuer "Marketing" reicht nicht fuer einen frisch eingebauten TikTok-Pixel.
Wie ein konformer Banner technisch aussieht
Ein sauber gebautes Cookie-Banner in Next.js mit Server-Components-kompatiblem Pattern setzt vor Consent nichts. Erst nach aktivem Klick werden die ausgewaehlten Skripte geladen:
"use client";
const COOKIE_CONSENT_KEY = "consent";
const COOKIE_PREFERENCES_KEY = "consent_prefs";
export function CookieBanner() {
const [visible, setVisible] = useState(false);
const [prefs, setPrefs] = useState({
necessary: true, // immer aktiv
statistics: false,
marketing: false,
});
useEffect(() => {
if (!localStorage.getItem(COOKIE_CONSENT_KEY)) {
setVisible(true);
}
}, []);
const save = (p: typeof prefs) => {
localStorage.setItem(COOKIE_CONSENT_KEY, new Date().toISOString());
localStorage.setItem(COOKIE_PREFERENCES_KEY, JSON.stringify(p));
setVisible(false);
window.dispatchEvent(new CustomEvent("consentChanged", { detail: p }));
};
// Andere Komponenten lauschen auf "consentChanged" und laden ihre
// Skripte erst dann nach.
}
Wichtig: Statistik-/Marketing-Skripte werden nicht im Layout direkt eingebunden, sondern ueber einen Listener, der auf das `consentChanged`-Event reagiert. Vor dem Event ist nichts aktiv — bestaetigt durch Playwright-Audit.
Audit-Trail: Was speichern, was nicht
Aufsichtsbehoerden koennen im Streitfall einen Nachweis verlangen, dass Nutzer X am Tag Y einer bestimmten Konfiguration zugestimmt hat. Ein reiner localStorage-Eintrag reicht dafuer nicht — der ist nicht beweisbar. Ich logge Consents serverseitig in einer eigenen Tabelle:
- Hash der Praeferenzen (z.B. SHA-256 ueber das Settings-JSON)
- Zeitstempel
- User-Agent (gekuerzt, ohne IP — die ist personenbezogen)
- Eventuell Session-ID oder anonyme Visitor-ID
Aufbewahrungsfrist: 3 Jahre nach dem letzten Consent — danach loeschen. Die Frist ergibt sich aus der zivilrechtlichen Verjaehrung von Schadensersatzansprueche.
Was ich konkret mache
Bei einem Compliance-Audit pruefe ich systematisch alle obigen Punkte mit Playwright und einem manuellen Walk-Through. Ein typisches Vorgehen: erst alle Praeferenzen ablehnen, dann beobachten, welche Cookies, LocalStorage-Eintraege und Drittanbieter-Requests trotzdem auftauchen. Im Anschluss dasselbe Spiel mit "Alle akzeptieren". Die Differenz ist der Punkt, an dem das Banner liefert, was es verspricht — oder eben nicht.
Implementierungs-seitig kuemmere ich mich um Auswahl und Einbau eines DSGVO-konformen CMP (selbstgehostet oder EU-Anbieter, keine US-Plattform), Server-Components-kompatibles Pattern in Next.js, Consent-Logging in Supabase EU, Test des Reject-Pfads mit echtem Browser, Update der Datenschutzerklaerung mit aktuellen Anbietern, und ein Re-Consent-Workflow falls sich die Cookie-Liste aendert.
Mehr Details und ein Audit-Angebot fuer dein Projekt findest du auf /compliance/cookie-consent.



