Using the Pulse Ad Player

This tutorial demonstrates how to integrate the Pulse Ad Player with an HTML5 video element.

Project Setup

Create a new HTML file, index.html, displaying a simple MP4 video, using an HTML5 video element, and including the Pulse SDK.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>HTML5 video with Pulse</title>
    <!-- typically, this should be loaded from the Ooyala CDN using your site id-specific domain name. -->
    <script src="http://pulse-demo.videoplaza.tv/proxy/pulse-sdk-html5/2.1/latest.min.js"></script>
  </head>
  <body style="background-color: black">
    <div id="container" style="width:640px;height:360px; position: relative ;margin:auto">
      <div id="video_container" style="position:absolute;width:100%;height:100%">
        <video id="video_player" style="position:absolute;width:100%;height:100%" controls>
          <source src="http://pulse-demo.cdn.videoplaza.tv/resources/media/sintel_trailer_854x480.mp4" type="video/mp4">
        </video>
      </div>
      <div id="adContainer" style="position:absolute;opacity:1;width:100%;height:100%;top:0px;left:0px;display:none"></div>
    </div>
  </body>
</html>

To display the two players on top of each others, create a container div which holds both the content player and the Ad Player. The adContainer div will host our Ad Player!

Open index.html in our browser and verify that the HTML5 video is visible and playable. You now have the initial setup to integrate ads with the HTML5 player!

Starting New Script and Declaring Variables

Add a new script to your page to write the code to integrate the Ad Player with the HTML5 video.

  1. Start by retrieving references to the different UI components to control them later:

    var content = document.getElementById('video_player');
    var videoContainer = document.getElementById('video_container');
    var adContainer = document.getElementById('adContainer');
  2. Declare a Pulse session and an Ad Player:

    var session = null;
    var adPlayer = null;

Creating the Ad Player

Then configure the Pulse SDK and create the Ad Player:

  1. Pass the Pulse host URL to the SDK with OO.Pulse.setPulseHost. For the purpose of this tutorial, we are using a Pulse demo account, but feel free to use your own account if you have one.

    OO.Pulse.setPulseHost('http://pulse-demo.videoplaza.tv');
  2. Create the Pulse session with your request parameters. Use the OO.Pulse.createSession method to create a session. It takes two parameters:

If you use the Pulse demo account, then specify the tag standard-linears for this demo. In this Pulse account, we have a set of standard linear ads that you can use to validate your integration.

Use the request settings to give the cue points where you want to insert mid-roll ad breaks.

  var contentMetadata = {
    tags: [ 'standard-linears' ]
  };

  var requestSettings = {
    linearPlaybackPositions: [ 10, 20 ] // Request 2 mid-roll breaks
    nonlinearPlaybackPositions: [ 5, 25 ] // .. and 2 overlays
  };

Create the session object. Behind the scenes, the Pulse SDK makes the ad request to Pulse.

  session = OO.Pulse.createSession(contentMetadata, requestSettings);

If the SDK is loaded dynamically and you want to know when the SDK is ready, you can use the pulseready DOM event:

  document.addEventListener('pulseready', function() {
    // OO.Pulse can now safely be used
    OO.Pulse.createSession(...);
  });
  1. Create the Ad Player with OO.Pulse.createAdPlayer. createAdPlayer can take some extra parameters, but they are not necessary for a basic integration.
    adPlayer = OO.Pulse.createAdPlayer({ adContainerElement: adContainer });

The Ad Player will display its ads within the provided element.

Implementing the OO.Pulse.AdPlayerListener Interface

Next step is to implement the OO.Pulse.AdPlayer.Listener interface, which the player uses to control the content player. Any reference to the variable content below is the instance of HTMLVideoElement, from the <video> tag used to play the main video content.

var adPlayerListener = {
  // Here, the Ad Player is telling the integration to start (or resume) playing the main content
  startContentPlayback: function() {
    content.play();
    videoContainer.style.display = 'block'; // or any other means to make the content player visible
  },

  // The Ad Player is telling the integration to pause the main content, so linear ads can be played
  pauseContentPlayback: function() {
    content.pause();
    videoContainer.style.display = 'none'; // or any other means to make the content player invisible
  },

  // If you tell the Ad Player to perform some action which is unexpected due to
  // the current state, this function is called to let the integration know
  illegalOperationOccurred: function(message) {
    console.warn('Illegal operation: ', message);
  },

  // The content finished playback, and if any post-rolls were served, they also finished
  sessionEnded: function() {
    videoContainer.style.display = 'block';
  },

  // When the viewer clicks an ad, this function is called to let the integration know, and provide
  // it with the information needed to open the clickthrough URL
  openClickThrough: function(url) {
    window.open(url);

    // Tell the Ad Player the clickthrough URL was opened, so the associated VAST event can be tracked
    adPlayer.adClickThroughOpened();
  }
};

In summary:

  • startContentPlayback is typically called when the Ad Player is done playing ads. In this case, hide your video player when the ads start and show it when the content starts.
  • illegalOperationOccurred is called when some conflicting events are reported to the Ad Player by the integration code. For example, continuing to report time updates for the content after pauseContentPlayback has been called.
  • sessionEnded is called by the Ad Player when both the content and any post-rolls have finished playing.
  • openClickThrough is called when an ad (typically a VPAID ad) requested a clickthrough link to be opened. It is then up to the integration to open the URL or not. If the link is opened, the SDK must be notified through adClickThroughOpened.

Connecting the Video Player events to the Ad Player

The last part of the integration is to connect the video player to the Ad Player, so it knows when to display ads. In the case of HTML5, it is also extremely easy!

  1. Register all the events the video player needs:

    content.addEventListener('play', onPlay);
    content.addEventListener('pause', onPause);
    content.addEventListener('timeupdate', onTimeUpdate);
    content.addEventListener('ended', onEnded);
  2. When the content starts, the Ad Player should start the ad session and pause the content (so pre-rolls are loaded if there are any).

    var initialPlay = true;
    
    function onPlay() {
     if(initialPlay) {
       initialPlay = false;
       content.pause(); // Pause the content so we can play pre-rolls
       adPlayer.startSession(session, adPlayerListener); // Start the Ad Player event flow
     } else {
       // When the content is resumed, call contentStarted
       adPlayer.contentStarted();
     }
    }
  3. The Ad Player needs to get the time updates from the content player, so it can trigger mid-roll ads.

    function onTimeUpdate() {
     adPlayer.contentPositionChanged(content.currentTime);
    }
  4. The Ad Player needs information on when the content is paused, so pause ads can be shown.

    function onPause() {
     // Let the Ad Player know the content is paused
     adPlayer.contentPaused();
    }

    If you implement pause handling, you must also implement a way to close the pause ads in one of the following ways:

    • Use the Ad Player skin, which contains a close button that sends the correct event to the SDK. This skin is located at HTML5 Ad Player Skins.
    • Implement your own close button for pause ads. This button should call adPlayer.pauseAdClosed().
    • Make sure that the content player's play button is still visible on top of the pause ad. When the viewer resumes the content with the play button, causing adPlayer.contentStarted() to be called, the pause ad closes automatically.
  5. Lastly, it needs to know when the content ends so post-rolls can be shown.

    function onEnded() {
     adPlayer.contentFinished();
    }

At this point, you should be able to see ads when you play the video. All the tracking logic is handled by the Pulse SDK.

Listen to Ad Player Events

The Ad Player fires different events that can be used to implement clickthrough, UI options, and so on. The tutorial only implements the clickthrough.

When the Ad Player is clicked, it fires an event OO.Pulse.AdPlayer.Events.AD_CLICKED that the integration can listen to. The event contains the URL to open. To listen to Ad Player events, you need to register them using addEventListener Ad Player instance.

// Register the clickthrough event listener
adPlayer.addEventListener(OO.Pulse.AdPlayer.Events.AD_CLICKED, function(event, data) {
  window.open(data.url);
  // Tell the SDK we opened the clickthrough URL
  adPlayer.adClickThroughOpened();
});

Overlay position

The Ad Player displays overlays with a 70% width and a bottom margin of 10% by default. If you want to change these settings, it can be done in CSS by using the pulse-overlay class. The overlay div can be directly manipulated by calling the getOverlayDiv API.

adPlayer.getOverlayDiv().style.width = '60%'; // change the overlay div width to 60%

You now have a working implementation of the Pulse Ad Player with an HTML5 video!

Enforcing mid-roll playback after seek/scrub actions

By default, viewers are allowed to seek (or scrub) through video content without mid-roll ad breaks getting triggered. However, if you want to enforce the playback of one or more of the unplayed mid-roll ad breaks, then use the seekMode parameter in the RequestSettings.

For example, to always play the last ad break, which is closest to the new position in the video content:

session = OO.Pulse.createSession(contentMetadata, { seekMode: OO.Pulse.SeekMode.PLAY_LAST });

In this case, when the session is started through startSession, the viewer is still shown the last ad break out of the ones that were skipped when seeking. See SeekMode, for all possible options of which mid-roll breaks to show.

To ensure ad breaks do not trigger prematurely, do not send contentPositionChanged updates until the viewer has stopped scrubbing!

Handling autoplay

On some platforms, most notably mobile web browsers, but also in Safari 11 on desktop, video elements are typically not allowed to autoplay unless the user has interacted with them first. If special care is not taken to handle this case, the viewer may be required to click play an additional time when the first ad is shown. With the Pulse Ad Player, there are two potential solutions:

  1. setting certain attributes to conform to autoplay requirements imposed by the browser
  2. sharing the element used for content and ad playback

The attribute method is recommended for desktop browsers, and is quite simple, while sharing the element is recommended for mobile browsers and requires some additional implementation work.

Automatically setting autoplay attributes

  var useAutoplayAttributes = false;

  if(OO.Pulse.getAutoplayMode() === OO.Pulse.AutoplayMode.MUTED) {
    useAutoplayAttributes = true;
  }

  adPlayer = OO.Pulse.createAdPlayer({ adContainerElement: adContainer, setAutoplayAttributes: useAutoplayAttributes });

Sharing the content player element

  var sharedElement;

  if(OO.Pulse.getAutoplayMode() === OO.Pulse.AutoplayMode.SHARED) {
    sharedElement = content;
  }

  adPlayer = OO.Pulse.createAdPlayer({ adContainerElement: adContainer, sharedElement: sharedElement });

OO.Pulse.getAutoplayMode can aid you in determining how to make sure autoplay functionality works as expected.

This way, the initial user action of clicking play on the content element allows the Ad Player to automatically start subsequent ad videos without user input. When the element is shared this way, the Ad Player currently does not restore the src attribute of the video element, so it must be saved prior to ad playback and restored manually in startContentPlayback:

  var contentSrc;

  function onPlay() {
    if(initialPlay) {
      contentSrc = content.src;
      initialPlay = false;
      content.pause(); // Pause the content so we can play pre-rolls
      adPlayer.startSession(session, adPlayerListener); // Start the Ad Player event flow
    } else {
      // When the content is resumed, call contentStarted
      adPlayer.contentStarted();
    }
  }
  // Within the ad player listener interface, adPlayerListener:
  startContentPlayback: function() {
    // Restore the previously saved source
    content.src = contentSrc;
    content.play();
    videoContainer.style.display = 'block';
  }