Privacy-friendly video embeds
If a picture's worth a thousand words and a video comprises many pictures, then a video's worth, erm… quite many words, really. From interviews to product reviews, tutorials to testimonials, behind-the-scenes glimpses to documentaries; video is a rich and highly engaging medium that can diversify and spice up the content of your website.
However, with the advent of privacy regulations on the internet, embedding a video in a web page has become more complicated than dropping an iframe in your HTML code. Many video platforms make use of cookies and similar technologies to track viewing behaviour, which requires consent from your visitors under the GDPR and ePrivacy regulations. This article will focus on Vimeo and YouTube, and how to be mindful of your users' privacy when embedding content from these two major video providers.
Vimeo
This is the simple case. Vimeo has a different business model than YouTube, based on paid memberships rather than advertising revenue. They don't need to track visitors no matter what and make it possible to opt out of any data collecting.
We do this by appending the dnt
parameter to the embed URL. Short for Do Not Track, the dnt
parameter will have the same effect as the browser setting of the same name. Setting the parameter to true
or 1
prevents the Vimeo player from tracking any session data or gathering analytics. If the embed URL was https://player.vimeo.com/video/45010429
, it now becomes https://player.vimeo.com/video/45010429?dnt=1
.
All that's left is to make the video responsive using the classic intrinsic ratio trick. We wrap the iframe
in another element:
And apply the following styles:
With very little effort and without further measures, we comply with privacy regulations. So let's enjoy a dance, shall we?
YouTube
Embedding YouTube videos requires a bit more work, as YouTube doesn't provide a mechanism to opt out of data collecting completely. There's a "privacy-enhanced" mode that serves the video from a different domain, https://www.youtube-nocookie.com
, but contrary to what you might think, this still makes use of browser storage to identify the viewer.
In fact, when using the alternative domain, YouTube merely delays the use of cookies until the viewer clicks the play button on a video. Meanwhile, a unique identifier in the browser's localStorage
allows YouTube to track users whether or not they watch the video. As far as privacy regulations go, these different browser storage mechanisms are equivalent. Consent is still needed.
Asking for consent
Privacy laws stipulate that consent must be freely given, informed and specific.
Consent is freely given when it results from a positive action, like the click of a button. We can't assume visitors agree to any data collecting just because they continue to surf on our website. We'll delay loading the video until consent is given.
Our visitors need to be informed. They need to know what they consent to. In this case: tracking and data processing by YouTube. We'll show a notice that explains this in simple terms, and link to YouTube's privacy policy for those who want the full details.
Finally, consent needs to be specific. Users should receive granular control over the types of data collecting they do or do not agree to. They should be able to reject YouTube's use of cookies while allowing Twitter's, for example. While we could resort to the ubiquitous cookie banner, I believe there's a better way. If visitors have to make a choice when landing on a website, they're likely to allow or reject all cookies. Instead, it makes sense to ask for consent at the time it's needed, when the user actually encounters a video. We'll therefore replace the video with a notice. You could call it just-in-time consent, which is now truly specific.
The markup
Let's build on to the video component we had earlier. We add a disclaimer and disable the iframe by turning the src
into a data-src
attribute. Notice how we're using the youtube-nocookie.com
domain anyway, which might not be good, but is still better for privacy.
Styling
We'll hide the iframe and show the notice by default. The notice will disappear when the iframe becomes active.
To ensure the notice doesn't overflow its container, we'll introduce a variation on the intrinsic ratio trick we used earlier. A pseudo-element ensures the aspect ratio of our video component is at least 16x9, but the container will grow if the notice grows taller, which might happen on smaller screens. A background color on the container offsets the video element from its surroundings, and the notice gets centered vertically with flexbox.
Then we style our notice:
Nailing the thumbnail
It'd be nice to replace the background color on the container with the preview image for our video. The thumbnail hints to the video's content and entices visitors to watch it.
YouTube delivers these thumbnail images from the https://i.ytimg.com
domain in different resolutions. The highest resolution image that's guaranteed to exist is https://i.ytimg.com/vi/<VIDEO ID>/hqdefault.jpg
, which measures 480px wide and 360px tall. Higher resolution sddefault.jpg
and maxresdefault.jpg
images might be available for your video, depending on its quality. For the video in our example, that's not the case.
Now, how do we know which image is available? We could check manually if higher resolution images exist by visiting the different URL's, but that method doesn't scale well. An automated method would use YouTube's Data API to retrieve a list of all the thumbnails available for a video. This requires quite a bit of setup, which we won't cover here.
For Cloudinary users, there's a simpler method. We retrieve the highest resolution thumbnail for any YouTube video using a URL in the format https://res.cloudinary.com/<CLOUD NAME>/image/youtube/<VIDEO ID>.jpg
. That image can then be scaled and altered using the array of image transformations that Cloudinary offers. Cloudinary probably uses YouTube's Data API behind the scenes, but does the hard work for us.
If you're willing to accept slightly grainy thumbnails, the easiest is of course to settle on the rather low-quality hqdefault
image, even for higher resolution videos. That's the path we'll take.
No matter which option you prefer, add the image as a background on the video container:
And make sure it covers the whole component:
We keep the background color on the container anyway; it'll be visible while the image loads. The result looks similar to this, where the button doesn't do anything yet:
Activating the videos
Clicking the button on any of our videos should unblock all of them. We'll create an activateVideos
function that does just that. We loop over all the iframes with a data-src
attribute pointing to the youtube-nocookie.com
domain, and set their src
attribute.
Then we add event listeners to the notices:
CSS will take care of hiding the notice and showing the now active iframe instead.
Storing the user's preference
Right now, the user has to approve of YouTube videos again each time the page reloads. Similar to a cookie banner, visitors probably expect us to remember their preference. We'll use a cookie, yes, to do that.
To not reinvent the wheel on this one, we'll make use of the lightweight js-cookie library. We'll store a youtube-consent
cookie when the user consents to YouTube videos. On every page load, we then check if the cookie's present, and show either the video or the notice depending on that.
The full script:
Our component is now fully functional.
Revoking consent
The last requirement is an option for users to revoke the consent. This could be a button or a toggle in the site's privacy or cookie policy. The button would delete the cookie, deactivate the videos, and attach the event listeners to the disclaimers again.
Conclusion
It's important to be mindful of your users' privacy when embedding content from a third party. If, like Vimeo, the provider offers privacy controls, default to them; your users can only benefit from it. If not, ask for consent first, and load the content afterwards. Inform your visitors and provide an option to revoke consent.