DSGVO Einwilligung Technisch Umsetzen
DSGVO-konforme Einwilligung technisch umsetzen – Consent Management
1. Rechtliche Anforderungen an die Einwilligung nach Art. 7 DSGVO
Artikel 7 DSGVO definiert die Anforderungen an eine gültige und wirksame Einwilligung. Diese muss folgende Bedingungen erfüllen:
1.1 Die 5 Kriterien für eine gültige Einwilligung:
| Kriterium | Bedeutung | Technische Umsetzung |
|---|---|---|
| Freely Given (Freiwillig) |
Keine Zwangsmittel, keine Voraussetzung ohne Rechtsgrund, keine Nachteil ohne Nicht-Einwilligung | Optional-Checkboxen (nicht verpflichtend für Nutzung). Bei essentiellen Services: klare Trennung |
| Specific (Spezifisch) |
Separate Einwilligung für jeden Zweck (nicht eine "Alles" Checkbox) | Separate Checkboxen pro Cookie-Kategorie, Datennutzung oder Service |
| Informed (Informiert) |
Nutzer muss wissen, welche Daten wofür verarbeitet werden | Klare, verständliche Erklärungen, Datenschutzerklärung verlinkt |
| Unambiguous (Unmissverständlich) |
Keine Zweideutigkeiten. Die Handlung muss klar Zustimmung signalisieren | Explizite Checkboxen (nicht Opt-Out), klare Call-to-Action Buttons |
| Active (Aktiv, Affirmative Action) |
Keine vorgefüllten Boxen. Nutzer muss aktiv zustimmen | Unkonfigurierte Checkboxen, keine automatische Aktivierung durch Scrolling |
2. Grundsätze der technischen Umsetzung
2.1 Consent BEFORE Processing
Nach Art. 7 Abs. 4 DSGVO muss die Einwilligung VOR der Datenverarbeitung erhoben werden. Das bedeutet:
- Cookies werden erst nach Einwilligung gesetzt (außer essentiellen)
- Google Analytics, Facebook Pixel, etc. werden erst nach Opt-In aktiviert
- Externe Scripts werden erst nach Zustimmung geladen
- Benutzer-Tracking beginnt nach Zustimmung
2.2 Granular Consent (Unabhängige Entscheidungen)
Nutzer sollen für jeden Zweck einzeln entscheiden können:
- ☐ Essentiell (Funktioniert die Website)
- ☐ Analytik (Google Analytics, Matomo)
- ☐ Marketing (Facebook, Google Ads Pixel)
- ☐ Externe Inhalte (YouTube, Vimeo, Twitter Embeds)
- ☐ Partner/Drittanbieter
2.3 Logging und Audit Trail
Jede Einwilligung muss dokumentiert werden:
- Zeitstempel der Einwilligung (ISO 8601 Format)
- IP-Adresse des Nutzers (gehashed für Datenschutz)
- Welche Zwecke wurden akzeptiert/abgelehnt
- Version der Datenschutzerklärung/Consent-Richtlinie
- Browser/Device-Info (optional, bei Bedarf)
- Withdrawable-Möglichkeit dokumentieren
3. Datenbankschema für Einwilligungen
Hier ist ein praktisches SQL-Schema zur Speicherung von Einwilligungen:
CREATE TABLE consents (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT, -- NULL für anonyme Nutzer
email VARCHAR(255), -- Alternative zu user_id
consent_hash VARCHAR(255) UNIQUE, -- SHA256 Hash für Anonymisierung
-- Einwilligung Zwecke (Boolean)
consent_analytics BOOLEAN DEFAULT FALSE,
consent_marketing BOOLEAN DEFAULT FALSE,
consent_external_content BOOLEAN DEFAULT FALSE,
consent_third_party BOOLEAN DEFAULT FALSE,
-- Audit Trail
timestamp_granted DATETIME, -- Wann wurde zugestimmt
timestamp_withdrawn DATETIME, -- Wann wurde zurückgezogen (NULL = noch gültig)
ip_address_hash VARCHAR(64), -- Hash der IP, nicht die echte IP speichern!
user_agent_hash VARCHAR(64), -- Hash des Browsers
consent_version VARCHAR(10), -- z.B. "v1.0", "v2.0" für Versionierung
-- Rechtliche Grundlagen
gdpr_compliant BOOLEAN DEFAULT TRUE,
legal_basis VARCHAR(50), -- z.B. "Art. 6 Abs. 1 a) DSGVO"
-- Nachverfolgung
withdrawn_by VARCHAR(50), -- "email", "unsubscribe_link", "api", "user_request"
notes TEXT, -- Frei für Notizen
INDEX idx_consent_hash (consent_hash),
INDEX idx_email (email),
INDEX idx_timestamp (timestamp_granted),
INDEX idx_withdrawn (timestamp_withdrawn)
);
-- Historisierung (Optional aber empfohlen)
CREATE TABLE consents_audit_log (
id INT AUTO_INCREMENT PRIMARY KEY,
consent_id INT,
old_analytics BOOLEAN,
new_analytics BOOLEAN,
changed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
changed_by VARCHAR(255),
FOREIGN KEY (consent_id) REFERENCES consents(id)
);
4. PHP Code: Einwilligung speichern und prüfen
<?php
// File: consent_manager.php
class ConsentManager {
private $db;
private $allowed_purposes = ['analytics', 'marketing', 'external_content', 'third_party'];
public function __construct($database_connection) {
$this->db = $database_connection;
}
/**
* Speichere Einwilligung in Datenbank
*/
public function saveConsent($email, $purposes, $ip_address) {
// IP-Adresse hashen (nicht speichern!)
$ip_hash = hash('sha256', $ip_address . $_SERVER['HTTP_USER_AGENT']);
$user_agent_hash = hash('sha256', $_SERVER['HTTP_USER_AGENT']);
$consent_hash = hash('sha256', $email . time() . rand());
$stmt = $this->db->prepare("
INSERT INTO consents (
email, consent_analytics, consent_marketing,
consent_external_content, consent_third_party,
timestamp_granted, ip_address_hash, user_agent_hash,
consent_version, consent_hash
) VALUES (?, ?, ?, ?, ?, NOW(), ?, ?, 'v2.0', ?)
");
$stmt->bind_param(
"siiiisss",
$email,
$purposes['analytics'] ? 1 : 0,
$purposes['marketing'] ? 1 : 0,
$purposes['external_content'] ? 1 : 0,
$purposes['third_party'] ? 1 : 0,
$ip_hash,
$user_agent_hash,
$consent_hash
);
if ($stmt->execute()) {
// Audit Log
$this->logConsentChange($stmt->insert_id, 'Created');
// Cookie setzen (zur Demonstration)
setcookie(
'consent_preferences',
$consent_hash,
time() + (365 * 24 * 60 * 60), // 1 Jahr
'/',
'',
true, // secure (HTTPS)
true // httpOnly
);
return ['success' => true, 'consent_id' => $stmt->insert_id];
} else {
return ['success' => false, 'error' => 'Database error'];
}
}
/**
* Prüfe, ob Nutzer Zustimmung für einen Zweck gegeben hat
*/
public function hasConsent($email, $purpose) {
if (!in_array($purpose, $this->allowed_purposes)) {
return false;
}
$field = 'consent_' . $purpose;
$stmt = $this->db->prepare("
SELECT $field FROM consents
WHERE email = ?
AND timestamp_withdrawn IS NULL
ORDER BY timestamp_granted DESC
LIMIT 1
");
$stmt->bind_param("s", $email);
$stmt->execute();
$result = $stmt->get_result()->fetch_assoc();
return $result ? (bool)$result[$field] : false;
}
/**
* Einwilligung zurückziehen
*/
public function withdrawConsent($email, $purpose = null) {
$stmt = $this->db->prepare("
UPDATE consents
SET timestamp_withdrawn = NOW()
WHERE email = ? AND timestamp_withdrawn IS NULL
");
$stmt->bind_param("s", $email);
if ($stmt->execute()) {
$this->logConsentChange(null, 'Withdrawn', $email);
return ['success' => true, 'message' => 'Consent withdrawn'];
}
return ['success' => false];
}
/**
* Audit Log entry
*/
private function logConsentChange($consent_id, $action, $email = null) {
$stmt = $this->db->prepare("
INSERT INTO consents_audit_log (consent_id, changed_at, changed_by)
VALUES (?, NOW(), ?)
");
$stmt->bind_param("is", $consent_id, $action);
$stmt->execute();
}
/**
* Alle Einwilligungen eines Nutzers abrufen (für Transparenz)
*/
public function getConsentForUser($email) {
$stmt = $this->db->prepare("
SELECT consent_analytics, consent_marketing,
consent_external_content, consent_third_party,
timestamp_granted, timestamp_withdrawn
FROM consents
WHERE email = ?
ORDER BY timestamp_granted DESC
LIMIT 1
");
$stmt->bind_param("s", $email);
$stmt->execute();
return $stmt->get_result()->fetch_assoc();
}
}
// Verwendungsbeispiel:
$db = new mysqli("localhost", "user", "password", "database");
$consent = new ConsentManager($db);
// Einwilligung speichern
$result = $consent->saveConsent(
'user@example.com',
['analytics' => true, 'marketing' => false, 'external_content' => true, 'third_party' => false],
$_SERVER['REMOTE_ADDR']
);
// Prüfen ob Nutzer Analytics akzeptiert hat
if ($consent->hasConsent('user@example.com', 'analytics')) {
// Google Analytics laden
echo '';
} else {
echo '';
}
?>
5. Cookie Banner – Einfaches HTML/JS Beispiel (ohne Bibliothek)
<!-- Cookie Banner HTML -->
<div id="cookie-banner" style="
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #f0f0f0;
border-top: 3px solid #333;
padding: 20px;
z-index: 9999;
font-family: Arial;
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
">
<div style="max-width: 1200px; margin: 0 auto;">
<h3>🍪 Datenschutz & Cookies</h3>
<p>Wir nutzen Cookies für Analytics und Marketing. Lesen Sie unsere
<a href="/datenschutz.html" target="_blank">Datenschutzerklärung</a></p>
<div style="margin: 15px 0;">
<label style="display: block; margin: 10px 0;">
<input type="checkbox" id="essential" checked disabled>
<strong>✓ Essentiell</strong> (Funktioniert die Website)
</label>
<label style="display: block; margin: 10px 0;">
<input type="checkbox" id="analytics">
<strong>Analytik</strong> (Google Analytics, Nutzungsverhalten verstehen)
</label>
<label style="display: block; margin: 10px 0;">
<input type="checkbox" id="marketing">
<strong>Marketing</strong> (Facebook Pixel, Retargeting)
</label>
<label style="display: block; margin: 10px 0;">
<input type="checkbox" id="external">
<strong>Externe Inhalte</strong> (YouTube, Twitter Embeds)
</label>
</div>
<div style="margin-top: 15px;">
<button id="accept-selected" style="
background: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
margin-right: 10px;
">✓ Akzeptieren</button>
<button id="accept-all" style="
background: #008CBA;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
margin-right: 10px;
">Alle akzeptieren</button>
<button id="reject-all" style="
background: #f44336;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
">Alles ablehnen</button>
</div>
</div>
</div>
<script>
// Cookie Banner JavaScript
const banner = document.getElementById('cookie-banner');
const acceptSelectedBtn = document.getElementById('accept-selected');
const acceptAllBtn = document.getElementById('accept-all');
const rejectAllBtn = document.getElementById('reject-all');
// Prüfe ob Einwilligung bereits vorhanden ist
if (document.cookie.includes('consent_preferences')) {
banner.style.display = 'none'; // Banner ausblenden
}
// Accept Selected
acceptSelectedBtn.addEventListener('click', function() {
const preferences = {
analytics: document.getElementById('analytics').checked,
marketing: document.getElementById('marketing').checked,
external: document.getElementById('external').checked,
essential: true // Immer true
};
saveConsent(preferences);
loadConsentScripts(preferences);
banner.style.display = 'none';
});
// Accept All
acceptAllBtn.addEventListener('click', function() {
const preferences = {
analytics: true,
marketing: true,
external: true,
essential: true
};
saveConsent(preferences);
loadConsentScripts(preferences);
banner.style.display = 'none';
});
// Reject All
rejectAllBtn.addEventListener('click', function() {
const preferences = {
analytics: false,
marketing: false,
external: false,
essential: true
};
saveConsent(preferences);
banner.style.display = 'none';
});
// Speichere Einwilligung (AJAX)
function saveConsent(preferences) {
fetch('/api/save-consent.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: document.body.dataset.userEmail || 'anonymous@example.com',
preferences: preferences
})
})
.then(response => response.json())
.then(data => {
// Erfolg - Cookie setzen
document.cookie = 'consent_preferences=' + data.consent_hash +
'; max-age=31536000; path=/; Secure; SameSite=Strict';
});
}
// Lade Consent-abhängige Scripts
function loadConsentScripts(preferences) {
if (preferences.analytics) {
// Google Analytics
window.dataLayer = window.dataLayer || [];
window.gtag = function() { dataLayer.push(arguments); };
gtag('js', new Date());
gtag('config', 'GA-XXXXX');
const script = document.createElement('script');
script.src = 'https://www.googletagmanager.com/gtag/js?id=GA-XXXXX';
script.async = true;
document.head.appendChild(script);
}
if (preferences.marketing) {
// Facebook Pixel
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};n.push=n;n.loaded=!0;
// ... Facebook Pixel Code ...
}
}
</script>
6. Consent für Minors (Art. 8 DSGVO)
Für Nutzer unter 16 Jahren gelten in Deutschland zusätzliche Anforderungen:
- Altersgrenze: Deutschland hat Art. 8 DSGVO auf 16 Jahre festgelegt (nicht 13 wie EU-Standard)
- Eltern-Einwilligung erforderlich: Für Nutzer unter 16 Jahren müssen Eltern zustimmen
- Altersverifikation: Websites müssen zumindest versuchen, das Alter zu überprüfen
- Praktische Umsetzung: Meistens durch "Bestätigung, dass Sie 16+ Jahre alt sind" Checkbox
7. Vergleichstabelle: Einwilligung vs. Legale Grundlagen
| Datenverarbeitung | Einwilligung erforderlich? | Alternative Rechtsgrundlagen | Technische Umsetzung |
|---|---|---|---|
| Analytik-Cookies (Google Analytics) | Ja (Art. 7 DSGVO) | Nur mit robust anonymisierten Daten ohne Consent | Cookie Banner mit Opt-In |
| Marketing-Cookies (Retargeting) | Ja (Art. 7 DSGVO) | Keine praktische Alternative | Separate Marketing-Checkbox |
| Essentiell-Cookies (Session, CSRF) | Nein | Art. 6 Abs. 1 b) DSGVO (Vertrag) | Können ohne Consent gesetzt werden |
| Newsletter-Abonnement | Ja (Double-Opt-In empfohlen) | Keine praktikable Alternative | Bestätigung-Link per E-Mail |
| Kundendaten für Order-Processing | Nein | Art. 6 Abs. 1 b) DSGVO (Vertrag) | Nicht verhinderbar bei Kauf |
| Profilierung/Personalisierung | Ja (meistens) | Ggf. legitimes Interesse mit Balancing | Klare Erklärung + Zustimmung |
8. Consent-Management-Plattformen (CMP)
| Lösung | Gebühren | DSGVO-Compliance | Features |
|---|---|---|---|
| Usercentrics | 200-1000 EUR/Monat | ✓ Zertifiziert | Cookie-Scanner, Auto-Blocking, Multi-Region |
| Cookiebot (Cybot) | 150-800 EUR/Monat | ✓ Zertifiziert | Auto-Detection, IAB TCF, GDPR-ready |
| Borlabs Cookie | 99-249 EUR/Jahr (Lizenz) | ✓ DSGVO-konform | WordPress-Plugin, einfache Bedienung |
| OneTrust | 500-5000 EUR/Monat | ✓ Enterprise | IAB TCF 2.0, Global Privacy Control, Governance |
| Open-Source (osano, CMPliance) | Kostenlos (Hosting selbst) | Depends auf Implementation | Flexible, aber aufwändig |
9. Cookie-Banner Checkliste für DSGVO-Compliance
| Element | Status | Anmerkungen |
|---|---|---|
| Banner ist sichtbar und nicht zu verstecken | ☐ Ja | Muss sofort beim Laden sichtbar sein |
| Separate Checkboxen pro Cookie-Kategorie | ☐ Ja | Nicht eine große "Alles akzeptieren" Box |
| Keine vorgefüllten Checkboxen | ☐ Ja | Alle Checkboxen müssen leer sein |
| "Alles ablehnen" und "Ausgewählte akzeptieren" Button gleich prominent wie "Alle akzeptieren" | ☐ Ja | Keine versteckten Ablehnung-Buttons |
| Link zur Datenschutzerklärung | ☐ Ja | Muss leicht erreichbar sein |
| Essentiell-Cookies sind automatisch aktiviert (nicht Opt-Out) | ☐ Ja | Nur für wirklich notwendige Cookies |
| Einwilligung wird vor der Verarbeitung erhoben | ☐ Ja | Tracking-Scripts vor Consent ausblenden |
| Withdrawal-Möglichkeit (z.B. im Footer) | ☐ Ja | Nutzer können Consent leicht zurückziehen |
| Timestamp + Audit Log gespeichert | ☐ Ja | Nachweis für Compliance-Audits |
10. A/B Testing und Consent Rates
Unternehmen dürfen ihre Cookie-Banner optimieren, aber nur im Rahmen von DSGVO-Compliance:
- Erlaubt: Unterschiedliche Button-Farben testen, verschiedene Texte testen, Position testen
- Nicht erlaubt: "Alles akzeptieren" Button mit dunkelgrünem, "Alles ablehnen" mit grauem Design (Nudging)
- Nicht erlaubt: "Alles ablehnen" tiefer verstecken
- Nicht erlaubt: Countdown-Timer ("In 10 Sekunden automatisch akzeptiert")
Das BGH und die Datenschutzbehörden handhaben dies streng. Die EuGH-Urteilssprechung (Planet49-Fall) und die Updates der EDPB-Guidelines sind klar: Jedes "Dark Pattern" ist untersagt.
11. Aufzeichnungspflichten für Einwilligungen
| Was muss dokumentiert werden? | Aufbewahrungsfrist | Wer hat Zugriff? |
|---|---|---|
| Timestamp der Einwilligung | Mind. 3 Jahre | Datenschutzbeauftragter, Audit-Team |
| Welche Zwecke wurden akzeptiert/abgelehnt | Mind. 3 Jahre | Datenschutzbeauftragter, Audit-Team |
| Version der Consent-Erklärung | Mind. 3 Jahre | Datenschutzbeauftragter, Audit-Team |
| IP-Adresse (gehashed) | Mind. 1 Jahr | IT-Security |
| Rückzug-Informationen | Mind. 3 Jahre | Datenschutzbeauftragter, Audit-Team |
12. Verwandte Dokumentationen
- 📖 Cookie-Banner-Pflicht – Wann notwendig?
- 📖 DSGVO Website-Checkliste 2026
- 📖 DSGVO Betroffenenrechte technisch umsetzen
- 📖 Datenschutzerklärung erstellen 2026
- 🔧 Enjyn Crawler – Website auf Sicherheit prüfen
Zuletzt aktualisiert: April 2026 | Rechtsstand: DSGVO (EU 2016/679), BDSG (2018), EDPB-Guidelines | Diese Informationen stellen keine Rechtsberatung dar. Konsultieren Sie bei kritischen Fragen einen Datenschutzanwalt.