Background Image
10.10.2024, Kai Gertz

Externe Inhalte DSGVO-konform einbinden

Externe Inhalte dürfen nur mit Zustimmung der Benutzer geladen werden. Wir zeigen, wie ein Teaser für noch blockierte Inhalte aussehen könnte.

Externe, eingebettete Inhalte (YouTube, Instagram, LinkedIn,..) dürfen streng genommen laut DSGVO erst nach der Einwilligung der Benutzer geladen und angezeigt werden. Das hat den Hintergrund, dass bereits beim Laden die IP-Adresse des Benutzers übertragen wird – die nach Richtlinie der europäischen Kommission zu den personenbezogen Daten gehört, wie auch hier beim Consent Management beschrieben.

Ein Platzhalter für (noch) blockierte Inhalte

Aber wie kann mit dieser Situation sinnvoll umgegangen werden? Die Inhalte einfach auszulassen, würde u.U. eine deutliche Verschlechterung der Inhalte bedeuten und die Leser könnten wichtige Zusammenhänge vermissen. Den Benutzern einen Hinweis auf die notwendige Zustimmung im Consent Management Dialog und einen Link dorthin zu präsentieren wäre möglich, aber störend – und würde unnötig den Lesefluss unterbrechen. 

Die beste Lösung ist wohl, einen Platzhalter anzuzeigen, der den Benutzern erklärt, dass an dieser Stelle eigentlich ein Inhalt zu sehen sein sollte, der jedoch einer Einwilligung Bedarf:

Screenshot einer Website mit einem externen eingebetteten Inhalt, der noch die Zustimmung des Benutzers erfordert.

(Schematische Darstellung) Platzhalter für einen externen Inhalt, in dessen Anzeige der Benutzer erst noch einwilligen muss. Statt den Benutzer zum Consent Management Dialog umzuleiten, kann hier direkt per Knopfdruck die Zustimmung gegeben werden.

Solche Platzhalter begegnen einem ab und zu im Web und man kann sie prinzipiell für jede Consent Management Plattform entwickeln, die sich per JavaScript API ansprechen lassen. Wir bei Tojio verwenden dafür meist Klaro, prinzipiell gibt es aber eine Vielfalt an denkbaren Projekten, die sich dafür einsetzen lassen:

Der Button im Platzhalter ist dann äquivalent zum Switch im Consent Management Dialog. Nur  muss eben nicht der Dialog geöffnet, der Schalter umgelegt und der Dialog gespeichert / beendet werden. Die aktualisierten Präferenzen können hier nun gespeichert und der externe Inhalt geladen werden. 

Mit den bisherigen Ansätzen müsste nun die Seite im Normalfall neu geladen werden und statt des Platzhalters muss der Server den Einbettungscode für den externen Inhalt rendern.

In den folgenden Abschnitten wird ein Ansatz vorgestellt, der auf dieses Neuladen verzichten kann und eine bessere User experience (UX) bietet. Darüber hinaus soll dieser Ansatz generisch sein, d.h. nicht auf eine bestimmte Consent Management Platform zugeschnitten sein. 

Ein Custom Element als "Versteck"

Eine Idee, die teilweise aus der Diskussion zum Consent Management in Drupal Starshot stammt, ist einen solchen Platzhalter als Custom Element (bzw. Web Component) zu realisieren: das Custom Element umschließt und versteckt den eigentlichen Inhalt, solange es keine Einwilligung des Benutzers gibt, ihn anzuzeigen. Diese Lösung könnte dabei:

  • unabhängig von Drupal auch in statischen Websites oder in Verbindung mit beliebigen Frontend-Frameworks (React, Vue,..) funktionieren
  • mit nahezu beliebigen Consent Management Plattformen (s.o.) zusammenarbeiten 

Das Umschließen des externen Inhalts (der selbst noch in einem HTML-Kommentar steckt und daher inaktiv ist) hat den Vorteil, dass nicht die ganze Seite neu geladen werden muss. Lediglich der Platzhalter verschwindet und überlässt den Raum dem nun aktivierten, externen Inhalt. 

Die Platzhalter-Komponente

Die Platzhalter-Komponente wird einfach als Wrapper um den eigentlichen Inhalt gelegt, der zudem in einen HTML-Kommentar eingeschlossen wird (selbst wenn er das nicht wäre, bliebe der Inhalt dennoch verborgen, denn die Komponente zeigt nach ihrem Einsetzen nach außen hin nur die Inhalte ihrer shadow root, nicht aber die Kind-Elemente, die sie im DOM-Baum hat).

Über Attribute muss Folgendes der Platzhalter-Komponente angegeben werden:

  • die service-id (so wie die Consent Management Plattform sie verwendet),
  • Name des Dienstes,
  • Beschreibung des Inhaltes zur Anzeige in der Vorschau 
  • und (optional) die aspect-ratio

Die Angabe des Seitenverhältnisses ist zwar technisch unnötig, aber sie hilft, Verschiebungen im Layout zu verhindern, wenn statt der Vorschau der echte Inhalt geladen wird. Das ermöglicht einen visuell glatteren Übergang zum echten Inhalt. Hier im Beispiel sind einfach die Pixelwerte width/height angegeben, wie sie der Container des echten Inhalts vorgibt.

<consent-required 
  service="video" 
  service-name="External video on YouTube/Vimeo" 
  content-description="What is the Drupal Starshot Initiative?" 
  aspect-ratio="903/363">
  
  <!--
    ... video embed code here ...
    ... could be anything else, too ..
  -->
      
</consent-required>

Die Kommunikation zwischen Consent Management und der Komponente

Was noch fehlt, ist die Kommunikations-Schicht, die zwischen der jeweils verwendeten und schon vorhandenen Consent Management Plattform und der Platzhalter-Komponente vermittelt. Wenn in der Consent Management Plattform registriert wird, dass der Benutzer Dienst XY aktiviert hat, soll das an alle interessierten Stellen weitergegeben werden – auch an unsere Platzhalter-Komponente. Die wiederum kann dann den Platzhalter gegen den echten Inhalt eintauschen und alle externen Medien können geladen werden.

Andersherum gilt: wenn der Button "Inhalte laden" im Platzhalter geklickt wird (der ja äquivalent zum aktivieren des entsprechenden Dienstes im Consent Management Plattform sein soll, nur eben auf dem kürzesten Weg), dann muss das der Consent Management Plattform je nach Maßgabe ihrer API mitgeteilt werden, sei es durch das Feuern eines Events oder einen direkten Funktionsaufruf.  

Für beide Richtungen der Kommunikation könnte ein Helferobjekt in Javascript geschrieben werden (ein Behavior in Drupal). Oder – hier unser Ansatz – die Funktionalität wird in einer weiteren Komponente definiert, die wiederum als Wrapper für die Platzhalter-Komponente fungiert. Die Struktur würde insgesamt dann so aussehen: 

<cmpname-consent-required>
  <consent-required 
  	service="video" 
  	service-name="External video on YouTube/Vimeo" 
  	content-description="What is the Drupal Starshot Initiative?" 
  	aspect-ratio="903/363">
  	
    <!--
    	<iframe src="https://xyz..." 
            width="640" 
            height="360" 
            loading="lazy" 
            class="media-oembed-content"
            title="What is the Drupal Starshot Initiative?">
        </iframe>
    -->
        
  </consent-required>
</cmpname-consent-required>

Verwendung der Komponente mit Drupal und Klaro

In Drupal ist die Komponente Bestandteil des Themes. Dort wird sie mit dem üblichen Mechanismus als Library in der Datei theme.libraries.yml definiert (sie könnte auch noch bequemer als Single Directory Component verwendet werden, aber das ist Thema eines weiteren Blogartikels 😀 ...

consent-required:
  js:
    components/organisms/consent-required/consent-required.js: {}
    components/organisms/consent-required/adapters/klaro-consent-required.js: {}
  css:
    theme:
      components/organisms/consent-required/consent-required.css: {}

Dann muss nur noch das Template für den Medien-Typ "Remote Video" abgeändert werden, so dass:

  • die library aktiviert wird wenn dieses Template verwendet wird
  • die Komponente um den Inhalt gelegt wird
<div{{ attributes.addClass('media-type--' ~ media.bundle() ~ ' view-mode--' ~ view_mode ~ ' mid-' ~ media.id() ~ ' media-lang-' ~ media.field_media_document.langcode ) }}>
  {{ title_suffix.contextual_links }}
  {{ attach_library('soh/consent-required') }}
  <klaro-consent-required>
    <consent-required
      service="youtube"
      service-name="Video auf YouTube"
      aspect-ratio="770/433"
      aspect-ratio-above="625"
      content-description="Video: {{ media.label() }}"
      agree-label="{{ 'Load content from YouTube' | t }}"
      consent-required-text="{{ 'This video is hosted on YouTube. By clicking on the button below, you consent to use the YouTube service. Please note that personal data may be transmitted to YouTube. For more information, see our privacy policy.'|t }}"
    >
      <!--{{ content.field_media_oembed_video.0 }}-->
    </consent-required>
  </klaro-consent-required>
</div>

Die Komponente im produktiven Einsatz

Die Web Component <consent-required> ist im Einsatz z.B. im Jahresbericht von Hoffnungszeichen e.V. – sie ist aktiv, solange Benutzer keine Zustimmung zu externen Inhalten von YouTube gegeben haben. Analog dazu wird sie für Google Maps eingesetzt bei der Startseite der NGO:

Screenshot der Seite &quot;Jahresbericht&quot; von Hoffnungszeichen mit einem DSGVO-konformen Teaser für Inhalte von YouTube
Screenshot der Startseite von Hoffnungszeichen e.V.

Das Custom Element <consent-required> ist freie Software, ebenso wie die Adapter für verschiedene Consent Management Platforms (derzeit Klaro und CookiesJSR) - falls jemand eigene Adapter baut: lasst es uns wissen, wir integrieren sie gern.