Paint the Web - a micro-Blog in .md about Dev, Web and more

Flood\Component: Canal\Asset - Module GDPR

The Canal\Asset modules provide JS logic and Sass Styles for easier use of Canal's backend things.

With the GDPR module it implements basic compliance for handling cookies, social media embedding, saving custom privacy selections and more.

This module doesn't promise full compliance, every implementation should be checked with your lawyer before deployment.

We don't provide legal advice in this article, every statement is a suggestion with the best in mind but it doesn't need to be legally valid in the time/region you apply it.

More in Wikipedia.


Currently Platform Handlers are integrated:

  • Social
    • Facebook
    • Twitter
    • Instagram Post
  • Media/Fun
    • Giphy
    • Pinterest
    • Tumblr (def.)
    • 500px
  • Video
    • YouTube
    • Vimeo
  • Audio
    • Spotify
    • Deezer
  • Location Service
    • Google Maps
  • Dev. Pages
    • JSFiddle
    • SassMeister
    • CodePen
    • GitHub Gist

Features, Planned and Issues

Notation notice: gdpr.elem is a pseudocode map selector, [string] is an optional string, string is a required string.


  • add elements to be handled
  • callback based, can be added to a IntersectionObeserver/LazyLoader
  • easy to add new platforms
  • each embed type could be handled on it's own
  • a embed type has a family, grouping same embeds for autloading, user settings features...
  • autoload skips the barrier and directly loads the element
  • event classes for handling animations through CSS
  • prerendered says if the server already did output html, then it is applied
    • at the moment only true is supported, direct JS HTML generation will be added
  • uses data attr as config
    • data-attr is added as attribute to the generated element, special syntax see in Twig part
  • auto_check dispatches the acceptance of check for the privacy info of the element, after the first element has been loaded
  • auto_check_load dispatches the loading all element's of the same family, after the first element has been loaded
  • html html registry for JS generated barriers/loaders and more (TODO)


  • Cookie notice
  • Persistent/page-leave user settings
    • after one accept, accept all
    • after one accept, load all

Known Issues:

  • Tumblr has no matter how an iframe load error
  • The loading to content-loaded is not perfectly configured on every platform, seems to be hard on some
  • Gdpr.dispatch has currently problems with LazyLoad, this was planned and dispatching will be fixed when implementing full lazy-load, this means using LazyLoad and auto_check* is a conflict.
  • Showing a preview images or html can collide with the css states loading and the transition to content-loaded. just a not so nice animation, especially when the iframe loads to fast for loading to finish before content-loaded with a high transition time in $gdpr--visible-time--*

In Sass

See Bitbucket master Module GDPR Style, currently the style just is a default scribble and not for productive, use it as base but you need to implement the final style yourself.

The included files need to be refactored/restructured for a library usage.

Using the included files:

// Variables like some basic gutter, drop-dwon animation adjustment
@import "vendor/flood/canal-asset/module/gdpr/style/config";
// Mixins for gutter, loading and visibility and embed
@import "vendor/flood/canal-asset/module/gdpr/style/mixin";
// The main style
@import "vendor/flood/canal-asset/module/gdpr/style/style--default";
// Just the border styles
@import "vendor/flood/canal-asset/module/gdpr/style/style--border";
// Some platform specific styling
@import "vendor/flood/canal-asset/module/gdpr/style/style--platform-specific";

In HTML/Twig

HTML Files per se are not existing, in the Canal Component View are Twig Files with option based behaviour.


  • overwriting logic for the variable gdpr, overwrites the backend family settings
  • free selectable CSS prefix, uses concatenating (--) element selectors
  • the id is not optimal, but so only truly needed when a checkbox is displayed, must be unique within (mostly) one family.type
  • gdpr.border adds modifier class w-border
  • used from js
    • is received from backend/overwritten in tpl like: 'data-attr': { 'allowfullscreen', 'width': 250 }
    • is added as data-attr="<key>|<value>" = data-attr="width|250", data-attr="<value>" = data-attr="allowfullscreen"
  • gdpr.preview [map], displays a preview
    • gdpr.preview.img [map], displays specified image as background style or as an img
      • [bool], if it should be style="background-image:url(src)"
      • gdpr.preview.img.src string, Url to image, absolute is recommended
      • gdpr.preview.img.alt [string], used as alt tag on the img
    • gdpr.preview.html [string], something that should be displayed as preview, e.g. Instagram embed api from backend
  • gdpr.prerender bool, if twig must render barrier, loading and default
  • gdpr.barrier [Map], show a barrier which the user must interact with to view the content
    • gdpr.barrier.label [map] a label that will be displayed in an <p>
    • gdpr.barrier.label.position string whe the label should be displayed
      • available: before-check, before-btn, on-end
    • gdpr.barrier.label.value string the text, could also be html
  • gdpr.loading bool, html for adding a css based spinner
    • gdpr.loading.label [string], displayed as a <p> below the spinner
  • gdpr.loading bool, html for adding a css based spinner
    • gdpr.loading.label [string], displayed as a <p> below the spinner

Example HTML output with a few of the optional things (concurrent, even when not possible to have concurrent):

<!-- having multiple classes, bg or img not both, `content-loaded` is added from JS (and a few more) -->
    class="gdpr gdpr--wrapper w-preview--as-bg w-preview--as-img w-preview--as-html content-loaded"

    <div class="gdpr--content"></div>

    <div class="gdpr--preview as-bg">
        <div class="gdpr--preview--image gdpr--preview--image-bg" style="background-image:url(some-pic.jpg);"></div>

    <!-- or -->
    <div class="gdpr--preview as-img">
        <img class="gdpr--preview--image gdpr--preview--image-img" src="some-pic.jpg" alt="Maps Preview Image">

    <!-- modifier `hidden-checkbox` comes from JS, after JS has checked the checkbox-->
    <div class="gdpr--barrier">
            <p class="gdpr--barrier--label">Label with position `before-check`</p>

            <div class="input-group input-group--checkbox">
                <label for="gdpr-check[google-maps--3]">I accept the <a href="/law/privacy" target="_blank">privacy policy</a>, showing will connect to Google.</label>
                <input id="gdpr-check[google-maps--3]" name="gdpr-check[google-maps--3]" required="" type="checkbox">

            <p class="gdpr--barrier--label">Label with position `before-btn`</p>

            <button>show Map</button>

            <p class="gdpr--barrier--label">Label with position `on-end`</p>

    <div class="gdpr--loading">
        <div class="gdpr--loading--inner"><span></span><span></span><span></span></div>
        <p class="gdpr--loading--label">The content is loading</p>

    <div class="gdpr--default">
        <span><a href="" target="_blank">original Content ⮊</a></span>

In Backend

Example of Maps and Twitter

import Gdpr from 'vendor/flood/canal-asset/module/gdpr/Canal-GDPR';
import Maps from "vendor/flood/canal-asset/module/gdpr/src/handler/Maps";
import Twitter from "vendor/flood/canal-asset/module/gdpr/src/handler/Twitter";

let gdpr = new Gdpr({
    debug: true,
    autoload: false,
    twitter: {
        debug: false,
        prerendered: true,
        auto_check: false,
        auto_check_load: true,
    'google-maps': {
        //autoload: true,
        prerendered: true,
        auto_check: true

gdpr.type_handler = {
    'twitter': (config, elem, gdpr) => new Twitter(config, elem, gdpr),
    'google-maps': (config, elem, gdpr) => new Maps(config, elem, gdpr),

    .forEach((elem) => {

Google Maps

Social Embed