oembed icon indicating copy to clipboard operation
oembed copied to clipboard

Further changes required for GDPR compliance

Open joepagan opened this issue 2 years ago • 8 comments

Hey, this is a great plugin! I would love to use it but I think some more changes are required to make it GDPR compliant.

It appears the plugin will:

However, these changes do not consider cookies which may load from all over services which your plugin supports like an embedded tweet for example which will also load marketing cookies.

A GDPR setting implies being compliant when it might not be, especially where other services like twitter might be used which may load cookies via a different method.

Suggested solution

Having only really worked with CookieBot as a solution I feel their approach is good, but as it's not a standard approach though giving us access to do the following I think is cookie-blocking service ambiguous enough? Though I can't really comment on what the other services require.

Here is an example that is compliant with CookieBot

<iframe
    data-cookieblock-src="https://www.youtube.com/embed/xxxxxxxxxxx"
    data-cookieconsent="marketing"
    frameborder="0"
    allowfullscreen
></iframe>

Where if marketing cookies are accepted, the data-cookieblock-src updates to a src attribute.

So maybe it would be best to give devs the opportunity to disable the src attribute so they can do this.

RE how to handle other services

If a script element is responsible for create an iframe element like a tweet used to (not sure if that's what happens anymore), we can perform a similar change:

<script type="text/plain" data-cookieconsent="marketing"></script>

where the type attribute changes on accepting.

Though of course this requires extending the twig variables a bit more if that's something which could be considered?

joepagan avatar Jan 17 '23 13:01 joepagan

I first raised a request concerning this, perhaps without giving full consideration to GDPR requirements: https://github.com/wrav/oembed/issues/23

What I think I'd like to see is:

  1. Interface / documentation language changed so that people don't think they're automatically compliant (I will try and find time for a pull request). I still see some value to this plugin setting as it is now.
  2. A solution like yours @joepagan - to enhance this and help people towards full GDPR compliance. I wonder what other approaches there are?

iparr avatar Jan 17 '23 13:01 iparr

Hmm interesting, so @joepagan and @iparr we'd need something like:

$iframe = $dom->getElementsByTagName('iframe')->item(0);
$src = $iframe->getAttribute('src');

$src = $this->manageGDPR($src);

if (Oembed::getInstance()->getSettings()->enableGdpr) {
    $iframe->setAttribute('data-cookieblock-src', $src);
    $iframe->setAttribute('data-cookieconsent', 'marketing');
}

I do a ton of backend the past year or two, ML stuff, so don't follow GDPR much.

reganlawton avatar Nov 03 '23 00:11 reganlawton

Updated v3.0.3 with new changes with a new setting to support.

reganlawton avatar Dec 03 '23 23:12 reganlawton

It looks like this update will set 'data-cookieblock-src' in addition to the 'src' attribute, though the Cookiebot implementation removes the 'src' attribute.

It would be great if we could also display a placeholder before or after the iframe-tag

<div class="cookieconsent-optout-marketing">
    Please
    <a href="javascript:Cookiebot.renew()">accept marketing-cookies</a>
    to watch this video.
</div> 

This is the original Cookiebot page:

https://support.cookiebot.com/hc/en-us/articles/360003790854-Iframe-cookie-consent-with-YouTube-example

paulwaddington avatar Jul 11 '24 14:07 paulwaddington

@paulwaddington is correct RE cookiebot, it would needed to remove the src attribute otherwise the iframe will load regardless of cookie consent. Once the user accepts the relevant cookies, Cookiebot updates the iframe's src to its data-cookieblock-src.

I wrote a solution which removes the src and also handles other embeds like TikTok, which provides a <script> rather than an <iframe>

public function addConsentChecksToEmbed(string $code): string
{
    try {
        $dom = new DOMDocument();

        // Disable errors - TikTok puts a <section> in a <blockquote> for some reason which raises a PHP warning
        libxml_use_internal_errors(true);
        $dom->loadHTML($code);
        libxml_use_internal_errors(false);

        // Ensure there is a root level element
        $body = $dom->getElementsByTagName('body')->item(0);
        $childNodes = iterator_to_array($body->childNodes);
        // Get the nodes under body which are elements
        /** @var DOMElement[] $childElements */
        $childElements = array_filter(
            $childNodes,
            fn (DomNode $node): bool => $node instanceof DOMElement,
        );

        if (count($childElements) === 1) {
            $root = $childElements[0];
        } else {
            // Wrap the elements in a div
            $root = $dom->createElement('div');
            if (!$root) {
                Craft::error('Could not create root element', __METHOD__);
                return '';
            }

            foreach ($childNodes as $child) {
                $root->appendChild($child);
            }
            $body->appendChild($root);
        }

        /** @var DOMElement $script */
        foreach($dom->getElementsByTagName('script') as $script) {
            $script->setAttribute('data-cookieconsent', 'marketing');
            $script->setAttribute('type', 'text/plain');
        }

        /** @var DOMElement $iframe */
        foreach($dom->getElementsByTagName('iframe') as $iframe) {
            $iframe->setAttribute('data-cookieconsent', 'marketing');
            $iframe->setAttribute('data-cookieblock-src', $iframe->getAttribute('src'));
            $iframe->removeAttribute('src');
        }

        return $dom->saveHTML($root);
    } catch (DOMException $e) {
        Craft::error($e->getMessage(), __METHOD__);
        return '';
    }
}

I'm currently using that in a Craft module with

{{ craft.videoEmbed.addConsentChecksToEmbed(entry.myField.embed(oEmbedOptions).code)|raw }}

MangoMarcus avatar Oct 08 '24 10:10 MangoMarcus

@MangoMarcus If you have a working local solution please send a PR I'd be happen to give it a look and test. If all good I'll merge it through 🍻

reganlawton avatar Oct 08 '24 10:10 reganlawton

Hey @reganlawton

Just checking if any progress has been made here? We have several customers complaining about compliance issues

D3VM4TT avatar Jan 22 '25 15:01 D3VM4TT

@D3VM4TT I throw together a quick branch of @MangoMarcus code you can try testing using dev-feature/consent-checks branch in composer.

reganlawton avatar Jan 22 '25 22:01 reganlawton

Hey @reganlawton, I've tested out that branch with cookiebot and it does seem to be correctly blocking youtube/vimeo/tiktok cookies from loading completely until a user grants consent!

harry2909 avatar May 21 '25 13:05 harry2909

This has been updated in v3.1.5

reganlawton avatar May 22 '25 01:05 reganlawton