Get started with Pod Serving

IMA SDKs make it easy to integrate multimedia ads into your websites and apps. IMA SDKs can request ads from any VAST-compliant ad server and manage ad playback in your apps. With IMA DAI SDKs, apps make a stream request for ad and content video—either VOD or live content. The SDK then returns a combined video stream, so that you don't have to manage switching between ad and content video within your app.

This guide demonstrates how to play a DAI Pod Serving stream, using the IMA HTML5 DAI SDK with a simple video player that relies on hls.js for playback. If you would like to view or follow along with a completed sample integration, with support for both HLS.js and Safari Playback, download the pod serving example or try our hosted example.

IMA DAI Pod Serving overview

Implementing pod serving using the IMA HTML5 DAI SDK involves two main components, which are demonstrated in this guide:

  • PodservingStreamRequest: An object that defines a stream request to Google's advertising servers. Requests specify a Network Code, Custom Asset Key, and an optional API key, as well as other optional parameters.
  • StreamManager: An object that handles communication between the video stream and the IMA DAI SDK, such as firing tracking pings and forwarding stream events to the publisher.

Prerequisites

Before you begin, you need the following:

  • Three empty files
    • dai.html
    • dai.css
    • dai.js
  • Python installed on your computer, or a web server or other hosted development environment to use for testing

1. Configure a development environment

Since the IMA SDK loads dependencies via the same protocol as the page from which it's loaded, you need to use a web server to test your app. The simplest way to start a local development server is to use Python's built-in server.

  1. Using a command line, from the directory that contains your index.html file run:

    python -m http.server 8000
    
  2. In a web browser, go to to http://localhost:8000/

You can also use any other hosted development environment or web server, such as the Apache HTTP Server.

2. Create a simple video player

First, modify dai.html to create a simple HTML5 video element and a div to use for Ad UI elements. Also add the necessary tags to load the dai.css and dai.js files, as well as to import the hls.js video player. Then, modify dai.css to specify the size and position of the page elements. Finally, in dai.js, define variables to hold the stream request information and an initPlayer() function to run when the page loads.

The stream request constants are as follows:

  • BACKUP_STREAM: A url for a backup stream to play, in case the IMA ads process encounters a fatal error, to preserve user experience.
  • STREAM_URL: The video stream url provided by your manifest manipulator or 3rd party partner using Pod Serving. It should require you to insert the stream ID provided by the IMA DAI SDK, before you make a request. In this case, the stream url includes a placeholder, [[STREAMID]], which will be replaced with the stream ID, before making a request.
  • NETWORK_CODE: The network code for your AdManager360 account.
  • CUSTOM_ASSET_KEY: The custom asset key that identifies your pod serving event in AdManager360. This may be created by your manifest manipulator or 3rd party pod serving partner.
  • API_KEY: An optional API key that can be required to retrieve a Stream ID from the IMA DAI SDK.

dai.html


<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script src="dai.js"></script>
  <link rel="stylesheet" href="dai.css" type="text/css">
</head>
<body onLoad="initPlayer()">
  <h2>IMA SDK DAI Demo (HLS.JS)</h2>
    <video id="video"></video>
    <div id="ad-ui"></div>
</body>
</html>

dai.css

#video,
#ad-ui {
  width: 640px;
  height: 360px;
  position: absolute;
  top: 35px;
  left: 0;
}

#ad-ui {
  cursor: pointer;
}

dai.js

var BACKUP_STREAM =
    'https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8'

// Stream Config.
const STREAM_URL   = "https://encodersim.sandbox.google.com/masterPlaylist/9c654d63-5373-4673-8c8d-6d92b66b9d46/master.m3u8?gen-seg-redirect=true&network=51636543&event=google-sample&pids=devrel4628000,devrel896000,devrel3528000,devrel1428000,devrel2628000,devrel1928000&seg-host=dai.google.com&stream_id=[[STREAMID]]";
const NETWORK_CODE     = "51636543";
const CUSTOM_ASSET_KEY = "google-sample";
const API_KEY          = "";

var hls = new Hls(); // hls.js video player
var videoElement;
var adUiElement;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
}

3. Load the IMA SDK

Next, add the IMA framework using a script tag in dai.html, before the tag for dai.js.

dai.html

<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3_dai.js"></script>
  <script src="dai.js"></script>
  <link rel="stylesheet" href="dai.css" type="text/css">
</head>

...

4. Initialize the StreamManager and make a stream request

In order to request a set of ads, create an ima.dai.api.StreamManager, which is responsible for requesting and managing DAI streams. The constructor takes a video element and the resulting instance takes an ad UI element to handle ad interactions.

Then, define a function to request the pod serving stream. This function first creates a PodStreamRequest, configures it with the streamRequest parameters provided in step 2, and then calls streamManager.requestStream() with that request object.

dai.js

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)

  requestPodStream(NETWORK_CODE, CUSTOM_ASSET_KEY, API_KEY);
}

function requestPodStream(networkCode, customAssetKey, apiKey) {
  // clear HLS.js instance, if in use
  if (hls) {
    hls.destroy();
  }

  // Generate a PodServing Stream Request
  const streamRequest = new google.ima.dai.api.PodStreamRequest();
  streamRequest.networkCode = networkCode;
  streamRequest.customAssetKey = customAssetKey;
  streamRequest.apiKey = apiKey;
  streamManager.requestStream(streamRequest);
}

5. Handle stream events

Next, implement event listeners for major video events. This simple example handles the STREAM_INITIALIZED, ERROR, AD_BREAK_STARTED and AD_BREAK_ENDED events by calling an onStreamEvent() function. This function handles stream loading and errors, as well as disabling the player controls while an ad is playing, which is required by the SDK. When the stream is loaded, the video player loads and plays the provided URL using a loadStream() function.

dai.js

var isAdBreak;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
  
  streamManager.addEventListener(
    [google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
     google.ima.dai.api.StreamEvent.Type.ERROR,
     google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
     google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
    onStreamEvent,
    false);

...

function onStreamEvent(e) {
  switch (e.type) {
    case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
      console.log('Stream initialized');
      loadStream(e.getStreamData().streamId);
      break;
    case google.ima.dai.api.StreamEvent.Type.ERROR:
      console.log('Error loading stream, playing backup stream.' + e);
      loadStream('');
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
      console.log('Ad Break Started');
      isAdBreak = true;
      videoElement.controls = false;
      adUiElement.style.display = 'block';
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
      console.log('Ad Break Ended');
      isAdBreak = false;
      videoElement.controls = true;
      adUiElement.style.display = 'none';
      break;
    default:
      break;
  }
}

function loadStream(streamID) {
  var url;
  if(streamID) {
    url = STREAM_URL.replace('[[STREAMID]]', streamID);
  } else {
    console.log('Stream Initialization Failed');
    url = BACKUP_STREAM;
  }
  console.log('Loading:' + url);
  hls.loadSource(url);
  hls.attachMedia(videoElement);
}

6. Handle player events

Next, implement event listeners for ID3 metadata, to notify the IMA SDK when ad events occur. Also add event listeners to the video element's pause and start events to allow the user to resume playback when the IMA pauses during ad breaks.

Finally, to automatically play the video once everything is loaded and ready, connect a handler to hls.js' MANIFEST_PARSED event, to trigger playback.

dai.js

...

function loadStream(streamID) {
  ...
  hls.loadSource(url);
  hls.attachMedia(videoElement);
  
  // Timed metadata is passed HLS stream events to the streamManager.
  hls.on(Hls.Events.FRAG_PARSING_METADATA, parseID3Events);
  hls.on(Hls.Events.MANIFEST_PARSED, startPlayback);
  
  videoElement.addEventListener('pause', onStreamPause);
  videoElement.addEventListener('play', onStreamPlay);
}

function parseID3Events(event, data) {
  if (streamManager && data) {
    // For each ID3 tag in the metadata, pass in the type - ID3, the
    // tag data (a byte array), and the presentation timestamp (PTS).
    data.samples.forEach((sample) => {
      streamManager.processMetadata('ID3', sample.data, sample.pts);
    });
  }
}

function startPlayback() {
  console.log('Video Play');
  videoElement.play();
}

function onStreamPause() {
  console.log('paused');
  if (isAdBreak) {
    videoElement.controls = true;
    adUiElement.style.display = 'none';
  }
}

function onStreamPlay() {
  console.log('played');
  if (isAdBreak) {
    videoElement.controls = false;
    adUiElement.style.display = 'block';
  }
}

That's it! You're now requesting and displaying ads in a pod serving stream with the IMA HTML5 DAI SDK. To learn about more advanced SDK features, see the other guides or the samples on GitHub.