Developing An Embeddable Javascript Widget

A clear trend in web development today is that sites are composed of many 3rd party widgets. Go to any big site, open up the web inspector and see how much is really loaded from the address you typed!

This is great – everyone delivers one service they do well, instead of each site rolling their own half-baked version of everything from a comment system to a media player. Remember the days before Youtube? To show a video you’d have to host a media file yourself and usually just link to it and hope the user’s browser’s setup correctly; watching it was often done in a tiny, non-fullscreen’able QuickTime window. Now you just drop in a an embed code and get a full-fledged video player right on your page, together with your content.

But with so many components co-existing on a page comes a number of challenges arise:

  1. The embed code must be short & concise and work with a number of CMS’s
  2. What if they interfere with each other? Will the failure of one bring down the others?
  3. Keeping page load time down

This post is the first in a series on how to make a solid embeddable widget using the latest in web development: AWS for delivery, grunt and RequireJS for building and managing, sandboxing Google Analytics with EasyXDM and safe-wrapping 3rd party libraries. Today we will focus on #1.

Our mission today

At Shootitlive we provide media through an HTML5 player and to make our service a breeze to use we set out to make the smallest possible embed code.

We went from this:

to this:

Just like many other Javascript web apps – our player wants a DOM tree to live in and is initialized from a global settings object (e.g. Google’s _gaq) to allow for asynchronous loading. So if you’re embedding 3rd party Javascript of any sort you’ll probably find this post very useful.

Shootitlive?

Shootitlive is a live media service used mainly by newspapers and bloggers including The Times in the UK and Aftonbladet in Sweden. Our content is delivered from our backend into the Shootitlive Player (SILP), through real-time JSON playlists. The idea is that you embed the player wherever you want to show your media feed. On-the-field photographers then publish photos, videos and audio straight from their camera to the web in a couple of seconds.

The many ways of embedding

The most rudimentary way of embedding still used by many services is the following:

The downside of this approach is that it blocks the DOM rendering, i.e. it is synchronous – and if the script fails the whole site might have its Javascript broken.

Therefore most providers use this technique instead:

Which is better due to being asynchronous and all.

For more on asynchronous vs. synchronous loading of Javascript, Emil Stenström has written a great in-depth post on JS loading patterns.

The second option however is still long and hairy and our experience is that the longer embed code you give to your users – the bigger the chance something terrible happens to it on its travel, whether it’s edited by a user or mangled by a well-intended CMS.
Also it has a lot of specifics pasted on each site – i.e. if we change something in the embedding / loading technique we must have each client update their embed code.

How we do it

In summary, our goals are:

  • One can pass arbitrary parameters to each embed
  • The embed code is short
  • It loads asynchronously
  • One can have multiple players on one page

Instead of pointing the embedding site straight to our player source file we decided to add a loader file that sets up the player and deals with all embedding-related issues. Also it enables us to tune our embedding technique and have it affecting all existing embeds.

With a loader file we don’t need any inline Javascript in the embed code which then could boil down to:

<script src="//our-cdn.com/shootitlive.load.js?project=13&client=greenfield[more URL encoded parameters]" async></script>

It is short and asynchronous for almost all modern browsers. Note that we can pass in arbitrarily complex JSON object in the query string through URL encoding. jQuery’s $.param() is handy for this.

The loader will have to carry out the following:

  1. find its own script tag, or equivalently find all player embeds in the DOM
  2. parse the parameters for each player through the query string
  3. create a container div for the player next to each script tag
  4. load the silp.min.js script with the supplied parameters

1: Identifying embed codes

Having multiple players makes things a bit more tricky since the very same script will be run multiple times – once for each player. Therefore we use a global `foundEls` variable to keep track of which embeds have already been found.

Note that the regexp re determines if a script tag is a Silp embed or not.

This code will identify all embed tags on the page once. If there are two embeds on a page – with HTML content in between that delays the DOM parsing, it will only find the first embed on the first run. However, usually the first inclusion will find all embed tags and store them in `foundEls` while the second run will not do anything. Due to this care must be taken so that the loader is idempotent (I confess, math lingo makes me feel warm inside).

2: Parsing the query string

Our second step is to parse the settings from each script tag and create a container div for the player next to it. One can use the previously mentioned $.param() to convert a JSON object into a query string. Luckily Ben Alman has written an inverse function deparam() that gives you back the original JSON object, you can find it here. I made it into a stand-alone version found here.

Equipped with this, we can transform an URL with a query string into a JSON object like this:

3 and 4: Creating a container for the player and feeding the parameters into its initialisation method

Naturally we want the player to be inserted next to the embed code that created it – which is easy since we have a handler to the <script> element for each embed.

All that remains is actually loading the player, and since it will initialize a player for every element in settings we only need to load its source once at the end of our loader script:

All in all

You can find the final loader script here. The loader script we use in production is slightly more involved due to backward-compatibility and the such, but the gist illustrates the distilled principle behind it.

The loader script comes with many benefits. For example we could create a custom loader script for a client – containing additional default parameters, extra code for custom templates, etc. Editing this custom loader would instantly affect all existing embeds for that client. We could even point them to a different version of the player. In summary – it provides a great middle-point for rolling out changes quickly without involving the client with technical issues.

If you have questions, want to tell me I don’t know the first thing about this and ought to pick another carrer path or just say hi: please comment or tweet me: @svammel.

What’s next

The upcoming articles will cover the refactoring and architectural improvements of our player. Topics will include:

  1. Using RequireJS for an embeddable app – either as many-files, or as a minified single-file version. We have done some pretty sweet solutions with grunt for no-brainer development, testing and deployment.
  2. Safely using jQuery and other 3rd party libraries in your embeddable through namespacing
  3. Running Google Analytics in the player without interfering with the parent page’s own analytics

Until then.

Cheers, The Shootitlive Team

Shoot It Live / Voogly is looking for a Python dev

office_star2sil-shutter-400pxWe’re in a search for a python developer that knows his way around Debian, PHP and MySql. We’re looking for someone based in Stockholm being curious, interested and biased in python. But most important is that you find what we are doing and our architecture to be exiting and challenging. We’re a young company in our second year about to expand Shoot It Live to all Scandinavian markets shortly and to global markets thereafter.

Your work will be to set up, change and develop Shoot It Live and add-on services. We nailed you down to be either one of these people:

We think you recently graduated from school and looking for work experience. You have been developing in python as a hobby and looking to see your hard spending hours coding end up being in use on the biggest sites. We can offer you a very exiting position to be on board almost from start and an excellent career start, where you will get to know top CTOs.

You are studying and looking for a part time job, where you can focus on what you like the most, to develop in python. We can offer you a very exiting challenge that can lead to a full time position once you graduated and give you great work experience.

You’re a consultant specialized in python development looking for a new challenge. You are used to work under stress and can deliver on time. We can offer you several projects.

You will be using the following language, frame works and tools:

Python
PHP
HTML/CSS
Java script
Mercurial
Smisk (python-smisk.org)
Imagemagick
ffmpeg
Amazon Cloud services (EC2, S3, Cloud Front, Devpay etc.)

Send your application to hello@shootitlive.comShoot It Live Office

Vi söker en Pythonutvecklare som är är kunning på Debian, PHP och MySql. Vi söker efter någon bosatt I Stockholm som är nyfiken, prestigelös och som verkligen gillar Python. Men viktigast är att du tycker vår arkitektur låter spännande och något som du vill jobba med. Vi är ett ungt företag som funnits I 2 år och håller just nu på att expandera I Norden och kommer därefter rulla ut våra tjänster globalt.

Du kommer att ha ansvar för att självständigt utveckla, implementera och testa funktionalitet för Shoot It Live och dess add-on tjänster. Vi tror att du är en av följande typer:

Du har nyligen tagit examen och letar efter jobb erfarenhet. Du har programmerat och utvecklat I Python på hobbynivå och skulle gärna se dina kreationer användas på de största webbplatserna. Vi kan erbjuda dig en superstart för din karriär där du kommer att lära känna top CTOs på några av de största media företagen I Norden.

Du studerar och letar efter ett extrajobb, där du kan fokusera på det du gillar mest, att koda I Python. Vi kan erbjuda dig en spännande utmaning där du kan utvecklas och som kan leda till ett heltidsjobb när du tagit examen.

Du är en konsult specialliserad på Python utveckling som letar efter nya utmaningar. Du är van att arbeta under tidspress och kan leverare mot deadline. Vi kan erbjuda dig många intressanta projekt.

Du kommer att använda följande språk, ramverk och verktyg:
         
Python
PHP
HTML/CSS
Java script
Mercurial
Smisk (python-smisk.org)
Imagemagick
ffmpeg
Amazon Cloud services (EC2, S3, Cloud Front, Devpay etc.)

Skicka din ansökan till hello@shootitlive.com