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 Invidi 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.vp.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.
- 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');
- 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:
- 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');
- 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(...);
});
- 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!
- Register all the events the video player needs:
content.addEventListener('play', onPlay);
content.addEventListener('pause', onPause);
content.addEventListener('timeupdate', onTimeUpdate);
content.addEventListener('ended', onEnded);
- 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();
}
}
- 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);
}
- 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.
- 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:
- setting certain attributes to conform to autoplay requirements imposed by the browser
- 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';
}