Async Embeds

Async API embeds have a different syntax than traditional API embeds. It's the future!

Async API embeds work a lot like traditional API embeds, except we have a different way of setting options and getting an API handle. These docs explain how Async API (or Standard) embeds work.

The Wistia APIs were specifically built for videos in projects. We do not formally support using our APIs for audio files in projects, or audio or video episodes in Channels at this time. For the most reliable experience, we recommend continuing to use these for videos in projects.

How to get an Async Embed Code

Async embeds are here! Wistia’s Standard and Popover embeds are asynchronous. Just navigate to the Embed and Share modal and select the “Standard Embed” from the “Inline Embed” tab, choose the “Popover Embed” tab. It’s seriously that easy.

Note that iframe embeds are already async because that’s just how iframes work.

Playlists are not asynchronous. But we’ve got Embed Links, which are better anyway. 😃

The Composition of an Async API Embed

Here’s an example async API embed, straight out of the embed modal:

<script src="" async></script>
<script src="" async></script>
<div class="wistia_embed wistia_async_g5pnf59ala" style="height:360px;position:relative;width:640px">
  <div class="wistia_swatch" style="height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;transition:opacity 200ms;width:100%;">
    <img src="" style="filter:blur(5px);height:100%;object-fit:contain;width:100%;" alt="" aria-hidden="true" onload=";" />

Let’s break down all the pieces of this embed code.

First, we have an async script tag for our SpeedDemon script, which helps the video initialize faster.

<script src="" async></script>

We include this in the embed code so that it can immediately request the data that the video needs, such as its embed options and video asset information, even before our JavaScript library, E-v1.js, finishes loading. It’s not required, but removing it from the embed code comes with a slight speed penalty.

After that, we have an async script tag for E-v1.js, our JavaScript library.

<script src="" async></script>

This script tag can go anywhere on your page. Header, footer, before the embed, after the embed, it doesn’t matter. That script loads our video embedding libraries into the window.Wistia namespace and watches the page for markup that looks like async Wistia embed codes.

Next we have the video container.

<div class="wistia_embed wistia_async_g5pnf59ala videoFoam=true" style="height:360px;position:relative;width:640px"></div>

The video container is where your video will be placed when all the initialization steps are complete. The video container’s attributes control how the video is initialized.

As part of the video container, first, the wistia_embed class.

<div class="wistia_embed wistia_async_g5pnf59ala videoFoam=true" style="height:360px;position:relative;width:640px"></div>

The wistia_embed class is a signal to our embedding library that this container is a Wistia embed. Without this, we cannot get a handle to the API.

Second, the wistia_async_hashedid class.

<div class="wistia_embed wistia_async_g5pnf59ala videoFoam=true" style="height:360px;position:relative;width:640px"></div>

This class tells our embedding library two things: (1) it’s an async embed, and (2) it should embed a video with hashed ID g5pnf59ala. When you grab your embed code from the Embed Modal, it will have its own hashed ID unique to the video.

Third, option=value style classes.

<div class="wistia_embed wistia_async_g5pnf59ala videoFoam=true" style="height:360px;position:relative;width:640px"></div>

In this case, we set videoFoam to true. But you could also set any options available in the Embedding Options page. If you’re setting more than one option, just separate them with spaces. If your option’s value includes spaces, then percent encode it!

You might say, “hey, that’s not a valid class!” But alas, it is. All characters — except the null terminator — are valid in the class attribute. Some are just much harder to target with CSS rules, which is not necessary in this case. For more info, check out Mathias’s notes on CSS escapes, the HTML5 id and class attributes, and his demos of CSS escapes with crazy classes.

We chose to set options in the class attribute because they are less likely than HTML5 data- attributes to be stripped out of CMSes, and the syntax aligns nicely with options for our iframe embeds.

Last, the style attribute.

<div class="wistia_embed wistia_async_g5pnf59ala videoFoam=true" style="height:360px;position:relative;width:640px"></div>

For fixed-size embeds, we define a width and height for the video. We recommend always using values in px to set the width and height, and using videoFoam if the video needs to be responsive. Also, to avoid issues with video foam and fullscreen, we recommend NOT adding borders, padding, or margin directly to the video container. Instead, you should create a wrapper element and add them there.

Within the video container is the swatch.

<div class="wistia_swatch" style="height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;transition:opacity 200ms;width:100%;">
  <img src="" style="filter:blur(5px);height:100%;object-fit:contain;width:100%;" alt="" aria-hidden="true" onload=";"/>

There’s a lot of code here, but the swatch is essentially just a placeholder image that we display behind the video container. If the video is ever slow to load, you’ll see this blurry image in its place as a way to say, “Don’t worry, soon something will be right here!”

Using the Wistia library asynchronously

Because E-v1.js is loaded asynchronously, we need to make sure any code that references it only runs after window.Wistia is defined. There are a few ways to do that.

The simplest way is as follows:

window.wistiaInit = function(W) {
  console.log("Wistia library loaded and available in the W argument!");

That function will be called as soon as E-v1.js loads. If E-v1.js is already loaded when you define the function, it will execute asynchronously in 500ms or less.

If you are writing code that is supposed to be repeatable — say for your entire website, or as a snippet for other users — we recommend using the following form instead:

window.wistiaInitQueue = window.wistiaInitQueue || [];
window.wistiaInitQueue.push(function(W) {
  console.log("Wistia library loaded and available in the W argument!");

window.wistiaInitQueue functions the same way as window.wistiaInit except it will not clobber any other functions that have been defined to run on initialization.

Getting an API handle

Traditional API embeds set the wistiaEmbed variable right in the embed code. We can’t do that with async embeds, so we need to use a new method: the Wistia.api() function.

<script src="" async></script>
<div id="my_video" class="wistia_embed wistia_async_g5pnf59ala" style="height:360px;position:relative;width:640px">
window.wistiaInit = function(W) {

In that snippet, we defined an ID attribute on the video container, then referenced that ID after the Wistia library was initialized.

Now that you have a handle to the video, you can use it just like a traditional API embed, with the Player API.

Setting embed options

You can customize the Wistia player’s appearance and behavior from right within the embed code. To make a few small adjustments, you can simply set a class of the style option=value. But if you want to set more complex inline options, this gets a little clunky. In that case, we suggest using window._wq to set them with a Javascript object literal.

You can read about both of these methods on our Embed Options and Plugins page.

How async embeds are initialized (for the curious)

The Wistia library defines Wistia.embeds.setup() which finds all (or a subset of) async video containers on the page and initializes them as Wistia videos. This function is called as soon as E-v1.js loads for the best experience. Once E-v1.js is loaded, it will watch the DOM forever for new Wistia embeds.

To setup that watch, we use a feature of modern browsers called mutation observers. They allow us to efficiently detect whenever a <div> with a wistia_embed and wistia_async_hashedid class is added to the DOM. Older browsers don’t have mutation observers, so in those, we poll the DOM once every 500ms for any matching elements that have not been initialized.

The following information is for micro-optimization on older browsers. Going forward, this will be less and less important, so we advise only making these micro-optimizations if you have no other choice.

If you want to prevent any initialization lag in older browsers, you can call Wistia.embeds.setup() immediately after you inject a Wistia embed into the page.

If you have a site with an extremely large number of <div> elements and are optimizing for older browsers, you might want to turn off our automatic watch. To do that, you can add this javascript:

window.wistiaInitQueue = window.wistiaInitQueue || [];
window.wistiaInitQueue.push(function(W) { W.embeds.dontWatch(); });

If you choose to turn off the watch, then you will need to call Wistia.embeds.setup() manually whenever you inject a new Wistia embed into the DOM.