iframe-Blocker

Zwei Klicks für mehr Datenschutz?

1. Hintergrund

Mmmh. Die DSGVO ist nun schon recht lange in Kraft, trotzdem haben noch nicht alle CMS entspr. Plugins zum Blocken von Drittanbieter-Content.

Für WordPress gibt es diverse Möglichkeiten (ich habe zeitweise – momentan wieder – BorlabsCookie eingesetzt, andere Vorschläge u.a. hier), aber für andere CMS oder nicht-CMS-Seiten gibt es noch keine weit verbreiteten Lösungen. Auch für LMS wie Moodle stehen – trotz aktiver Community und umfangreicher Plugin-Datenbank – keine Lösungen bereit…

Das ist ziemlich "unschön", da hier diverse (personenbezogene) Informationen von Seitenbesuchenden abgefischt und Cookies gesetzt werden können. Eine Folge ist, dass es zwingend zu unvollständigen Datenschutzhinweisen kommen muss.

Exkurs: Meine rechtliche Laienmeinung

Die Seitenbetreibenden haben gem. Art. 13 DSGVO die Pflicht, die Betroffenen "zum Zeitpunkt der Erhebung dieser Daten" darüber zu informieren, dass und wie personenbezogene Daten verarbeitet werden. So weit, so einfach: Beim ersten Besuch der Webseite wird ein Overlay (nein, nicht so ein klitzekleines Cookie-Banner!) eingeblendet, welches die Nutzung der Seite stark beeinträchtigt. Hierin müssen ein Link zur Datenschutzerklärung und mind. ein Button angezeigt werden, mit dem die Betroffenen der Verarbeitung der Daten in der beschriebenen Weise zustimmen.

Allerdings sollen die Betroffenen nach Art. 13 (1) lit. c.-e. DSGVO auch über Verarbeitungszweck, Rechtsgrundlage, berechtigte Interessen der Verantwortlichen und über Empfänger bei Datenweitergabe informieren, außerdem nach Art. 13 (2) lit. a. DSGVO über die Speicherdauer informiert werden. Die oft (z.B. bei eingebetteten YouTube Videos) in den Datenschutzerklärungen auffindbaren Formulierungen wie

"Eingebettete Videos werden von YouTube, LLC, 901 Cherry Ave., San Bruno, CA 94066, USA bereitgestellt. Beim Abspielen wird eine Verbindung zu den Servern von YouTube hergestellt. Dabei wird YouTube mitgeteilt, welche Seiten Sie besuchen. YouTube kann Ihr Surfverhalten evtl. Ihnen persönlich oder Ihrem YouTube-Benutzendenkonto zuordnen. Außerdem werden von YouTube Cookies und weitere Methoden eingesetzt, die evtl. Hinweise über Ihr Nutzungsverhalten sammeln. Weitere Informationen zur Datenverarbeitung bei YouTube finden Sie in der Datenschutzerklärung des Anbieters unter https://www.google.de/intl/de/policies/privacy/."

beinhalten zwar Verantwortliche und Verarbeitungsbeschreibung, allerdings keine detaillierten Angaben zu z.B. Rechtsgrundlage, Zweck und Speicherdauer. Das ist mindestens unvollständig, kann aber auch nicht viel besser sein, da viele relevanten Informationen von YouTube wenig transparent (als Geschäftsgeheimnis?) behandelt werden. Zwar beinhalten die verlinkten Datenschutzhinweise von (in diesem Fall) Google "Hinweise" (≠ detaillierte Informationen) zu Datenkategorien, Verarbeitungszweck und Speicherdauer. Ich bin mir daher nicht so sicher, ob damit der-/diejenige Seitenbetreibende, welche/r das YouTube-Video einbettet, seiner Informationspflicht gegenüber den Besuchenden seiner Seite ausreichend nachkommt…

Daher habe ich immer mal wieder nach Lösungen für die Blockade von iframes gesucht – und am Ende selber eine gebaut:

Die iframes werden nur teilweise geladen und senden keine Anfrage an die Server Dritter, in einem Hinweistext wird auf die (immer noch unvollständige (s.o.)) Datenschutzerklärung verwiesen. Dadurch hat der Besuchende nun die theoretische Möglichkeit, sich zuerst über die Datenverarbeitung bei dem Anbieter des eingebetteten Inhalts zu informieren und trifft mit dem Anklicken eine willentliche Entscheidung (= Einwilligung gem. Art. 6 (1) lit. a) DSGVO, wobei die Ansprüche an eine Einwilligung (vgl. Art. 7 DSGVO) wohl nich alle erfüllt werden, scheint mir?). Aber dieser erzwungene zweite Klick ist sicherlich besser, als Seitenbesuchende der Informationsweitergabe an Dritte einfach unkommentiert auszusetzen. Denn wenn ein iframe erst einmal geladen wird, ist ganz schön was los: Da werden Netzwerkverbindungen zu diversen "Dritten" aufgebaut, lustig Cookies gesetzt und sicherlich noch weitere informationen (User Agents, gerätespezifische "Fingerabdrücke") übertragen.

Das Video unten zeigt, was im Hintergrund passiert, wenn ein iframe geladen wird 😮

2. Vorgehen (für YouTube und Vimeo)

2.1 iframes nummerieren, mit Klassen versehen und Attribute ändern

Um den iframe anzusprechen und später "entsperren" zu können, benötigt er eine eindeutige Klasse oder ID. Für den Fall, dass eine Seite mehrere iframes enthält, geht das am einfachsten durch das Anlegen einer Variable i = 1, das Anwenden der Funktion auf alle iframes (via .each(), Doku) und das Hochzählen am Ende der Funktion durch i++.

Die iframes von YouTube und Vimeo findet man mit dem Selektor $('iframe[src*="youtu"],iframe[src*="vimeo"]'), die Platzhalter mit Wildcard (*, Doku) erlauben eine generelle Erfassung aller entsprechenden iframes, ohne die Video-URLs genau zu kennen. Die Kürzung auf "youtu" statt "youtube" ist dem hauseigenen URL-Shortener-Dienst youtu.be geschuldet 🙂 Um den iframe einfacher ansprechen zu können, schiebe ich das jeweils selektierte Element mit = $(this) in die Variable video.

Dann vergebe ich via .addClass() (Doku) die Klasse 'video_iframenr'+i, worurch – wenn mehrere iframes vorhanden – diese durchnummeriert werden.

Jeder iframe hat normalerweise eine src-Angabe, woher sonst sollte bekannt sein, welche Inhalte in den iframes angezeigt werden sollen. Hier kann man nun ansetzen, und den Ladevorgang der Inhalte zu manipulieren, indem man das Attribut (.attr, Doku) data-src anlegt und mit dem momentanen Inhalt des src-Attributes befüllt, welches man danach löschen kann (.removeAttr, Doku).

Das Skript sieht also bis hierhin so aus:

jQuery

$(document).ready(function(){
   var i = 1;
   $('iframe[src*="youtu"],iframe[src*="vimeo"]').each(function(){
      var video = $(this);
      video.addClass('video_iframenr'+i).attr('data-src',video.attr('src')).removeAttr('src');
      i++;
   });
});

Aus z.B.

HTML

<iframe src="https://www.youtube.com/embed/arPqFrpObtg" ></iframe>

wird so

HTML

<iframe class="video_iframenr1" data-src="https://www.youtube.com/embed/arPqFrpObtg" ></iframe>

Dieser iframe hat keinen Inhalt, da er kein gültiges src-Attribut hat. Es kann also auch keine Verbindung mit YouTube- oder Vimeo-Servern aufgebaut werden.

Nicht ganz einschätzen kann ich das Timing. $(document).ready(); sollte eigentlich bereits beim abgeschlossenen Ladevorgangs des DOM abgefeuert werden, also wenn die iframe-Inhalte noch nicht geladen sind. Zu diesem Zeitpunkt sollten also noch keine Anfragen an den Anbieter herausgegangen sein und keine Cookies des Anbieters angekommen sein?

2.2 Overlay basteln

Als nächstes benötige ich ein Overlay, der die entsprechenden Infos und (später) den "Entsperr"-Button enthält. Dafür nutze ich .wrap() (Doku), um den iframe mit einem div mit der Klasse video_iframeoverlay zu umschließen. Dann kann ich dieses umschließende div via .parent() (Doku) selektieren und mit .append() (Doku) einen Textknoten für meinen Text einbauen.

In diesem Hinweistext würde ich gerne den Link zum Video anbieten. Der steht natürlich momentan im data-src-Attribut, daher lege ich diesen in der Variable sourceLink ab und bereinige diesen via .replace() um den URL-Bestandteil -nocookie. Der ist in den Fällen vorhanden, wenn ein YouTube-Embed-Code mit dem "erweiterten Datenschutzmodus" generiert wurde; er ist bei einer Verlinkung aber ungünstig, da das Linkziel nicht gefunden wird. Damit der Link nicht zu lang wird, kann man ihn in einer weiteren Variable (hier: sourceLinkShort) auf 30 Zeichen gekürzt mit einem "…" am Ende ablegen. Diese beiden Variablen werden dann im Hinweistext nach dem Strickmuster <a href="[sourceLink]">[sourceLinkShort]</a> genutzt. Den eigentlichen Hinweistext formuliere ich später noch ausführlich 🙂

jQuery

      ...

      var sourceLink = video.attr('data-src').replace('-nocookie', '');
      var sourceLinkShort = jQuery.trim(sourceLink).substring(0, 30) + "...";
      video.wrap('<div class="video_iframeoverlay"></div>');
      video.parent('.video_iframeoverlay').append('<p>Hinweistext mit Link <a rel="noopener" target="_blank" href="' + sourceLink + '">' + sourceLinkShort + '</a>.</p>');

      ...

Aus z.B.

HTML

<iframe src="https://www.youtube.com/embed/arPqFrpObtg" ></iframe>

wird so

HTML

<div class="video_iframeoverlay">
   <iframe class="video_iframenr1" data-src="https://www.youtube.com/embed/arPqFrpObtg" ></iframe>
   <p>Hinweistext mit Link <a rel="noopener" target="_blank" href="https://www.youtube.com/embed/arPqFrpObtg">https://www.youtube.com/embed/...</a>.</p>
</div>

2.3 Unlock-Button

Um den eigentlichen iframe-Inhalt nun per Knopfdruck nachladen zu können, benötigt man einen Button (bzw. einen später via CSS als Button gestalteten Link), mit dem das data-src-Attribut wieder zum src-Attribut gemacht wird. Etwas kniffelig ist, dass jeder Unlock-Button ja nur "seinen" iframe (und nicht etwa alle auf der Seite) entsperren soll. Dafür machen wir uns wieder die durchnummerierte iframe-Nummer bzw. die entsprechend nummerierte Klasse zunutze. Also füge ich folgenden Link zum Hinweistext (= innerhalb von video.parent('.video_iframeoverlay').append('<p>...</p>'); hinzu:

<a id="unlockiframe" class="video_iframenr' + i + '">Inhalt laden</a></p>');

So bekommt auch jeder dieser Links/Buttons die gleiche Klasse wir der iframe, zu dem er gehört. Nun muss das Ensperren gebastelt werden:

Jedes Element mit der ID unlockiframe und einer passenden Klasse soll .on() .click() (Doku, Doku) den dazugehörigen iframe entsperren. Dafür schiebe ich die Klasse des Buttons in die Variable relatediframe, und schreibe bei dem iframe mit der selben Klasse ($('iframe.' + relatediframe)) das momentane data-src-Attribut zurück in das src-Attribut. Das data-src-Attribut kann danach gelöscht werden.

Nun muss noch das Overlay entfernt werden: Dafür wird der $('iframe.' + relatediframe) mit .unwrap() (Doku) von dem umschließenden div befreit und der Hinweistext (der sich in einem einzigen p-Tag befinden sollte!) via $('iframe.' + relatediframe + ' + p') (ist ja ein Folge-Element des iframes) selektiert und entfernt (.remove(), Doku):

jQuery

$('#unlockiframe[class*=video_iframenr]').on('click', function () {
   var relatediframe = $(this).attr('class');
   $('iframe.'+relatediframe).attr('src',$('iframe.'+relatediframe).attr('data-src'));
   $('iframe.'+relatediframe).removeAttr('data-src');
   $('iframe.'+relatediframe).unwrap();
   $('iframe.'+relatediframe+' + p').remove();
});

3. Fertig 🙂

Eine kommentierte Gesamtversion des Skriptes incl. m.E. sinnvollem Hinweistext sieht dann so aus:

jQuery

// iframe Block

$(document).ready(function(){

   // Fuer den Fall, dass mehrere iframes vorhanden sind i zum hochzaehlen anlegen,
   var i = 1;

   // bei jedem YT- und Vimeo-iframe (Filter auch fuer youtu.be)
   $('iframe[src*="youtu"],iframe[src*="vimeo"]').each(function(){

      // iframe als Variable ablegen,
      var video = $(this);

      // dem iframe eine nummerierte Klasse geben, das data-src mit src-Attribut befuellen und src loeschen.
      video.addClass('video_iframenr'+i).attr('data-src',video.attr('src')).removeAttr('src');

      // Links fuer das Overlay generieren, nocookie aus der URL entfernen, auf 30 Zeichen kuerzen
      var sourceLink = video.attr('data-src').replace('-nocookie', '');
      var sourceLinkShort = jQuery.trim(sourceLink).substring(0, 30) + "...";

      // Ein Overlay mit Text und Unlock-Button (mit gleicher Klasse wie der iframe) einblenden
      video.wrap('<div class="video_iframeoverlay"></div>');
      video.parent('.video_iframeoverlay').append('<p>Hier wurde ein einegebetteter Medieninhalt (<a rel="noopener" target="_blank" href="' + sourceLink + '">' + sourceLinkShort + '</a>) blockiert. Beim Laden oder Abspielen wird eine Verbindung zu den Servern des Anbieters hergestellt. Dabei k&ouml;nnen dem Anbieter personenbezogene Daten mitgeteilt werden. Weitere Informationen finden Sie in unseren <a href="/datenschutzerklaerung" rel="noopener" target="_blank" title="Datenschutzerkl&auml;rung">Datenschutzhinweisen</a> im Abschnitt "2.5 Eingebettete Medieninhalte und Dienste von anderen Webseiten".<a id="unlockiframe" class="video_iframenr' + i + '">Inhalt laden</a></p>');

      // Hochzaehlen, falls mehrere iframes vorhanden sind.
      i++;
   });

   // Bei Klick auf einen Unlock-Button ...
   $('#unlockiframe[class*=video_iframenr]').on('click', function () {

      // ...den Klassennamen des Buttons (= Klassenname des blockierten iframes) auslesen ...
      var relatediframe = $(this).attr('class');

      // ...und beim entspr. iframe data-src in src zurueckwandeln und data-src loeschen.
      $('iframe.'+relatediframe).attr('src',$('iframe.'+relatediframe).attr('data-src'));
      $('iframe.'+relatediframe).removeAttr('data-src');

      // Am Ende das Overlay (unwrap) und Text (remove) loeschen.
      $('iframe.'+relatediframe).unwrap().siblings('p').remove();
   });
});

Das kann man sicherlich optimieren und besser strukturieren?
Tipps gerne in die Kommentare! Danke!

Das ganze benötigt nun noch ein entsprechendes

4. Design

Alle iframes, egal ob src oder data-src auf Youtube oder Vimeo verweisen, haben eine Breite von 100%, eine maximale (natürlich von Seitendesign bzw. Theme abhängig zu wählende) Breite (hier: 1000px) und eine zu der max. Breite passende Höhe von 562px (das gewünschte Seitenverhältnis von 16:9 ergibt 1000/16=562 😉 ). Die !important-Angaben überschreiben die evtl. im iframe-Code inline vorhandenen Größenangaben.

CSS

iframe[src*="youtu"], iframe[src*="vimeo"],
iframe[data-src*="youtu"], iframe[data-src*="vimeo"] {
   width: 100% !important;
   max-width: 1000px;
   height: 562px !important;
}

Das Overlay und die Zentrierung des Hinweistextes mache ich via Spalten-Flexboxing, der Farbverlauf ist natürlich Geschmackssache 🙂

CSS

.video_iframeoverlay {
   width: 100% !important;
   max-width: 1000px;
   height: 562px !important;
   position:relative;
   background-image: linear-gradient(170deg,rgba(100, 0, 0,0.25),rgba(0,0,0,0.05) 70%);
   position:relative;
    -webkit-display:flex;
       -moz-display:flex;
        -ms-display:flex;
            display:flex;
    -webkit-flex-direction:column;
       -moz-flex-direction:column;
        -ms-flex-direction:column;
            flex-direction:column;
    -webkit-justify-content:center;
       -moz-justify-content:center;
        -ms-justify-content:center;
            justify-content:center;
}

Text und Button werden wie folgt positioniert und gestaltet:

CSS

.video_iframeoverlay p {
   padding: 0 1.5rem;
   text-align: center;
   margin: 0;
   z-index: 2;
   position:absolute;
}
.video_iframeoverlay #unlockiframe {
   background: #bf304a;
   color: #fff;
   padding: 0.5rem;
   border-radius: 0.5rem;
   cursor: pointer;
   display: block;
   margin: 0.5rem auto 0;
   width: 12rem;
   max-width:90%;
   z-index: 2;
}
.video_iframeoverlay #unlockiframe:hover {
   background:#30a3bf;
}

Wer will, kann z.B. via .video_iframeoverlay::before noch eine Grafik oder FontAwesome-Icons o.ä. hinein basteln.

  1. Selber testen? Hier klicken!
  2. Skript / Design herunterladen? Die Dateien videoblock.js und videoblock.css müssen im <head> einer HTML-Datei/-Seite eingebunden werden, ebenso wie eine Kopie oder CDN-Version von jQuery.
  3. Komplettpaket? Das Ganze gibt es hier mit relativen Links, so dass es auch lokal funktionieren sollte: Download

5. Funktionierts?

Diverse Tests haben weder einen Verbindungsaufbau mit YouTube- bzw. Vimeo-Servern noch deren Cookies nachweisen können. Das ganze habe ich mal versucht, in einem Video aufzuzeichnen:

Test des iframe-Blockers im Video

Getestet in Firefox, Chrome, Edge, Internet Explorer (v.11 🙂 ), jew. nur unter Windows als OS.

6. Disclaimer und Hinweise

  • Ob das wirklich wirklich funktioniert, auch auf Mobilgeräten, unter MacOS und Linux,
  • ob das die Ansprüche der DSGVO (mehr) erfüllt,
  • ob das überhaupt notwendig ist,

weiß ich alles nicht so genau. Es scheint für meine Ansprüche aber ausreichend zu funktionieren. Trotzdem erlaube ich mir folgenden Disclaimer:

Ich bin kein Web-Entwickler, sondern Bastler aus dem #TeamHalbwissen. Die Nutzung und Weiterentwicklung ist daher "auf eigene Gefahr". Ob dieses Skript tut, was es soll und ob es überhaupt notwendig ist, kann ich nicht abschließend beurteilen.

Viel Spaß beim Basteln! 🙂 Hinweise zu Fehlern oder möglichen Verbesserungen nehme ich sehr gerne entgegen.

"iframe-Blocker" 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.


Deprecated: Die Datei Theme ohne comments.php ist seit Version 3.0.0 veraltet und es ist keine Alternative verfügbar. Bitte füge ein comments.php-Template zu deinem Theme hinzu. in /home/medienma/public_html/wp-includes/functions.php on line 5653

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert


Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/medienma/public_html/wp-content/plugins/simple-lightbox/includes/class.utilities.php on line 545