How-to: Obtain User Consent Prior to Loading Videos (2-click video solution)

computer screen with video playback thumbnails


Displaying videos from YouTube and Vimeo on websites is a common practice used by many companies to create more engaging experiences for their visitors. While it is important to offer customers a great experience, it is also imperative to make sure your site visitors understand what's happening as they interact with your site. This is sometimes referred to as a 2-click video solution.

We have developed a visually engaging solution for this. In this blog post we show the solution we have created with screenshots, code snippets, and live examples.


Our client Senec is working in a competitive environment and has to react on changing requirements regarding privacy quickly. At the same time the user experience cannot be harmed by regulations. In the beginning of the year Senec requested us to build a two-step process for YouTube/Vimeo video playback.

Senec's website is built with Drupal 8 and won the International Splash Awards 2019.

When loading a page that contains a video, a preview is displayed website with a custom image and a play button according to their design system. 

Screenshot video on Senec website before privacy overlay

But when the visitor decides to click on the video playback button, an information message is displayed as shown in the image below.

Screenshot video on Senec website with privacy overlay warning about video content

It is only after the user clicks on 'Play video' that the request is made to to the video provider to fetch the content and display it.

Displaying the video like this allows for both an engaging visual experience, and at the same time protects the user's privacy until consent has been explicitly granted.


As for the implementation, it didn't require a lot of effort, and was accomplished with just a few lines of JavaScript, some HTML and CSS. As the solution is implemented with Drupal, we will make reference to the twig template used and the JavaScript code. The following snippets are just some pointers and might need to be adjusted for your particular implementation.

The first step is to include the information overlay HTML along with the video playback element. Below is the Twig template that generates the markup for the video player. Twig is the default template engine in Drupal 8, and the generated markup can be obtained directly from the website linked below.

<div {{ media_remote_video_attributes.addClass(media_remote_video_classes) }}>
  <div class="media-remote-video__content position-relative media-remote-video__thumbnail" data-video='{{ media_remote_video_url }}'>
    <div class="picture--fill">
      {{ media_remote_video_image }}
      <div class="consent-message">
        <p>{{ consent_message }}</p>
        {% include '@atoms/_button.twig' with {
          button_element: 'a',
          button_link: '#',
          button_color: 'primary',
          button_size: 'sm',
          button_text: 'Play video'|t,
          button_other_classes: 'play-video',
    {% include '@atoms/_svg-icon-gradient.twig' with {
      svg_icon_gradient_svgname: 'play',
    } only %}

Here is the SCSS file used to generate the CSS for the video solution. The actual CSS code can be obtained from the website linked below.

.media-remote-video__content {
  padding-bottom: 52.5%;
  padding-top: 1.5rem;
  height: 0;
  @include media-breakpoint-up(lg) {
    padding-bottom: 50%;
  @include media-breakpoint-up(xl) {
    padding-bottom: 52.5%;
  .consent-message {
    display: none;
  .svg-icon-gradient {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate3d(-50%, -50%, 0);
    z-index: 1;
    cursor: pointer;
    &:hover {
      // stylelint-disable max-nesting-depth, selector-max-specificity
      // stylelint-disable declaration-no-important
      .svg--fill-transparent {
        stroke: $color-orange !important;
  &.consent {
    .field--name-field-video-thumbnail {
      display: none;
    .consent-message {
      background-color: $color-blue-cloud;
      color: $white;
      height: 100%;
      padding: 0 15%;
      text-align: center;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      @include media-breakpoint-down(sm) {
        font-size: $font-size-sm;
        padding: 0 4%;
      .btn {
        margin-top: map-get($spacers, 3);
    .svg-icon-gradient {
      display: none;
  iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;

Then it is just a matter of having the JavaScript function that is responsible for displaying the message and loading the actual video when the user clicks on the 'Play Video' button.

export function enable($context) {
  const $videoThumbnail = $('.media-remote-video__thumbnail', $context);

  $videoThumbnail.each(function videoThumbnailFn() {
    const $thisThumbnail = $(this);
    const $videoThumbnailIcon = $thisThumbnail.find('.svg-icon-gradient');
    const $videoPlay = $thisThumbnail.find('.play-video');

    $ showConsent() {
    $ showVideo(e) {
      const $video = $'video');

And that is it. You can see it working live at the Senec website.


Submitted by Anonymous (not verified) on 12. February 2020

This makes a lot of sense. Any plany to make this re-usable? I'd chip in some time. (@geek-merlin)

Submitted by Christoph Breidert on 17. February 2020

Feel free to grab the code and do something with it. We are currently re-using it in other projects and will maybe create something more generic out of it.

Add new comment