The Interactive Media Ads (IMA) SDK for HTML5 allows you to add VAST video ads to your web video player. For an example, check out our demo.

What are VAST video ads?

VAST stands for Video Ad Serving Template. It is an industry standard for serving video ads and tracking URLs. These ads can be shown as pre-roll (before your video), mid-roll (during your video, like TV commercial breaks), or post-roll (after your video) ads.

What you'll build

In this codelab, you'll add the IMA SDK to a preexisting web video player. You'll start with a simple video player that just plays video, and you'll finish with a player that shows pre-, mid-, and post-roll ads.

What you'll learn

What you'll need

Download the Code

There are two ways to get the code - you can clone the GitHub repo or download a zip file.

Step 1a: Clone the sample code GitHub repository

Clone the repository from GitHub:

git clone https://github.com/googlecodelabs/ima-html5.git

Step 1b: Download the sample code zip file

As an alternative to cloning the GitHub repo, you can download the code for this codelab. Unpack the downloaded zip file. This yields a folder called ima-html5-master. Change to that directory now.

Step 2: Explore the sample code

The source code contains one folder for each step of this codelab, along with all of the resources you will need. It also contains folders for "start," "final," and "work." For this codelab, make your changes in the "work" directory. The step-NN folders contain the desired end state of each step of this codelab. They are there for reference.

Test the web server

You'll need to host your code on a web server. Navigate to the directory where you unzipped your code and run python -m http.server. You should see Serving HTTP on 0.0.0.0 port 8000 ...

Now visit your work site in your web browser (by navigating to localhost:8000/work/) and you should see a page that looks like this.

This app doesn't have an IMA integration yet. If you click the play button, the content of the video (starting with a woman driving a car) plays without ads.

The first step to getting the IMA SDK implemented is to load it. Open your text editor. To load the SDK, add <script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3.js"></script> at the end of the body of index.html, just before the ads.js script tag.

index.html

<html>                                                                                                                             
  <head>
    <title>IMA HTML5 Simple Demo</title>
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>

  <body>
    <div id="mainContainer">
      <div id="content">
        <video id="contentElement">
          <source src="//s0.2mdn.net/4253510/google_ddm_animation_480P.mp4"></source>
          <source src="//s0.2mdn.net/4253510/google_ddm_animation_480P.webm"></source>
        </video>
      </div>
    </div>
    <button id="playButton">Play</button>
    <!-- BEGIN NEW CODE -->
    <script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3.js"></script>
    <!-- END NEW CODE -->
    <script type="text/javascript" src="ads.js"></script>
  </body>
</html>

This step doesn't change the behavior of the web page - when you test it, make sure there are no errors in the Chrome DevTools Console.

TRY IT

There are two main steps to use the IMA SDK – requesting ads and playing ads. Before you can play ads, you'll need to request them. To request ads, you'll need to create an AdDisplayContainer, AdsRequest, and AdsLoader.

Create the AdDisplayContainer

The IMA SDK needs to know how much room you have to show a video ad, and where to put that ad. To convey that information, create an AdDisplayContainer. The AdDisplayContainer takes a handle to a div in which the IMA SDK will render video ads. Add a new div to index.html with id="adContainer".

index.html

<html>                                                                                                                             
  <head>
    <title>IMA HTML5 Simple Demo</title>
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>

  <body>
    <div id="mainContainer">
      <div id="content">
        <video id="contentElement">
          <source src="//s0.2mdn.net/4253510/google_ddm_animation_480P.mp4"></source>
          <source src="//s0.2mdn.net/4253510/google_ddm_animation_480P.webm"></source>
        </video>
      </div>
      <!-- BEGIN NEW CODE -->
      <div id="adContainer"></div>
      <!-- END NEW CODE -->
    </div>
    <button id="playButton">Play</button>
    <script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3.js"></script>
    <script type="text/javascript" src="ads.js"></script>
  </body>
</html>

Now that you've created the AdDisplayContainer div, provide the AdDisplayContainer with a handle to it.

ads.js

let playButton;
let videoContent;
// BEGIN NEW CODE 1/3
let adDisplayContainer;
// END NEW CODE 1/3

function init() {
  videoContent = document.getElementById('contentElement');
  playButton = document.getElementById('playButton');
  playButton.addEventListener('click', onPlayClicked);
  // BEGIN NEW CODE 2/3
  setUpIMA();
  // END NEW CODE 2/3
}

// BEGIN NEW CODE 3/3
function setUpIMA() {
  adDisplayContainer = new google.ima.AdDisplayContainer(
      document.getElementById('adContainer'), videoContent);
}
// END NEW CODE 3/3

function onPlayClicked() {
  videoContent.play();
}

init();

The IMA SDK shows and hides the AdDisplayContainer as needed. You also provide the AdDisplayContainer with a handle to the video player, which allows the SDK to track the current time of your content to support Video Multiple Ad Playlists (VMAP). VMAP provides the ability to schedule ad breaks during your content (for example, play ads at 10, 15, and 20 minutes into your video).

Create an AdsRequest

Next you'll create an AdsRequest. The AdsRequest gives the SDK the information it needs to get ads from an ad server:

The following code creates an AdRequest using our sample ad tag with 640x360 linear ads and 640x150 non-linear ads. The ads play with sound but not autoplay.

ads.js

...
function setUpIMA() {
  ...
  const adsRequest = new google.ima.AdsRequest();
  adsRequest.adTagUrl = 'https://pubads.g.doubleclick.net/gampad/ads?' +
      'sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&' +
      'ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&' +
      'unviewed_position_start=1&' +
      'cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&cmsid=496&' +
      'vid=short_onecue&correlator=';
  adsRequest.setAdWillAutoPlay(false);
  adsRequest.setAdWillPlayMuted(false);
  adsRequest.linearAdSlotWidth = 640;
  adsRequest.linearAdSlotHeight = 360;
  adsRequest.nonLinearAdSlotWidth = 640;
  adsRequest.nonLinearAdSlotHeight = 150;
}
...

Create an AdsLoader and request ads

Now you can request ads. For this you'll need an AdsLoader. Create an AdsLoader by pasting adsLoader = new google.ima.AdsLoader(adDisplayContainer)into ads.js and call requestAds() as shown below. Also add a line to call adsLoader.contentComplete() when the content video finishes to trigger post-rolls.

ads.js

...
let adsLoader;
...
function setUpIMA() {
  ...
  adsLoader = new google.ima.AdsLoader(adDisplayContainer);
  videoContent.onended = () => {adsLoader.contentComplete();};
  adsLoader.requestAds(adsRequest);
}

This step doesn't change the appearance of the web page, but you should see a request to the pubads.g.doubleclick.net domain in the Chrome DevTools network panel. If you don't see that request, check to make sure there are no errors in the Chrome DevTools Console.

TRY IT

Add AdsLoader event handlers

Now that you've made an ad request, you need to handle the response and play the ads. The first step is to get the AdsManager created by the SDK when the ad response resolves. To do this, add new event listeners to the AdsLoader for the ADS_MANAGER_LOADED and AD_ERROR events. ADS_MANAGER_LOADED fires when your AdsManager is successfully created (explained in the next steps), and AD_ERROR is fired if something goes wrong in creating the AdsManager. You'll add the methods to handle these events in the next step.

ads.js

function setUpIMA() {
  ...
  // BEGIN NEW CODE
  adsLoader.addEventListener(
      google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
      onAdsManagerLoaded,
      false);
  adsLoader.addEventListener(
      google.ima.AdErrorEvent.Type.AD_ERROR,
      onAdError,
      false);
  // END NEW CODE
  adsLoader.requestAds(adsRequest);
}

Handle AdLoader errors

Before handling the success case, make sure you have a handler for a failed ad load. When the AdsLoader fires an AD_ERROR, something has gone fatally wrong when loading ads, like a network error or a malformed VAST response, so just play your content as shown below.

ads.js

function onAdError(adErrorEvent) {
  console.log(adErrorEvent.getError());
  videoContent.play();
}

Get the AdsManager and add AdsManager event handlers

Now you'll write the event handlers for these events. In onAdsManagerLoaded, get a handle to the AdsManager and set up these event handlers as shown in the code that follows:

ads.js

// BEGIN NEW CODE 1/3
let adsManager;
// END NEW ODE 1/3
...
// BEGIN NEW CODE 2/3
function onAdsManagerLoaded(adsManagerLoadedEvent) {
  const adsRenderingSettings = new google.ima.AdsRenderingSettings();
  adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true;
  
  adsManager = adsManagerLoadedEvent.getAdsManager(
      videoContent, adsRenderingSettings);
  adsManager.addEventListener(
      google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED,
      onContentPauseRequested);
  adsManager.addEventListener(
      google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED,
      onContentResumeRequested);
  adsManager.addEventListener(
      google.ima.AdEvent.Type.LOADED,
      onAdLoaded);
  adsManager.addEventListener(
      google.ima.AdErrorEvent.Type.AD_ERROR,
      onAdError);
}

function onContentPauseRequested() {
  videoContent.pause();
}

function onContentResumeRequested() {
  videoContent.play();
}

function onAdLoaded(adEvent) {
  if (adEvent.type == google.ima.AdEvent.Type.LOADED &&
      !adEvent.getAd().isLinear()) {
    videoContent.play();
  }
}
// END NEW CODE 2/3

function onAdError(adErrorEvent) {
  console.log(adErrorEvent.getError());
  // BEGIN NEW CODE 3/3
  if (adsManager) {
    adsManager.destroy();
  }
  // END NEW CODE 3/3
  videoContent.play();
}

This step doesn't change the appearance of the web page. When you test it, check to make sure there are no errors in the Chrome DevTools Console.

TRY IT

Now that you've requested ads and created an AdsManager, the last step is to play the ads. This requires changes in three places, as shown in the code snippets below.

  1. In onPlayClicked, set the playClicked flag to true and, if the AdsManager has loaded, call playAds().
  2. In onAdsManagerLoaded(), call playAds() if the play button has already been clicked.
  3. In playAds()
  1. initialize the AdDisplayContainer by calling adDisplayContainer.initialize()
  2. initialize the AdsManager by calling adsManager.init(...) with the width, height, and ViewMode of your player (ViewMode.NORMAL for inline playback, and ViewMode.FULLSCREEN for fullscreen playback
  3. star the AdsManager by calling adsManager.start().

ads.js

...
let playClicked;
...
// CHANGE TO AN EXISTING METHOD
function onPlayClicked() {
  // videoContent.play();
  playClicked = true;
  if (adsManager) {
    playAds();
  }
}

function onAdsManagerLoaded(adsManagerLoadedEvent) {
  ...
  if (playClicked) {
    playAds();
  }
}

function playAds() {
  adDisplayContainer.initialize();
  adsManager.init(640, 360, google.ima.ViewMode.NORMAL);
  adsManager.start();
}

After this step, you should see ads before, during, and after the content video.

TRY IT

Companion Ads extension

The VAST spec has support built-in for a standard display ad type called companion ads. Companion ads are banner ads served with your video ad that are designed to work with the ad - for example, a banner ad for the car that your video ad is currently showing off. Companion ads can also stick around after the ad finishes and the user is watching your content. To add a companion ad to your sample, add a companion div to your HTML and the Google Publisher Tag (GPT) library boilerplate to register that companion ad.

index.html

<html>
  <head>
    <title>IMA HTML5 Simple Demo</title>
    <link rel="stylesheet" type="text/css" href="style.css">
    <!-- BEGIN NEW CODE 1/2 -->
    <script type='text/javascript'>
      var googletag = googletag || {};
      googletag.cmd = googletag.cmd || [];
      (function() {
        var gads = document.createElement('script');
        gads.async = true;
        gads.type = 'text/javascript';
        gads.src = '//www.googletagservices.com/tag/js/gpt.js';
        var node = document.getElementsByTagName('script')[0];
        node.parentNode.insertBefore(gads, node);
      })();
    </script>

    <!-- Register your companion slot -->
    <script type='text/javascript'>
      googletag.cmd.push(function() {
         googletag.defineSlot('/124319096/external/single_ad_samples', [728, 90], 'companionDiv')
            .addService(googletag.companionAds())
            .addService(googletag.pubads());
        googletag.companionAds().setRefreshUnfilledSlots(true);
        googletag.pubads().enableVideoAds();
        googletag.enableServices();
      });
    </script>
    <!-- END NEW CODE 1/2 -->
  </head>

  <body>
    <div id="mainContainer">
      <div id="content">
        <video id="contentElement">
          <source src="//s0.2mdn.net/4253510/google_ddm_animation_480P.mp4"></source>
          <source src="//s0.2mdn.net/4253510/google_ddm_animation_480P.webm"></source>
        </video>
      </div>
      <div id="adContainer"></div>
    </div>
    <!-- BEGIN NEW CODE 2/2 -->
    <div id="companionDiv" style="width:728px; height:90px;">
       <script type="text/javascript">
         googletag.cmd.push(function() { googletag.display('companionDiv'); });
       </script>
    </div>
    <!-- END NEW CODE 2/2 -->
    <button id="playButton">Play</button>
    <script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3.js"></script>
    <script type="text/javascript" src="ads.js"></script>
  </body>
</html>

You should see a sample companion ad below your video player.

TRY IT

Autoplay extension

Mobile browsers, and recently some desktop browsers, no longer allow you to autoplay any video on a web page. Instead, your video player returns a promise when you call play() that tells you if the play was allowed or not. Take advantage of this returned promise to determine if autoplay videos are allowed, and update your ad request accordingly.

Refactor the AdsRequest code

First separate your AdsRequest code from the setUpIMA() method, as shown below. You'll need to delay requesting ads until you know if the current environment will allow you to autoplay video or not, which you'll discover through the code that follows.

ads.js

function setUpIMA() {
  adDisplayContainer = new google.ima.AdDisplayContainer(
      document.getElementById('adContainer'), videoContent);
  
  adsLoader = new google.ima.AdsLoader(adDisplayContainer);

  videoContent.onended = () => {adsLoader.contentComplete();};

  adsLoader.addEventListener(
    google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
      onAdsManagerLoaded,
      false);
  adsLoader.addEventListener(
      google.ima.AdErrorEvent.Type.AD_ERROR,
      onAdError,
      false);
}

function requestAds() {
  const adsRequest = new google.ima.AdsRequest();
  adsRequest.adTagUrl = 'https://pubads.g.doubleclick.net/gampad/ads?' +
      'sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&' +
      'ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&' +
      'unviewed_position_start=1&' +
      'cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&cmsid=496&' +
      'vid=short_onecue&correlator=';
  adsRequest.setAdWillAutoPlay(autoplayAllowed);
  adsRequest.setAdWillPlayMuted(autoplayRequiresMuted);
  adsRequest.linearAdSlotWidth = 640;
  adsRequest.linearAdSlotHeight = 360;
  adsRequest.nonLinearAdSlotWidth = 640;
  adsRequest.nonLinearAdSlotHeight = 150;

  adsLoader.requestAds(adsRequest);
}

Hide the play button (for now)

If autoplay works, your users won't need the play button. You should hide the play button until you know that users need it. To hide the play button, add the following to the style.css file.

style.css

#playButton {
  display: none;
  ...
}

Check for autoplay support

Check if you can autoplay your content video using the code below.

ads.js

let autoplayAllowed;
let autoplayRequiresMuted;

function init() {
  ...
  // Add call to checkAutoPlaySupport before setUpIMA.
  checkAutoplaySupport();
  setUpIMA();
}

function checkAutoplaySupport() {
  videoContent.play().then(onUnmutedAutoplaySuccess, onUnmutedAutoplayFail);
}

function onUnmutedAutoplaySuccess() {
  videoContent.pause();
  autoplayAllowed = true;
  autoplayRequiresMuted = false;
  requestAds();
}

function onUnmutedAutoplayFail() {
  checkMutedAutoplaySupport();
}

function checkMutedAutoplaySupport() {
  videoContent.volume = 0;
  videoContent.muted = true;
  videoContent.play().then(onMutedAutoplaySuccess, onMutedAutoplayFail);
}

function onMutedAutoplaySuccess() {
  videoContent.pause();
  autoplayAllowed = true;
  autoplayRequiresMuted = true;
  requestAds();
}

function onMutedAutoplayFail() {
  videoContent.volume = 1.0;
  videoContent.muted = false;
  autoplayAllowed = false;
  autoplayRequiresMuted = false;
  requestAds();
}

Play ads automatically

Modify the playClicked conditional in onAdsManagerLoaded to either allow for autoplay or show the play button if autoplay isn't allowed.

ads.js

function onAdsManagerLoaded(adsManagerLoadedEvent) {
  ...
  if (playClicked || autoplayAllowed) {
    playAds();
  } else if (!autoplayAllowed) {
    playButton.style.display = 'block';
  }
}

The page should autoplay with volume, autoplay without volume, or show you a play button, depending on the settings of your browser.

TRY IT

You've reached the end of the codelab - you can now integrate the IMA SDK into your own HTML5 video player.

Learn more