Cookie Widget DSGVO Guide
Cookie Widget: DSGVO-konformer Cookie-Banner in einer Zeile
Cookies brauchen seit DSGVO eine aktive Einwilligung. Das Enjyn Cookie Widget liefert eine vollständige, kostenlose Alternative zu Cookiebot und Usercentrics – selbst gehostet, ohne Abo, ohne Datenweitergabe an Drittanbieter.
Was ist das Cookie Widget?
Ein selbstgehostetes Cookie-Consent-System mit: ✓ Automatischer Cookie-Erkennung (~50 bekannte Tracker, mit Wildcards) ✓ Script- und Iframe-Blocker (Tracker laden gar nicht erst) ✓ Datenschutz-Auto-Tabelle (per <div>-Container) ✓ 9 vorgefertigte Themes (inkl. Glasmorphismus) ✓ Live-Design-Anpassung (Farbe, Transparenz, Blur) ✓ Rechtstext-Lesemodus (kompakter Banner mit Ausklappfeld) ✓ Mobile-optimiert (Bottom-Sheet mit Inner-Scrolling) ✓ Mehrsprachig (DE / EN, Auto-Erkennung) ✓ Anonymisierter Consent-Log (DSGVO Art. 7 Nachweispflicht) ✓ Reopen-Button für Widerruf (jederzeit, optional ausblendbar) ✓ Zurück-Button (history.back) (automatisch bei vorhandener Historie) ✓ Quarantäne für unbekannte Cookies ✓ 3D-Cookie als Style-Element
Schnellstart (eine Zeile)
<script src="https://enjyn.de/src/enjyn-cookie.php" async></script>
Das war's. Banner erscheint beim ersten Besuch mit direkt sichtbaren Kategorien.
DSGVO-Anforderungen erfüllt
| Anforderung | Umsetzung im Widget |
|---|---|
| Aktive Einwilligung | Cookies werden erst beim Klick auf einen Button aktiviert |
| Ablehnen so prominent wie Akzeptieren | „Nur Notwendige" und „Alle akzeptieren" gleichwertig dargestellt |
| Granulare Auswahl | Toggle-Switches pro Kategorie, direkt im Banner |
| Widerruf so einfach wie Erteilung | Reopen-Button + Container data-enjyn-open |
| Keine Cookies vor Zustimmung | Echter Script-Blocker via type="text/plain" |
| Nachweis der Einwilligung | Server-Log mit anonymisierter Pseudo-ID |
Drei Konfigurations-Wege
# Variante 1: window.EnjynCookie (volle Kontrolle)
<script>
window.EnjynCookie = {
site_name: "Meine Website",
primary: "#2563eb",
position: "bottom-right",
privacy_url: "/datenschutz"
};
</script>
<script src="https://enjyn.de/src/enjyn-cookie.php" async></script>
# Variante 2: data-Attribute (Simpel-Setup)
<script src="https://enjyn.de/src/enjyn-cookie.php"
data-primary="#16a34a"
data-position="bottom-center"
data-privacy-url="/datenschutz"
async></script>
# Variante 3: URL-Parameter (für CMS-Systeme)
<script src="https://enjyn.de/src/enjyn-cookie.php?primary=16a34a&position=bottom-center"
async></script>
Konfigurationsoptionen im Überblick
| Option | Standard | Beschreibung |
|---|---|---|
| Allgemein | ||
site_name | – | Name der Website (auch für Cookie-Provider-Auflösung) |
operator | – | Betreiber-Name |
contact | – | Datenschutz-Kontakt-E-Mail |
lang | de | Sprache: de / en |
auto_lang | true | Browser-Sprache automatisch erkennen |
privacy_url | – | Link zur Datenschutzerklärung |
imprint_url | – | Link zum Impressum |
consent_lifetime | 180 | Tage bis erneut nachgefragt wird |
auto_scan | true | Auto-Erkennung von Cookies |
show_reopen | true | Cookie-Icon in der Ecke nach Consent |
log_consents | false | Anonymisierten Consent-Log aktivieren |
log_endpoint | – | URL für Consent-Log-POST |
| Design | ||
primary | #2563eb | Akzentfarbe |
primary_text | #ffffff | Text auf Primary-Buttons |
position | bottom-right | bottom-right / -left / -center / center |
theme | auto | siehe Themes-Liste |
style | modern | modern / minimal / box |
animation | slide | slide / fade / pop |
radius | 14px | Ecken-Radius |
btn_radius | 10px | Button-Ecken-Radius |
opacity | 1 | Karten-Transparenz (0–1) |
card_blur | 0 | Glasmorphismus-Blur in px |
backdrop | true | Verdunkelung Hintergrund |
backdrop_blur | 2 | Backdrop-Blur in px |
backdrop_alpha | 0.35 | Hintergrund-Dunkelheit (0–1) |
border_width | 1 | Rahmenstärke in px |
font_scale | 1 | Schriftgrößen-Skalierung |
| Lesemodus | ||
legal_mode | undefined | true / false / undefined (auto-Erkennung) |
legal_paths | [] | Eigene Pfade zusätzlich zu Standards |
9 vorgefertigte Themes
| Theme | Look |
|---|---|
| default | Modern, blau, weiß |
| dark | Dunkler Modus |
| glass | Glasmorphismus, halbtransparent mit Blur |
| glass-dark | Dunkler Glaseffekt |
| neon | Knallige Akzente auf schwarz |
| minimal-bw | Reduziert, schwarz/weiß, scharfe Kanten |
| pastel | Rosa, weich, sehr rund |
| brutal | Hart kantig, gelb, harter Schatten |
| soft | Sehr rund, Pill-Buttons, weiche Schatten |
Adaptive Button-Anzeige
Die Buttons im Banner passen sich automatisch an den Inhalt an:
# Es gibt optionale Kategorien (Analytics, Marketing, …)
[Zurück] [Nur Notwendige] [Alle akzeptieren]
# Der Nutzer wählt eine Kategorie ab
[Zurück] [Nur Notwendige] [Auswahl speichern]
# Nur essential vorhanden, keine optionalen Cookies
[Zurück] [Akzeptieren]
# Keine Browser-Historie (Direkteinstieg)
[Nur Notwendige] [Alle akzeptieren]
Eigene Cookie-Kategorien konfigurieren
window.EnjynCookie = {
categories: {
analytics: {
label_de: "Statistik",
desc_de: "Anonymisierte Auswertung der Seitennutzung.",
cookies: [
# Einzelner Cookie
{
name: "_ga",
provider: "Google LLC (USA)",
purpose_de: "Unterscheidet eindeutige Besucher.",
duration: "2 Jahre",
type: "HTTP-Cookie"
},
# Wildcard – matched _ga_ABCDEF, _ga_XYZ123 etc.
{
name: "_ga_*",
provider: "Google LLC (USA)",
purpose_de: "GA4-Session-State.",
duration: "2 Jahre",
type: "HTTP-Cookie"
}
],
# Diese Scripts laden erst NACH Zustimmung
scripts: [
{ src: "https://www.googletagmanager.com/gtag/js?id=G-XXXX",
async: true }
]
}
}
};
Script-Blocker: Wie es richtig funktioniert
Viele Cookie-Banner löschen Cookies nur nachträglich – das ist DSGVO-rechtlich grenzwertig, weil die Tracking-Anfrage trotzdem bereits passiert ist. Das Enjyn Cookie Widget verhindert das Laden komplett:
# Vorher (DSGVO-Verstoß): Tracker lädt SOFORT
<script src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>
# Nachher: Tracker wird vor Consent NICHT geladen
<script type="text/plain"
data-cookiecategory="analytics"
data-src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>
Iframe-Blocker (YouTube, Maps, Vimeo)
<iframe data-cookiecategory="marketing"
data-src="https://www.youtube-nocookie.com/embed/VIDEO_ID"
width="560" height="315"></iframe>
Inhalts-Platzhalter
Statt eines leeren Bereichs vor Consent erscheint eine „Inhalt blockiert"-Box mit Akzeptier-Button:
<div data-enjyn-placeholder="marketing"></div>
Automatische Cookie-Erkennung
Der Auto-Scanner findet Cookies aus mehreren Quellen:
1. document.cookie → inkl. Live-Überwachung neu gesetzter Cookies
2. localStorage → wird enumeriert
3. sessionStorage → wird enumeriert
4. IndexedDB → Datenbank-Namen werden erfasst
5. PerformanceObserver → Drittanbieter-Domains werden erkannt
6. MutationObserver → dynamisch eingefügte Scripts/Iframes
(z. B. Google Tag Manager, Cookiebot)
7. Cookie-Datenbank → ~50 bekannte Tracker mit Wildcard-Matching
(z. B. _ga_* matcht _ga_ABCDEF)
# Unbekannte Cookies landen in einer Quarantäne-Kategorie
# → standardmäßig DEAKTIVIERT, damit der Betreiber sie sortieren kann.
# Provider "Diese Website" wird automatisch durch site_name oder
# location.hostname ersetzt (kein Platzhalter im UI sichtbar).
Quarantäne & Cookie-Zuordnung
Sobald ein Cookie in categories.X.cookies definiert ist (auch via Wildcard), gilt diese Kategorie und der Cookie verschwindet aus der Quarantäne. Zusätzlich gibt es eine Laufzeit-API:
# Workflow für Quarantäne-Cleanup
EnjynCookie.unknown() → Liste aller unbekannten Cookies
# Pro Cookie zuordnen:
EnjynCookie.assign("xyz_session", "essential", {
provider: "Mein CMS",
purpose_de: "Session-Verwaltung",
duration: "Session",
type: "HTTP-Cookie"
});
Datenschutzerklärung – Auto-Integration
Statt mühsam jede Cookie-Tabelle manuell zu pflegen, platzierst du einfach Container in deiner Datenschutzerklärung. Das Widget befüllt sie automatisch.
# Komplette Tabelle aller Cookies <div data-enjyn-cookie-table></div> # Nur eine Kategorie <div data-enjyn-cookie-table="analytics"></div> # Reine Komma-Liste der Cookie-Namen <span data-enjyn-cookie-list></span> # Link öffnet die Cookie-Einstellungen <a data-enjyn-open href="#">Cookie-Einstellungen ändern</a>
Unter der automatisch eingefügten Tabelle erscheint dezent „bereitgestellt durch Enjyn Gruppe" (Text-Link auf enjyn.de).
Rechtstext-Lesemodus
Auf rechtlichen Seiten (Datenschutz, Impressum, AGB) wird der Banner
automatisch als schmaler Banner unten rechts dargestellt – ohne Backdrop,
damit der Text gut lesbar bleibt. Die Kategorien sind hinter einem
Ausklappfeld versteckt.
# Automatisch erkannte Pfade
/datenschutz, /datenschutzerklaerung, /privacy, /privacy-policy,
/impressum, /imprint, /legal,
/agb, /terms, /terms-of-service, /tos,
/cookies, /cookie-policy, /cookie-richtlinie,
/widerruf, /withdrawal, /haftungsausschluss
# Eigene Pfade ergänzen
window.EnjynCookie = {
legal_paths: ["/nutzungsbedingungen", "/eigener-pfad"]
};
Banner-Text im Lesemodus: „Die Cookies wurden noch nicht akzeptiert, oder es wurde noch keine Einstellung festgelegt. Sie befinden sich aktuell nur im Lesemodus für Rechtsdokumente."
Mobile-Optimierung
Das Widget passt sich auf Smartphones und Tablets automatisch an: ✓ Banner als zentriertes Bottom-Sheet (volle Breite, mittig) ✓ Inner-Scrolling: lange Kategorien-Listen scrollen, Buttons und Footer bleiben sichtbar ✓ Touch-Targets mindestens 44 px hoch ✓ Cookie-Tabelle wird zum Card-Layout mit Labels ✓ Buttons: Zurück + Nur Notwendige nebeneinander (je 50 %), Akzeptieren in eigener Zeile (volle Breite, am Daumen unten) ✓ 3D-Cookie dezenter (56 px statt 78 px)
Reopen-Button steuern
Standardmäßig erscheint nach der Consent-Wahl ein kleines Cookie-Icon
in der Ecke, mit dem der Nutzer seine Einstellungen jederzeit ändern kann.
Diesen Button kann der Betreiber ausschalten – z. B. wenn er den Widerruf
über einen eigenen Link in der Fußzeile anbietet.
window.EnjynCookie = {
show_reopen: false # Icon ausblenden
};
# Stattdessen einen Trigger im Text:
<a data-enjyn-open href="#">Cookie-Einstellungen</a>
Live-Design-Anpassung
# Theme zur Laufzeit wechseln
EnjynCookie.setTheme("glass")
# Einzelne Werte feintunen
EnjynCookie.setDesign({
primary: "#ff0080", # Akzentfarbe
opacity: 0.7, # Karten-Transparenz
card_blur: 20, # Glasmorphismus-Blur (px)
backdrop_blur: 8, # Hintergrund-Blur (px)
radius: "24px", # Ecken-Radius
font_scale: 1.1 # Schriftgrößen-Skalierung
})
JavaScript API
# Banner-Aktionen
EnjynCookie.open() → Settings-Dialog öffnen
EnjynCookie.accept() → Alle akzeptieren
EnjynCookie.reject() → Nur Notwendige
EnjynCookie.reset() → Banner zurücksetzen
EnjynCookie.get() → Aktueller Consent
EnjynCookie.isAllowed("analytics") → Boolean
# Design (live)
EnjynCookie.setTheme("glass")
EnjynCookie.setDesign({...})
EnjynCookie.getDesign() → aktuelle Werte
EnjynCookie.themes() → Array aller Theme-Namen
# Auto-Scanner & Zuordnung
EnjynCookie.scan() → Sofort-Scan auslösen
EnjynCookie.found() → Alle erkannten Cookies
EnjynCookie.unknown() → Quarantäne-Liste
EnjynCookie.assign(name, category, meta)
→ Cookie manuell einer Kategorie zuordnen
# Sprache & Datenschutz
EnjynCookie.setLanguage("en") → Sprache wechseln ohne Reset
EnjynCookie.refreshPrivacy() → Datenschutz-Container neu rendern
# Events
EnjynCookie.onChange(fn) → Listener auf Consent-Änderungen
EnjynCookie.version → "1.0.0"
EnjynCookie.config → vollständige Konfiguration
onChange-Listener: Analytics nach Consent starten
EnjynCookie.onChange(function (record) {
if (record.choices.analytics) {
# hier Google Analytics, Matomo etc. initialisieren
gtag('js', new Date());
gtag('config', 'G-XXXX');
}
if (record.choices.marketing) {
# hier Facebook Pixel, LinkedIn Insight etc.
}
});
Was das Widget NICHT macht
❌ Kein Tracking der Besucher ❌ Keine externen Schriftarten / Icons (alles inline-SVG) ❌ Keine Datenübertragung vor Consent ❌ Kein personenbezogenes Logging (IP nur als anonymisierter Hash) ❌ Keine Drittanbieter-CDN ✓ 100% selbst gehostet ✓ Komplett im Quellcode einsehbar ✓ Funktioniert ohne JavaScript-Build-Tools ✓ ~25 KB gzipped (rund 130 KB unkomprimiert)
Server-Log: Einwilligungs-Nachweis
# Was wird gespeichert?
- Zeitstempel der Einwilligung
- Sprache (de/en)
- Choices: { essential:true, analytics:false, marketing:false }
- Anonymisierte Pseudo-ID (16 Zeichen)
- Site (Hostname der Website)
- Version des Widgets
# Was wird NICHT gespeichert?
- Keine IP im Klartext
- Kein User-Agent im Klartext
- Keine Klarnamen oder E-Mails
- Kein Browser-Fingerprint
# Anonymisierung
IP-Subnet (/24 IPv4, /48 IPv6) + sha256 + tägliches Salt
Salts werden nach 30 Tagen automatisch gelöscht
→ Re-Identifikation praktisch unmöglich
Vergleich mit kommerziellen Anbietern
| Feature | Cookiebot | Usercentrics | Enjyn Cookie Widget |
|---|---|---|---|
| Preis pro Monat | ab 9 € | ab 50 € | 0 € |
| Auto-Cookie-Erkennung | ✓ | ✓ | ✓ |
| Script-Blocker | ✓ | ✓ | ✓ |
| Selbst gehostet | × | × | ✓ |
| Datenweitergabe an Drittland | EU (Dänemark) | EU | keine |
| Custom Themes | begrenzt | € Premium | 9 + Live-Editor |
| Rechtstext-Lesemodus | × | × | ✓ |
| 3D-Cookie als Style-Element | × | × | ✓ |
- Tausche bei Tracking-Scripts
srcgegendata-srcundtype="text/plain" - Setze
EnjynCookie.onChange()-Listener für dein Analytics-Setup - Nutze
data-enjyn-cookie-tablein der Datenschutzerklärung – keine doppelte Pflege - Setze
site_name, damit die eigenen Cookies (PHPSESSID, enjyn_consent …) den echten Site-Namen statt „Diese Website" anzeigen - Wildcards in Cookie-Namen (
_ga_*) werden automatisch erkannt - Quarantäne-Cookies via
EnjynCookie.assign(name, category, meta)zur Laufzeit zuordnen - Teste mit
EnjynCookie.reset()in der DevTools-Konsole - Auf Rechtstextseiten greift der Lesemodus automatisch – schmaler Banner unten rechts
- Reopen-Button optional ausblendbar mit
show_reopen: false
Lizenz & Wasserzeichen
Das Widget ist kostenlos nutzbar. Das „powered by Enjyn Gruppe"-Wasserzeichen (Logo unten im Banner, Settings-Dialog und in der Datenschutz-Tabelle) ist Lizenzbestandteil und darf weder im HTML noch im CSS entfernt werden. Der Code erzwingt es sowohl serverseitig (PHP) als auch clientseitig (JavaScript + CSS).
Diebstahlschutz: Das Widget funktioniert nur, wenn es von einer autorisierten Domain (Standard: enjyn.de) geladen wird. Bei unautorisierten Kopien zeigt es einen roten Warnbanner und führt keine Funktionen aus.