Wie angekündigt, hier ein dritter Teil der Serie zur DSGVO. Die anderen beiden gibt es hier (Teil 1) und hier (Teil 2). Folgende Modifikationen und Einstellungen habe ich vorgenommen:
Inhalt
1. WordPress-Funktionen
Ich empfehle ein eigenes (Child-) Theme, damit alle Änderungen update-sicher sind und nicht bei jedem Theme-Update übergebügelt werden. Grundsätzlich können alle folgenden Änderungen direkt in die functions.php
(liegt im Ordner [WordPress-Verzeichnis]/wp-content/themes/[aktivesTheme]/) eingefügt werden:
1.1 Checkbox ins Kommentare-Formular einbasteln
Ich gehe von einem mehr oder weniger standardmäßigem Kommentar-Formular (z.B. via <?php comment_form()?>
innerhalb der Datei comments.php
) aus. Dann kann man recht einfach eine Funktion schreiben, die via echo
html-Elemente in das Formular einfügt. Die Funktion wird via add_action
(Doku) an der Stelle comment_form_after_fields
eingehakt (s. Hooks). Um die Funktion auch aufzurufen, wenn der/die Benutzende eingeloggt ist, kann comment_form_logged_in_after
genutzt werden:
PHP / functions.php
// Checkbox für DS-Einwilligung ins Kommentarformular einfügen function mm_privacyconsent_field() { echo '<p class="privacyconsentheadline">Zustimmung zur Datenverarbeitung</p> <input id="privacyconsent" name="privacyconsent" type="checkbox" required="required" />'. '<label for="privacyconsent">' . __( 'Ich stimme der Verarbeitung der eingegebenen Daten im Sinne der <a target="_blank" href="/datenschutzerklaerung">Datenschutzerklärung</a> zu.*' ) . '</label>'; } // für eingeloggte Benutzende add_action( 'comment_form_logged_in_after', 'mm_privacyconsent_field' ); // für nicht-eingeloggte Benutzende add_action( 'comment_form_after_fields', 'mm_privacyconsent_field' );
Das injizierte HTML besteht aus einem Text (<p>
), der Checkbox (<input>
) und der Beschriftung (<label>
). Klassen und IDs für optionale CSS-Styles nicht vergessen! Die IDs des <input>
-Objektes ist darüber hinaus für die Zuordnung des <label>
notwendig.
Ergebnis:
Über das required="required"
ist das Feld automatisch ein Pflichtfeld. Um es "noch ein wenig verpflichtender" zu machen bzw. die Kommentierenden mit etwas mehr Nachdruck auf die Datenschutzerklärung aufmerksam zu machen, könnte man mittels jquery den Aktiv-/Inaktiv-Status des "Abschicken"-Buttons an diese Checkbox koppeln.
Dafür wird dem Button (hier: #comments input#submit
) standarmäßig die Eigenschaft (.prop()
, Doku) disabled
und auch (via .addClass()
, Doku) eine Klasse mit gleichem Namen gesetzt (für’s CSS, s.u.).
Dann wird an die Checkbox (hier: input#privacyconsent
) mittels Eventhandler (.change()
, Doku) eine Überprüfung (if($(this).is(":checked"))
) angebastelt, die sowohl die Eigenschaft als auch die Klasse disabled
je nach Check-Status der Checkbox "umschaltet":
jQuery
// DSGVO Checkbox bei Kommentaren $(document).ready(function(){ $('#comments input#submit').prop("disabled", true); $('#comments input#submit').addClass( 'disabled' ); $('input#privacyconsent').change(function(){ if($(this).is(":checked")) { $('#comments input#submit').prop("disabled", false); $('#comments input#submit').removeClass( 'disabled' ); } else { $('#comments input#submit').prop("disabled", true); $('#comments input#submit').addClass( 'disabled' ); } }); });
Der Klasse disabled
kann man dann einfach via CSS ein paar Styles (hier: Deckkraft und Cursor-Form) mitgeben:
CSS
#comments #submit.disabled { opacity: 0.5; cursor: not-allowed; }
Hier das Ergebnis:
Find ich gut. 🙂 – bekommt einen Haken ✔
1.2 IP von Kommentierenden nicht speichern …
Die nächste Baustelle bei den Kommentaren ist die Speicherung von IP-Adressen. Diese kann man ebenfalls mit einer Funktion in der functions.php
ändern, indem man an der Stelle pre_comment_user_ip
(Doku) die IP (Parameter $comment_author_ip
) mit "nichts" überschreibt:
php / functions.php
// Keine IP-Adressen von Kommentierenden speichern function mm_remove_comment_author_ip( $comment_author_ip ) { return ''; } add_filter( 'pre_comment_user_ip', 'mm_remove_comment_author_ip' );
Quellen u.a.: wp-ninjas.de | blogmojo.de
Ergebnis:
1.3 … oder zeitverzögert löschen
Wer nicht im Code herumpfuschen möchte, kann das Plugin Remove Comments IPs nutzen. Dort wird es auch im nächsten Release eine Funktion geben, um die Speicherdauer abweichend zur Voreinstellung (bisher: 60 Tage) einzustellen. Das ist für das Thema IP-Adresse zur Spam-Filterung nutzen recht wichtig. Die Version des Plugins von hier beinhaltet bereits den Filter remove_comment_ip_days_to_deletion
, ist aber noch kein offizielles Release.
Da ich die IP-Adresse für den Spamfilter (noch) nicht benötige, speichere ich auch keine IP-Adressen. Datenvermeidung und so 🙂
1.4 Bisherige IP-Adressen von Kommentaren entfernen
Die eventuell in der Datenbank vorhandenen IP-Adressen müssen entfernt werden. Dafür ist leider ein kleiner Datenbank-Eingriff notwendig. Mit dem SQL-Befehl
SQL
UPDATE wp_comments SET comment_author_IP = ' ';
kann man recht einfach alle IP-Adressen in der Datenbank löschen. Anleitungen u.a. auf wp-ninjas.de oder tantedine.de. Da ich mich entschlossen habe, alle "alten" Kommentare zu löschen, habe ich das allerdings gar nicht angewendet.
Das Thema IP-Adressen: ✔
1.5 User Agent nicht speichern
Nach dem gleichen Strickmuster wie das Überschreiben der IP-Adresse (s.o.) funktioniert das "nicht speichern" des User Agent. Lediglich die Stelle, an der der Hook einhakt (pre_comment_user_agent
, Doku) und der betroffene Parameter ($comment_agent
) sind andere:
php / functions.php
// Keinen User Agent von Kommentierenden speichern function mm_remove_comment_agent_string( $comment_agent ) { return ''; } add_filter( 'pre_comment_user_agent', 'mm_remove_comment_agent_string' );
Ergebnis:
Also auch hier mache ich erst mal einen Haken dran: ✔
1.6 Gravatare abschalten
Das ist einfach: Im Redaktionsbereich von WordPress gibt es unter > Einstellungen > Diskussion die Option "Avatare anzeigen". Häkchen entfernen, speichern, fertig:
Easy. ✔
1.7 Emojis abschalten
Hier müssen ebenfalls Funktionen in die functions.php
eingefügt werden:
php / functions.php
// Emojis deakivatieren function mm_disable_emojis() { remove_action( 'wp_head', 'print_emoji_detection_script', 7 ); remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ); remove_action( 'wp_print_styles', 'print_emoji_styles' ); remove_action( 'admin_print_styles', 'print_emoji_styles' ); remove_filter( 'the_content_feed', 'wp_staticize_emoji' ); remove_filter( 'comment_text_rss', 'wp_staticize_emoji' ); remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' ); add_filter( 'tiny_mce_plugins', 'mm_disable_emojis_tinymce' ); add_filter( 'wp_resource_hints', 'mm_disable_emojis_remove_dns_prefetch', 10, 2 ); } add_action( 'init', 'mm_disable_emojis' ); // Emoji-Plugin in TinyMCE deaktivieren function mm_disable_emojis_tinymce( $plugins ) { if ( is_array( $plugins ) ) { return array_diff( $plugins, array( 'wpemoji' ) ); } else { return array(); } } //Remove emoji CDN hostname from DNS prefetching hints. function mm_disable_emojis_remove_dns_prefetch( $urls, $relation_type ) { if ( 'dns-prefetch' == $relation_type ) { /** This filter is documented in wp-includes/formatting.php */ $emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/2/svg/' ); $urls = array_diff( $urls, array( $emoji_svg_url ) ); } return $urls; }
Quelle: kinsta.com
Ergebnis:
Die Wirksamkeit kann ich mit meinen beschränkten Mitteln nicht vollumfänglich testen. Allerdings wird das hier gezeigte Skript nicht mehr geladen, …
… das Skript und die Styles aus dem Header verschwinden, …
… und auf verschiedenen Geräten werden nun verschiedene (system-eigene?) Emojis angezeigt:
Das wirkt zumindest, als würde es wirken: ✔
2. Plugins
Ich setze drei Plugins mit "DSGVO-Bezug" ein:
Das Plugin Borlabs Cookie schlägt gleich zwei Fliegen mit einer Klappe:
Erstens die Opt-In-Funktion / das Cookie-Banner und die jederzeit von Betroffenen änderbaren Cookie-Einstellungen. Optionen (Texte, Cookie-Banner-Aussehen, -Platzierung, etc.) können variabel angepasst werden.
Zweitens bietet das Plugin die Option, Drittanbieter-Inhalte mit einer Zwei-Klick-Lösung zu blockieren und nur auf Wunsch nachzuladen. Das funktioniert ziemlich gut. Zusätzlich werden YouTube-Links automatisch mit dem Link zum "Erweiterten Datenschutzmodus" ersetzt.
Sollte einmal ein Drittinhalt nicht automatisch geblockt werden (z.B. die <blockquote>
-Embeds von Instagram, obwohl ich nicht weiß, ob hier überhaupt Daten ausgetauscht werden), können Shortcodes eingesetzt werden.
Borlabs Cookie schlägt mit 29,- € für einzelne Webseiten zu Buche. Find ich für den Funktionsumfang ok. Auch die 149,-€-Agenturversion (auf unbegrenzt vielen Kundenprojekten einsetzbar) finde ich preislich in Ordnung. Vor allem, wenn man bedenkt, dass die ePrivacy-Verordnung ja irgendwann kommt. Vielleicht jetzt schon mal kaufen, bevor bei dem dann einsetzenden Ansturm die Preise hochgehen?
Nachtrag:
Ich nutze für eine allgemeine Einwilligung in die Datenverarbeitung gem. Datenschutzerklärung nun "GDPR Cookie Consent". Das Blocken von Inhalten Dritter regele ich über eine Eigenentwicklung.
Cookie-Banner & Drittinhalte: ✔
Vor diesen Lösungen habe ich auch noch mit anderen Zwei-Klick-Ansätzen (Skripte und Plugins) experimentiert, das war aber immer entweder frickelig oder nicht verlässlich genug. Wer lieber ein anderes Plugin einsetzen oder selber basteln möchte, hier ein paar Anregungen:
- Plugin "Embed videos and respect privacy"
- Plugin "Lazy Load for Videos"
- Plugin "WP YouTube Lyte"
- Skript: DSGVO Video-Embed
- Zwei-Klick-Embed-Code-Generator von runamind.de
2.2 Kommentare-Abo-Plugin
Das Plugin Subscribe to Comments Reloaded (StCR) biete die Möglichkeit eines Double-Opt-Ins und einer eigenständigen Abonnement-Verwaltung. Auch hier sind viele Optionen und Texte konfigurierbar: Alle E-Mail-Autotexte, das Aussehen und der Funktionsumfang der Abo-Verwaltungsseite, Abo-Optionen (auch Autoren-Abos möglich) …
Mehr als genug Optionen für mich und ausreichend DSGVO-konform: Abonnement mit Double-Opt-In und Verwaltung durch die Benutzenden: ✔
2.3 Spamfilter-Plugin
Bei Antispam Bee werden in den Einstellungen alle datenschutzrelevanten Einstellungen gekennzeichnet, damit sie genauer betrachtet und deren Auswirkungen abgewogen werden können. Das sind vor allem die Überprüfung der Herkunft (via Geotargeting, Doku der Entwickler/innen hier) und der Sprache (via Google Translate, Doku der Entwickler/innen hier):
Da ich Google-Diensten (nicht für den Privatgebrauch, aber als Webseitenbetreiber bzgl. der Daten meiner Seitenbesuchenden) etwas skeptisch gegenüberstehe, lasse ich diese Sprachüberprüfung (vorerst) deaktiviert. Auch das Geotargeting lasse ich erst einmal aus, obwohl der genutzte Dienst ip2country an dieser Stelle eine weitere Speicherung und Verarbeitung der Daten ausschließt. Ich behalte mir allerdings – wie bereits an anderer Stelle erläutert – vor, diese Einstellungen anzupassen.
Akismet deaktiviert, Antispam Bee konfiguriert: ✔
3. Organisatorisches: ADV-Vertrag, Verfahrensverzeichnis, Datenschutzerklärung
Mein Hoster domainfactory Serverprofis GmbH bietet einen ADV-Vordruck im Kundenmenü (Nr. 16) Kundenmenü an. Ausgefüllt, unterschrieben, zurückgeschickt: ✔
Auch Verfahrensverzeichnis und Datenschutzerklärung waren nach dieser Artikelserie "nur" noch Schreibarbeit: Noch einmal fein säuberlich auflisten, in welchem Falle welche Daten zu welchem Zweck wie lange gespeichert werden. Eine Vorlage für das VVZ gibt es z.B. hier (LDI NRW): ✔
Meine frisch zusammengestellte Datenschutzerklärung findet man hier: ✔
4. Fazit
Ja, das war schon etwas Arbeit. Ich hoffe, ich hab an alles gedacht? Zumindest Untätigkeit sollte man mir nicht vorwerfen können. Dann mache ich jetzt mal – so einigermaßen DSGVO-konform – die Webseite wieder öffentlich zugänglich.
Stand: 18.07.2018, die DSGVO ist seit 54 Tagen in Anwendung 🙂
"Umsetzung der DSGVO" von Martin Smaxwil ist unter einer CC BY 4.0-Lizenz veröffentlicht.
Darüber hinausgehende Hinweise zu Bestandteilen wie Code Snippets u.ä. findet man hier.