Blue Wistia logo alongside the word engineering

Building the Wistia Labs Framework

When we first rolled out Wistia Labs, the whole company spent 2 days of rapid development to make it happen. But weeks before and after were spent making the framework that allowed it to happen.

We recently explained how we built Wistia Labs with an all-hands-on-deck hackathon called Labstock. Working on Labs this way wouldn’t have been possible without a lot of background preparation beforehand.

The Old Wistia Labs

If you’re an old-school Wistia follower, you might remember the original Wistia Labs, which handled things like the Social Bar.

The Social Bar

Back then, we didn’t have an organized way to add things to embed codes, so we just appended JavaScript and HTML specific to the situation. It wasn’t a very cross-compatible approach — Labs worked with one type of embed code, they frequently conflicted with existing frameworks like jQuery, and we couldn’t use them in any place where JavaScript wasn’t allowed.

After we built the SuperEmbed Builder, we dispensed with Labs because we were able to perfect the functionality they provided and work it directly into the product.

The Product Dilemma

Even though universally appealing functionality like Calls to Action and the Social Bar had been rolled into the SuperEmbed Builder, people continued asking for things that we didn’t want to put into the product right away, or perhaps ever (for the most niche requests). We also wanted a place where we could experiment with functionality that might not yet be compatible across all of our officially supported browsers.

Twitter Lab

With a new Player API and embed codes at our disposal, we decided that we wanted to do a Twitter Follow Lab (to insert Twitter Follow buttons into videos), but we couldn’t do it the same way we’d done Labs in the past.

All of our previous Labs depended on injecting JavaScript, but our Twitter card is just an iframe, so you can only give it an iframe source, not put scripts inside of it.

The Plugin API

Our new embed codes consisted of a video ID plus a hash of options for that embed. Wouldn’t it be cool if we could just list the Labs we were using directly in the embed code and have it work on iframes without any external scripts?

The first thing we developed was a way to load and execute plugin scripts in the right context, called the Plugin API. To do that securely in production, we had to migrate our iframe embed code sources from to (why?). To make it easy to add HTML around the video, we enabled “the grid” for all embed codes.

The Lab Tools Library

The Twitter Lab didn’t use any kind of organized framework. It was originally just some regular expression parsing and jQuery bindings. I wrote a library called “labtools.js” to let us manipulate any type of Wistia embed code. It still used regular expressions and jQuery, but also leaned on our oEmbed endpoint. Now, it didn’t matter what kind of embed code people were giving us: we could reliably inject Labs into them.

A lot of work went into Lab Tools, based on a combination of our Player API and jQuery, before the Twitter Lab, but it wasn’t perfect - the scope was pretty small. In preparation for Labstock, we tried to generalize the structure of a Lab. Using the Twitter Lab’s design as inspiration, we created a blank Lab that accepted an embed code, added some dummy options, and previewed the new embed code.

When you preview an embed code in a Lab, we’re taking the embed code that we output and displaying it both in the text area and on the page. That sounds easy, but existing frameworks like jQuery complicate matters. They can inject HTML or scripts, but when you combine external and inline script tags, the order in which they are executed isn’t reliable. We had to write our own JavaScript methods to inject the HTML and execute the JavaScript in the proper order.

Thanks to Lab Tools, when we were developing Labs, we were getting a real-time preview on the Lab page if we made a change to the plugin script. However, in some Labs, refreshing the embed code for every change is a terrible experience. For those, we needed a solution that was more precise. The Presentation Sync Lab, for instance, created its own public JavaScript interface and used an API embed for its preview. Instead of re-embedding for every change, we could tell it to add or remove specific slides.

Presentation Syncing

We also took elements of the Wistia app, like jamjars and fonts, and applied them to everything in a standard framework. This gave Labs a lot of structure and unified the way they looked.


Lab Tools and the Plugin API were buggy to start. Most of us didn’t have many problems, but I was focused mostly on fixing the tools instead of helping with the development of individual Labs. Still, it’s good that we caught and crushed the bugs before release, and Labstock allowed us to find the issues very quickly.

Documentation could have been better: there were some JavaScript functions that almost everyone needed, but aren’t part of the Player API and aren’t publicly documented. That was actually by design, but methods to inject dynamic CSS and scripts, for example, are so useful that we will likely make them public soon.

Poor planning for fully client-side pages was also an issue. To start out, if we wanted to update the header or footer, we had to make the change by hand on every single Lab page. This problem became obvious when we learned the Twitter Follow Lab’s original style was not the final design, and that all Lab pages would be getting both a header and subheader. We solved this with a Ruby script that injects the header into the proper location, but it would have been nice to have that in mind from the start.


Labstock showed us how much we could get done as a company in a short period of focused effort. While we were able to accomplish our basic goals, we learned what we could do better next time: document the most useful methods and plan a little further ahead.

It had side benefits, too. Everyone who created a Lab became familiar with the Player API and Plugin API, which makes their jobs that much easier on a daily basis. And since our customers are using these same APIs, we saw firsthand what we need to do to improve them.