Videos from Vimeo that you can play directly in your email client, with beautiful fallbacks for those less awesome clients (cough, cough, Outlook).

See the Pen Video preview for email by Stig Morten Myre (@stigm) on CodePen.

Here’s how:

Basic Usage

{[ emailvimeo id:'231200000' title:'Small Groups are Back!' mp4_url:'https://player.vimeo.com/external/231200000.sd.mp4?s=84f7cd2a8e3badba6145b63ad738a286692cd34c&profile_id=164' m3u8_url:'https://player.vimeo.com/external/231200000.m3u8?s=e4ab8e042dec16207b42effe026aebd92cbb0fb1' ]}

This will put the video with the id provide onto your email in a responsive container. The id can be found in the address of the Vimeo video. There are also a couple of options for you to add:

  • id (required) – The Vimeo id of the video.
  • thumbnail_url (required) – A URL for the default image.
  • title – The title of the video, provides hover text (Watch {{title}}) for email clients that cannot play inline.
  • mp4_url (required for embed) – The Standard Def MP4 link from Vimeo.
    • Settings > Video Files > Get Direct Links to Use with your own player
  • m3u8_url (required for embed) – The HTTP Live Streaming link from Vimeo
    • Settings > Video Files > Get Direct Links to Use with your own player

Setup

To use the Vimeo email embed in your templates, copy the CSS below into the <style> tag for every template you want to use the embed.

video{width:100%;max-width:100%;}
    .video-wrapper {display:none;}
    @media (-webkit-min-device-pixel-ratio: 0) and (min-device-width:1024px){
        .video-wrapper { display:block!important; }
        .video-fallback { display:none!important; }
    }

    @supports(-webkit-overflow-scrolling:touch) and (color:#ffffffff) {
        div[class^=video-wrapper] { display:block!important; }
        div[class^=video-fallback] { display:none!important; }
    }

     #MessageViewBody .video-wrapper { display:block!important; }
     #MessageViewBody .video-fallback { display:none!important; }

    .video-preview:hover .play-button {
      transform: scale(1.1);
    }
    
    .video-preview:hover tr {
      background-color: rgba(255, 255, 255, .2);
    }

Very Advanced Usage

Static images for video previews are boring. The quality compromise of a GIF could work, it might not be the best representation of your video. Using progressive enhancement in email we can rotate through a few still frames from the video using a keyframe animation. To use keyframes use a comma separated list of URLs in the animate_urls parameter.

To use the animate_urls feature, you will need to copy the CSS using a separate lava block. Then copy the css output to the style block contained in your html email template. (Found in Settings > Communications > Communication Templates). We recommend creating a temporary template for one time use. 

  • css_output (false) – Output CSS instead of the HTML for the embed.
  • animate_urls (optional) – Comma seperated list of URLs to be animated via CSS
  • animation_time (optional) – Total time, in seconds, to complete a full cycle through the animate_urls.
  • transition_time (optional) – Time, in seconds, to transition between animate urls.

Credits

The underlying embed methodology was developed by Stig Morten Myre at Campaign Monitor.

Parameters

id
thumbnail_url
mp4_url
m3u8_url
title
css_output
animate_urls
animation_time
transition_time
{%- assign id = id | Trim -%}
{% assign css_output = css_output | AsBoolean %}
{%- assign keyframes = '' -%}

{%- if animate_urls != '' -%}
  {% assign animate_urls = animate_urls | Split:',' %}
  {% assign frame_count = animate_urls | Size %}
  {%- if frame_count > 0 -%}
  {% assign time_per_slide = animation_time | DividedBy:frame_count,5 %}
  {% assign percent_hold = time_per_slide | Minus:transition_time | DividedBy:animation_time,5 %}
  {% assign percent_move = frame_count | Times:percent_hold | Times:-1 | Plus:1 | DividedBy:frame_count,5 %}
  {%- endif -%}

  {% capture keyframes %}
  {% for frame in animate_urls -%}
  {%- assign x = forloop.index0 | Times:percent_hold -%}
  {%- assign next-x = forloop.index0 | Plus:1 | Times:percent_hold -%}
  {%- assign y = forloop.index0 | Times:percent_move -%}
  {{ x | Plus:y | DividedBy:0.01,2  }}% { background-image: url("{{ frame }}") }
  {{ next-x | Plus:y | DividedBy:0.01,2 }}% { background-image: url("{{ frame }}") }
  {% endfor -%}
  100% { background-image: url("{{ animate_urls[0] }}") }
  {% endcapture -%}
{%- endif -%}

{% if id != '' %}
  {%- stylesheet -%}
      video{width:100%;max-width:100%;}
      .video-wrapper {display:none;}
      @media (-webkit-min-device-pixel-ratio: 0) and (min-device-width:1024px) 
      {
          .video-wrapper { display:block!important; }
          .video-fallback { display:none!important; }
      }

      @supports(-webkit-overflow-scrolling:touch) and (color:#ffffffff) {
      div[class^=video-wrapper] { display:block!important; }
      div[class^=video-fallback] { display:none!important; }
      }

      #MessageViewBody .video-wrapper { display:block!important; }
      #MessageViewBody .video-fallback { display:none!important; }

      .video-preview:hover .play-button {
        transform: scale(1.1);
      }
      .video-preview:hover tr {
        background-color: rgba(255, 255, 255, .2);
      }
      
      {%- if keyframes != '' -%}
      @-keyframes video-frames {
      {{ keyframes }}
      }
      
      @-webkit-keyframes video-frames {
      {{ keyframes }}
      }
      {%- endif -%}
  {%- endstylesheet -%}

  {%- cache key:'vimeoemail-{{ id }}' duration:'0' twopass:'false' -%}
    {%- if thumbnail_url == '' or title == '' -%}
        {%- webrequest url:'https://player.vimeo.com/video/{{id}}/config' -%}
        {%- assign thumbnail_url = results.video.thumbs.1280 -%}
        {%- assign title = results.video.title -%}
        {%- endwebrequest -%}    
    {%- endif -%}
  

    {% if mp4_url != '' %}
    <div class="video-wrapper" style="display:none;">
      <video controls="" playsinline="" poster="{{ thumbnail_url }}">
        {% if m3u8_url %}<source src="{{m3u8_url}}" type="application/x-mpegURL">{% endif %}
        <source src="{{mp4_url}}" type="video/mp4">
        <!-- fallback 1 -->
        <a href="https://vimeo.com/{{ id }}" title="Watch {{ title }}" target="_blank">
          <img src="{{ thumbnail_url }}" />
        </a>
      </video>
    </div>
    {% endif %}
    <!--[if (mso)|(IE)]><table width="600" align="center" cellpadding="0" cellspacing="0" role="presentation"><tr><td><![endif]-->
    <div class="video-fallback" {%- if mp4_url == '' -%}style="display:block!important;"{%- endif -%}>
      <!--[if !vml]-->
      <a href="https://vimeo.com/{{ id }}" title="Watch {{ title }}" class="video-preview" style="background-color: #5b5f66; background-image: radial-gradient(circle at center, #5b5f66, #1d1f21); display: block; text-decoration: none;">
        <table cellpadding="0" cellspacing="0" border="0" width="100%" background="{{ thumbnail_url }}" role="presentation" style="animation: video-frames 15s ease infinite; -webkit-animation: video-frames 15s ease infinite; background-size: cover; min-height: 180px; min-width: 320px;">
          <tr style="transition: all .5s cubic-bezier(0.075, 0.82, 0.165, 1);">
            <td width="25%">
              <img src="https://placehold.it/150x337.gif?text=+" alt="" width="100%" border="0" style="height: auto; opacity: 0; visibility: hidden;">
            </td>
            <td width="50%" align="center" valign="middle" style="vertical-align:middle!important;">
              <div class="play-button" style="background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.1)); border: 4px solid white; border-radius: 50%; box-shadow: 0 1px 2px rgba(0,0,0,0.3), inset 0 1px 2px rgba(0,0,0,0.3); height: 34px; margin: 0 auto; padding: 18px 16px 18px 24px; transition: transform .5s cubic-bezier(0.075, 0.82, 0.165, 1); width: 30px;">
                <div style="border-color: transparent transparent transparent white; border-style: solid; border-width: 17px 0 17px 30px; display: block; font-size: 0; height: 0; Margin: 0 auto; width: 0;">&nbsp;</div>
              </div>
            </td>
            <td width="25%">
              &nbsp;
            </td>
          </tr>
        </table>

      </a>
      <!--[endif]-->
      <!--[if vml]>
        <v:group xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" coordsize="600,337" coordorigin="0,0" href="https://vimeo.com/{{ id }}" style="width:600px;height:337px;">
          <v:rect fill="t" stroked="f" style="position:absolute;width:600;height:337;"><v:fill src="{{ thumbnail_url }}" type="frame"/></v:rect>
          <v:oval fill="t" strokecolor="white" strokeweight="4px" style="position:absolute;left:261;top:129;width:78;height:78"><v:fill color="black" opacity="30%" /></v:oval>
          <v:shape coordsize="24,32" path="m,l,32,24,16,xe" fillcolor="white" stroked="f" style="position:absolute;left:289;top:151;width:30;height:34;" />
        </v:group>
      <![endif]-->
    </div>
    <!--[if (mso)|(IE)]></td></tr></table><![endif]-->
  {%- endcache -%}
{% endif %}