Contains the technical steps and processes to implement the Integral Ad Science (IAS) web video SDK without the need to wrap individual tags. IAS's web video SDK is a VPAID-like API which allows you to access the IAS Campaign Monitoring (CM) and Open Web technology which includes brand safety, fraud, and viewability features.
This document outlines the technical steps and processes to implement the Integral Ad Science (IAS) web video SDK without the need to wrap individual tags. IAS's web video SDK is a VPAID-like API which allows you to access the IAS Campaign Monitoring (CM) and Open Web technology which includes brand safety, fraud, and viewability features. In addition, the web video SDK offers video blocking in the form of blocking recommendation based on brand safety and fraud detection signals. The web video SDK is built with the latest video technology and is available for HTML5 (The Flash SDK, which went up to version 3.4.2, is no longer maintained. The Flash deprecation plan is under review by the IAS team). The IAS web video SDK (in the code as 'VANS') is a compile-in solution to your VPAID ad unit or Player/AdManager (as a plugin or extension module) which acts as a fly-on-the-wall for video events and data throughout the video playback cycle managed by your VPAID AD Unit or Player/AdManager. The web video SDK operates in two modes: CM and Open Web.
CM mode captures viewability, fraud, and brand safety data for measurement.
Open Web mode allows the integrator to detect in real-time if an impression presents a risk and block the ad accordingly.
The web video SDK HTML5 API has initialization methods for each solution, each with its own configuration options and macros detailed further below.
Typically, integrations measure each ad impression using one of the following (see diagrams for 1-3 below):
a single instance of the CM solution
a single instance of the Open Web solution
a single instance of both a CM and a Open Web solution
two instances of the CM solution
Note that this discussion is limited to the web video SDK and does not address scenarios where tags are also wrapped using the IAS VPAID Wrapper product. Confirm with IAS if you are unsure what to implement.
Whatever mode (or modes) of the web video SDK you implement as part of your integration, the lifecycle for an ad session comprises initialization, where you instantiate the SDK in Open Web or CM mode and it begins listening for signals from an ad; event handling, where you pass events to the SDK instance(s) during the ad lifecycle; and ad-end, where the integration asynchronously unloads data to servers. Caveats and best practices for each of these lifecycle stages are addressed later in this guide.
This guide describes an integration option (an HTML5 adapter) that allows Ad Platforms/Exchanges/Ad servers/Video Players to easily enable IAS video solutions for specific portions of the traffic without the need to change the video ad tags served. The web video SDK is available through your IAS Solutions Engineering contact.
Read the rest of this section to familiarize yourself with the high-level details and to confirm technical requirements
Read through the Walkthrough section for your appropriate integration
Complete the initial implementation
Read through the Pre-Certification Testing Self-Checklist - use the Topic Guides, API reference, Implementation Best Practices, and examples in Code Samples to confirm you met all requirements
The diagrams on the following pages detail the sequence of expected interactions throughout an ad lifecycle for a web video SDK integration.
CM mode, VPAID ad unit integration
Open Web mode, VPAID ad unit integration, ad not blocked
CM + Open Web mode, VPAID ad unit integration, ad not blocked
CM mode, Player/AdManager integration
The HTML5 web video SDK supports two types of integrations:
VPAID ad unit integrations, where the integration is served as part of the VPAID ad unit,
video player/AdManager integrations, where the integration is served as a plugin or extension to the player or AdManager.
This table presents a high-level overview of the two different types of integrations, as well as summaries of the way that significant lifecycle processes (initialization, ad-end, event passthrough) should be handled. These instructions are covered in-depth below.
Component to be Integrated With | VPAID ad unit | Player / AdManager |
High-level Summary | The web video SDK is loaded with the VPAID ad unit, receives events and data through the ad lifecycle, and is destroyed along with the VPAID at at-end. | The web video SDK is loaded as an extension or plugin to the player or an AdManager and receives events and data as the player/AdManager handles the ad lifecycle. |
Initialization Handling | Before the ad is loaded. | Before each ad is loaded. |
Event logic Handling | Send VPAID 2.0 events as they occur, following web video SDK certification-compliant guidelines. | Use IAB event mapping when corollaries exist. You may confirm event and data mapping with IAS. |
Ad-end Logic Handling | IAS recommends delegating script execution environment destruction to the web video SDK to avoid losing crucial measurement data. | No specific instructions. |
Testing Requirements | Provide IAS with sample VPAID ads containing the web video SDK integration. | Provide IAS with a test page containing creatives, your player/AdManager, and the web video SDK integration. |
The web video SDK injects a script element with the web video API bridge listener in the same document it is in to process video events and handle measurement logic. Notify IAS if your SDK or execution environment precludes dynamic script injection of the IAS listener.
You can check that this is correctly injected by searching for an element with the attribute data-ias-script-tag="found".
Event calls and data are sent to a web video SDK instance from your SDK are asynchronously passed in real-time to the listener, which sends data to the IAS server throughout the video lifecycle.
If you overwrite any of the browser API globals, notify IAS so IAS can confirm this will not lead to conflicts with IAS's measurement logic.
To facilitate communication between you and the IAS engineering team throughout the integration and QA process, please upload your integration code to a private GitHub Gist and make that URL available to your IAS representative. Additionally, to ensure IAS stays coordinated on both sides, please update the Gist when you make a change to the integration code throughout the QA process.
(VPAID integrations only) Ad-end handling: At the end of every video ad session, IAS sends all event calls asynchronously from the listener (note that this is not from the IAS script itself), which are subject to interruption by VPAID destruction processes. See the Ad End Processes section for details on how best to troubleshoot and prevent this.
This section walks through an integration with a generic VPAID ad unit. Code Samples contains links to full code samples.
The first step is to initialize the web video SDK. Ensure that the web video SDK is loaded before the ad is loaded.
Instantiate the web video SDK constructor (__IASVANS) and, depending on your integration type, call its initCM or initFW method, being sure to pass in a configuration object with all necessary properties, the VPAID ad slot, and (Open Web blocking integrations only) a blocking callback.
As a best practice, IAS recommends allowing the web video SDK to handle any ad destruction processes (here, this._stopAd) by delegating to config.onMeasurementCallback, so that the integration's execution context remains intact until all ad-end measurements are successfully processed.
Here is an example of Open Web initialization, with a blocking callback passed in:
// init the web video SDK this.fwVansInstance_ = __IASVANS(); var adNode = this._slot;
// Open Web blocking var fwConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
advEntityId: 'YOUR-IAS-PROVIDED-ADV-ENTITY-ID',
pubEntityId: 'YOUR-IAS-PROVIDED-PUB-ENTITY-ID',
impId: 'PROVIDE-YOUR-OWN-IMPRESSION-ID',
onMeasurementComplete: this.stopAd.bind(this),
ias_xps:"autoplayed", // video context parameter for autoplay status
ias_xbp:"2", // video context parameter for video placement type
ias_xar: "1" // video context parameter for autorefresh status
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
// proceed with ad if IAS blocking instructions are not received in time.
var blockingInstructionsTimeout = setTimeout(this.callEvent_('AdLoaded'), 1500);
// provide a blocking callback
var blockingCallback = function (result) {
if (result === 'block') {
this.integral_timeout_ = new Date().valueOf() - blockingTimeoutStart; this.callEvent_('AdBlocked');
}
else if (result === 'safe') {
this.callEvent_('AdLoaded'); }
};
// start the blocking timeout before initFW
var blockingTimeoutStart = new Date().valueOf();
this.fwVansInstance_.initFW(config, adNode, blockingCallback);
Here is a CM example with advertiser macros. For an example of a CM initialization with publisher macros, see Code Samples.
// init the web video SDK
this.cmVansInstance_ = __IASVANS(); var adNode = this._slot;
// advertiser
var cmConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE', anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID', advId: 'PROVIDE-YOUR-OWN-ADV-ID',
campId: 'PROVIDE-YOUR-OWN-CAMP-ID', creativeId: 'PROVIDE-YOUR-OWN-CREATIVE-ID', placementId: 'PROVIDE-YOUR-OWN-PLACEMENT-ID', chanId: 'PROVIDE-YOUR-OWN-CHANNEL-ID',
impId: 'PROVIDE-YOUR-OWN-IMPRESSION-ID',
onMeasurementComplete: this.stopAd.bind(this),
ias_xps:"autoplayed", // video context parameter for autoplay status
ias_xbp:"2", // video context parameter for video placement type
ias_xar: "1" // video context parameter for autorefresh status
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
this.cmVansInstance_.initCM(config, adNode);
After initializing your instance of the web video SDK, use sendEvent to send events to it throughout the ad lifecycle. Note that some event names must be mapped to resizeAd. Details on events and contextual parameters required for certification may be found below.
IAS's recommended implementation wraps your event-sending logic and creates an object with the required context every time a pertinent event is received.
The AdImpression object has two required properties for Open Web blocking integrations:
integral_timeToDecision
integral_didBlock
Open Web Example
if (this.fwVansInstance_) {
var vansEventName,
adContext = {
ad_duration: this.getAdDuration(), volume: this.getAdVolume()
};
if (eventType === 'AdSizeChange') {
// add viewMode when it is necessary for context
adContext.viewMode = this.attributes_['viewMode'];
}
// remap name of event sent to IAS when needed
if ( ['AdSizeChange', 'AdExpanded', 'AdUserMinimize'].indexOf(eventType) > 0 ) {
// no adUserMinimize in this implementation of VPAID
vansEventName = 'resizeAd';
} else {
vansEventName = eventType;
}
// add additional attributes to Open Web ad impression
if (eventType === 'AdImpression') {
var timeToDecisionWhenTimedOut = new Date().valueOf();
adContext.integral_timeToDecision = this.integral_timeout_ || timeToDecisionWhenTimedOut;
// indicate to IAS that you did not block the ad
adContext.integral_didBlock = false;
}
if (eventType === 'AdBlocked') {
adContext.integral_timeToDecision = this.integral_timeout_;
adContext.integral_didBlock = true;
vansEventName = 'AdImpression'; // send to the web video SDK as an AdImpression event
// this.sendAdErrorWithAdBlockedMessage is not implemented here.
// This section primarily serves to underline that you should
// add a timeout before sending the AdBlocked notification to the player.
var sendAdErrorToPlayerAfterTimeout = setTimeout (this.sendAdErrorWithAdBlockedMessage, 500);
}
this.fwVansInstance_.sendEvent(vansEventName, adContext);
}
CM Example
// VPAID events to pass to IAS web video SDK
this.iasRequiredEvents_ = [
'AdStarted', 'AdStopped', 'AdImpression', 'AdVideoStart', 'AdVideoFirstQuartile', 'AdVideoMidpoint', 'AdVideoThirdQuartile', 'AdVideoComplete', 'AdUserMinimize', 'AdUserClose', 'AdPaused', 'AdPlaying', 'AdLinearChange', 'AdExpandedChange', 'AdVolumeChange', 'AdClickThru', 'AdError', 'AdSizeChange'];
var sendDataToIas = function(eventType) {
if (eventShouldBeReportedToIas()) {
var iasEventName = getIasEventName(eventType), iasAdContext = createIasAdContext.call(this, eventType);
this.cmVansInstance_.sendEvent(iasEventName, iasAdContext);
}
};
var eventShouldBeReportedToIas = this.cmVansInstance_ && this.iasRequiredEvents_.indexOf(eventType) > 0;
var getIasEventName = function(eventType) {
var VPAID_TO_IAS_EVENT_MAP = {
'AdSizeChange': 'resizeAd',
'AdExpanded': 'resizeAd',
'AdUserMinimize': 'resizeAd' // no adUserMinimize in this implementation of VPAID
};
var remappedEventName = VPAID_TO_IAS_EVENT_MAP[eventType];
return remappedEventName === undefined ? remappedEventName : eventType;
};
var createIasAdContext = function(eventType) {
var adContext = {
ad_duration: this.getAdDuration(),
volume: this.getAdVolume()
};
// add required event-specific context properties
if (eventType === 'AdSizeChange') {
adContext.viewMode = this.attributes_['viewMode'];
}
return adContext;
};
sendDataToIas.call(this, eventType);
To ensure the web video SDK can complete measurement on the ad before its executing environment is destroyed, IAS recommends deferring VPAID destruction until the web video SDK signals that measurement has unloaded.
This is accomplished above by the config.onMeasurementComplete callback that delegates VPAID.stopAd logic to the web video SDK, and additional timeout logic whenever calling events to ensure data transfer can complete even when the web video SDK fails to invoke the callback. IAS recommends using both config.onMeasurementComplete and implementing a timeout in your event-handling logic before sending any ad-destruction-triggering notifications to the player.
if (eventType in this.eventsCallbacks_) {
// send data to player, optionally with timeout
if (eventType === 'AdStopped' || eventType === 'AdSkipped' || 'AdError') {
setTimeout(this.eventsCallbacks_[eventType].bind(this), 500);
} else {
this.eventsCallbacks_[eventType]();
}
}
This section walks through an integration as a player/AdManager plugin. Each section has two examples - one for a video.js-like API, and one for a Google IMA AdManager-like API. You can find a link to full code samples in Code Samples.
Initialize your web video SDK CM instance before loading each ad for optimal measurement.
Create an instance of __IASVANS and call its initCM method on the config object with all required properties and the DOM node where the ad is rendered. Initialize one instance of CM per video ad.
Google IMA AdManager-like API
playerSDK.addPlugin('integralIntegration',function (dataPassedToPluginInitialization){
if (typeof(dataPassedToPluginInitialization) === 'undefined') {
return;
}
var player = this;
player.on(playerSDK.AD_EVENTS.AD_LOADED, function(event){ var currentAd = player.ads.ad;
// populate config macros as soon as ad metadata become available
var integralConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID',
campId: player.ads.ad.getSomeMacro(),
chanId: player.ads.ad.getSomeMacro2(),
placementId: player.ads.ad.getSomeMacro3(),
pubOrder: player.ads.ad.getSomeMacro4(),
pubId: player.ads.ad.getSomeMacro5(),
custom: player.ads.ad.getSomeMacro6(),
custom2: player.ads.ad.getSomeMacro7(),
ias_xps:"autoplayed", // video context parameter for autoplay
ias_xbp:"2", // video context parameter for video placement
ias_xar: "1" // video context paramter for autorefresh status
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
player.integral.getAdContext = function() { var adContext = {
ad_duration: player.ads.ad.getDuration(),
volume: player.getVolume() };
return adContext; };
player.integral.cmVansInstance = new __IASVANS();
player.integral.cmVansInstance.initCM(integralConfig, player.containerElement()); // assume that the <video> element used for playback is managed by the player SDK as a child of this container element.
// add additional event listeners to support events that are not in
the SDK
player.on('fullscreenchange', player.integral.FullscreenChangeListener);
player.on('volumechange', player.integral.VolumeChangeListener);
// send events not supported in the SDK but which are needed for IAS measurement
player.integral.cmVansInstance.sendEvent('AdImpression', player.integral.getAdContext());
player.integral.cmVansInstance.sendEvent('AdVideoStart', player.integral.getAdContext());
}); player.on(playerSDK.AD_EVENTS.FIRST_QUARTILE, function(){ player.integral.cmVansInstance.sendEvent('AdVideoFirstQuartile',
player.integral.getAdContext()); });
player.on(playerSDK.AD_EVENTS.MIDPOINT, function(){ player.integral.cmVansInstance.sendEvent('AdVideoMidpoint',
player.integral.getAdContext()); });
player.on(playerSDK.AD_EVENTS.THIRD_QUARTILE, function(){ player.integral.cmVansInstance.sendEvent('AdVideoThirdQuartile',
player.integral.getAdContext());
}); player.on(playerSDK.AD_EVENTS.PAUSE, function(){
player.integral.cmVansInstance.sendEvent('AdPaused', player.integral.getAdContext());
}); player.on(playerSDK.AD_EVENTS.RESUME, function(){ player.integral.cmVansInstance.sendEvent
('AdPlaying',player.integral.getAdContext());
}); player.on(playerSDK.AD_EVENTS.CLICK, function(){
player.integral.cmVansInstance.sendEvent('AdClickThru', player.integral.getAdContext());
}); player.on(playerSDK.AD_EVENTS.AD_ENDED, function(){ player.integral.cmVansInstance.sendEvent('AdVideoComplete',
player.integral.getAdContext()); // remove event listeners when not needed anymore
player.off('volumechange', player.integral.VolumeChangeListener);
player.off('fullscreenchange', player.integral.FullscreenChangeListener);
});
player.on(playerSDK.AD_EVENTS.SKIP, function(){ player.integral.cmVansInstance.sendEvent('AdVideoComplete',
player.integral.getAdContext());
// remove event listeners when not needed anymore
player.off('volumechange', player.integral.VolumeChangeListener); player.off('fullscreenchange',
player.integral.FullscreenChangeListener); });
player.integral.VolumeChangeListener = function() { player.integral.cmVansInstance.sendEvent('AdVolumeChange',
player.integral.getAdContext()); };
player.integral.FullscreenChangeListener = function() { var isFullscreen = (document.fullscreenElement ||
document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement),
iasContext = player.integral.getAdContext();
if (isFullscreen) { iasContext.viewMode = 'fullscreen';
} else {
iasContext.viewMode = 'normal';
}
player.integral.cmVansInstance.sendEvent('resizeAd', iasContext); };
});
Google IMA AdManager-like API
var iasPlugin = (function() {
'use strict'; var cmVansInstance,
adManagerSDKEvents, adManagerSDKErrorEvents, iasToAdManagerSDKEventMap;
var buildEventMap = function (adManagerSDKGlobalObject) {
var adManagerAPI;
try {
adManagerAPI = adManagerSDKGlobalObject.adManagerAPI; adManagerSDKEvents = adManagerAPI.AdEvents; adManagerSDKErrorEvents = adManagerAPI.AdErrorEvents; iasToAdManagerSDKEventMap = {
'AdStarted': adManagerSDKEvents.STARTED,
'AdSkipped': adManagerSDKEvents.SKIPPED, 'AdSkippableStateChange': adManagerSDKEvents.SKIPPABLESTATE_CHANGED,
'AdVolumeChange': adManagerSDKEvents.VOLUME_CHANGED, 'AdRemainingTimeChange': adManagerSDKEvents.DURATION_CHANGE, 'AdImpression': adManagerSDKEvents.IMPRESSION,
'AdVideoStart': adManagerSDKEvents.STARTED, 'AdVideoFirstQuartile': adManagerSDKEvents.FIRST_QUARTILE, 'AdVideoMidpoint': adManagerSDKEvents.MIDPOINT, 'AdVideoThirdQuartile': adManagerSDKEvents.THIRD_QUARTILE, 'AdVideoComplete': adManagerSDKEvents.COMPLETE, 'AdClickThru': adManagerSDKEvents.CLICK,
'AdPaused': adManagerSDKEvents.PAUSED,
'AdPlaying': adManagerSDKEvents.RESUMED,
'AdError': adManagerSDKErrorEvents.AD_ERROR
};
} catch (error) {
console.error('Unable to instantiate plugin; Ad Manager SDK global object unavailable');
}
}; // creates and returns a certification-compliant ad data object for each event sent.
var getAdContext = function(adManager, adInstance) {
var adContext = {
volume: adManager.getVolume(),
ad_duration: adInstance.getDuration(), viewMode: adInstance.getViewMode()
};
return adContext; };
var addAdManagerSDKEventListener = function(adManager, iasEvent, adManagerSDKEvent) {
adManager.addEventListener(adManagerSDKEvent, function(event) { var currentAd = event.getAd(); cmVansInstance.sendEvent(iasEvent, getAdContext(adManager,
currentAd)); });
};
var addAllAdManagerEventListeners = function(adManager) { Object.keys(iasToAdManagerSDKEventMap).forEach(function
(iasEventName) {
var adManagerSDKEventName = iasToAdManagerSDKEventMap
[iasEventName];
addAdManagerSDKEventListener(adManager, iasEventName,
adManagerSDKEventName); });
};
var initializeIAS = function(adManager, adSlot) {
// populate config macros as soon as ad metadata become available adManager.addEventListener(adManagerSDKEvents.LOADED, function
(event) {
var currentAd = event.getAd(), integralConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE', anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID', campId: currentAd.getSomeMacro(),
chanId: currentAd.getSomeMacro2(), placementId: currentAd.getSomeMacro3(), pubOrder: currentAd.getSomeMacro4(), pubId: currentAd.getSomeMacro5(),
custom: currentAd.getSomeMacro6(),
custom2: currentAd.getSomeMacro7(), ias_xps:"autoplayed",
// video context parameter for autoplay status
ias_xbp:"2", // video context parameter for video placement type
ias_xar: "1" // video context parameter for autorefresh status
debug: {
enabled: false, // should be false by default monDomain: '' // only used in debugging;
// IAS will advise on usage
} };
try {
cmVansInstance = new __IASVANS(); cmVansInstance.initCM(integralConfig, adSlot); cmVansInstance.sendEvent('AdLoaded', getAdContext());
} catch (error) {
console.error('Unable to instantiate IAS plugin', error);
} });
};
var init = function(adManager) {
var adSlot = adManager.getVideoElement(); // pass in video element
if the //container element is not a real HTML element attached to the DOM at the time of
//init.
initializeIAS(adManager, adSlot); buildEventMap(adManagerSDKGlobalObject); addAllAdManagerEventListeners(adManager);
};
var dispose = function(adManager) {
// remove any event listeners if necessary
};
return {
init: init,
dispose: dispose };
});
After initializing a new SDK instance, use __IASVANS().sendEvent to send events to the instance throughout the ad lifecycle.
Including the web video SDK source code in your JavaScript exposes the web video SDK constructor function __IASVANS. Each instance of the SDK exposes two initialization methods, initFW and initCM, which initialize a Open Web and a CM ad session measurement instance of the web video SDK.
Both initialization methods require a configuration object and a DOM node representing the video ad for geometric measurement. Open Web initializations also optionally consume a blocking callback function to activate the IAS blocking recommendation engine. Create a new instance of the SDK for each ad measured.
Instantiate the web video SDK before each ad is loaded to ensure that measurement can capture all ad lifecycle events.
Pass all required IDs, macros, and additional properties at the time of initialization. There isn't an API for passing macros or IDs to an instance of the SDK after initialization. Contact IAS to discuss other strategies for delayed macro passage.
All CM properties (except debug and onMeasurementComplete) are tracked by IAS log-level reporting. Note that Open Web supports Log-level reporting.
If you want to pass other data to be tracked, remap the property fields that are not required for initialization (refer to the API reference to see which properties are required). IAS does not track additional data passed as config properties.
In the future IAS may add support for additional macro fields for compliance purposes and because of advances in technology. IAS recommends implementing the Web Video SDK config so that randomly named parameters can pass through from the tag or environment into the Web Video SDK config in the underlying integration. This ensures your integration can take advantage of additional macro fields if IAS adds them in the future. For example, adding query parameters to a VAST URL results in that parameter getting passed to VANS. That way, clients and parties who may be closer to the source of truth for information such as autoplay/break position can pass in that data downstream of where the integration is actually implemented.
See the API reference for a full list of available IDs and macros for each type of integration.
Macro | Description |
partner | Your partner code. Use the value provided to you by IAS. |
anId | Your ad-network-ID. Use the value provided to you by IAS. |
advId, campId | (for buy-side / advertisers) |
campId, pubId, pubOrder, pubCreative, placementId, chanId | (for sell-side / publishers) |
ias_xps ias_xbp ias_xar | (for buy-side and sell-side). For autoplay, break position, and autorefresh. |
Macro | Description |
partner | Your partner code. Use the value provided to you by IAS. |
advEntityId | Use the value provided to you by IAS. |
pubEntityId | Use the value provided to you by IAS. |
ias_xps, ias_xbp, ias_xar | For reporting player state, break position, and auto-refresh status, when known. |
The web video SDK includes a framework for diagnostic monitoring that, when enabled, sends additional pixels throughout the ad lifecycle to aid in troubleshooting problems that arise in live traffic.
Configure diagnostic monitoring at initialization for both Open Web and CM instances of the SDK. Disable diagnostic monitoring by default and enable on an as-needed basis. For implementation details and examples, see the API reference.
A best practice for streamlining the integration process through release is to implement an ad-hoc setting of the debug.enabled property on an individual placement or campaign level. For example, integrate setting debug.enabled via a query parameter attached to the VAST URL of an ad tag.
For the web video SDK to properly measure metrics such as viewability, the SDK needs to consume a real DOM element (not a proxy object exposed by SDKs such as Google IMA) that is in the same scope as the video ad and attached to the DOM at the time of initialization. Tell IAS of any inconsistencies or idiosyncrasies in your SDK or execution environment that impact your ability to fulfill this requirement.
The web video SDK in Open Web mode allows the integrator to detect in real-time if an impression presents a risk, and to block the ad accordingly. Activate the blocking feature by providing a callback when initializing a Open Web web video SDK instance. The callback should contain logic for how to proceed based on the response received (block or pass). The web video SDK invokes the callback on the blocking recommendation returned by the server.
Send IAS an AdImpression event in all cases (block, pass, or timeout) to all instances of the web video SDK that are measuring the impression (for example, CM + CM; CM + Open Web), and must include information on your blocking decision and timing.
IAS enables blocking capabilities on the pubEntityId level. When campaigns are not configured for blocking (for example, Open Web monitoring), the blocking recommendation always returns 'pass'.
Once initialized, the web video SDK expects to "hear" VPAID 2.0 (spec here events as signals from your VPAID ad unit or player AdManager.
For certification, IAS expects to be signaled upon every expected VPAID 2.0 event according to IAB VPAID standards as they occur in real-time. Send events through the web video SDK's sendEvent method, and include all required contextual parameters.
See the API Reference for a list of web video SDK-required VPAID 2.0 events, including any notes that prescribe mapping from other events if your SDK's events do not directly support the events listed. If your SDK does not have an ad lifecycle event that corresponds to a given IAB event, do not substitute another event unless that remapping is explicitly endorsed by IAS. Please additionally note the specific instructions around resizeAd.
Since some VPAID 2.0 events are associated with certain properties tied to the environment, IAS expects you to pass contextual parameters when sending an event. For certification, IAS expects a volume, duration, width, and height reading on every event, as well as a view mode with specific events.
Here is an example of sending an AdVolumeChange event, where integral is a web video SDK Open Web or CM instance:
integral.sendEvent('AdVolumeChange', {
volume: 1, ad_duration: 30, viewMode: 'normal'
});
At the end of every video ad session, the IAS listener (note: not the web video SDK itself) sends all event calls asynchronously to servers for processing.
If the player prematurely destroys the execution context that the IAS integration is running in, transfer of events and data by the SDK may be interrupted. This can have a significant effect on reporting, especially for measured and viewable rates, and IAS cannot certify an integration that does not send needed ad-end events.
Any event followed by processes that entail destruction of the script execution context by the player may trigger this situation. For instance, if the player destroys the VPAID as soon as it receives an AdStopped event, measurement data are subject to loss if the IAS web video SDK is interrupted while unloading data to servers.
If your SDK's supported video ad events/logic does not map 1:1 to the VPAID 2.0 events listed below, please be mindful of the situations that they describe ((as detailed in the spec)[https://www.iab.com/wp-content/uploads/2015/06/VPAID_2_0_Final_04-10-2012.pdf] and contact IAS if you have questions. The list below may not be exhaustive.
AdSkipped
AdVideoComplete
AdStopped
Blocked AdImpression (due to the AdError that follows)
AdError
As of web video SDK 3.6.0, integrators can use the API to provide a callback function to be invoked once the web video SDK has finished sending measurement data to IAS. This callback is provided to the web video SDK as a property called config.onMeasurementComplete.
By delegating to the web video SDK any logic that would trigger the ad environment destruction via the callback, IAS can prevent premature destruction of the execution environment and ensure that the web video SDK is able to complete asynchronous data transfer at the conclusion of an ad session.
In cases where multiple instances (for example, CM + CM, CM + Open Web) measure a single ad impression, IAS recommends implementing logic to ensure the callbacks have been signaled for both instances before the ad can be unloaded. An example of such an implementation, and further technical details, can be found in the API Reference.
Send end-of-life notifications (events listed above) before dispatching the corresponding VPAID events to the player. If your SDK typically sends ad events to the player first and to third-party integrations second, IAS recommends reversing this ordering for end-of-life notifications.
After sending the web video SDK any end-of-life events, implement a timeout of 500-750ms before sending the player anything that would result in the ad being destroyed (for example, AdStopped or AdError).
If possible, avoid XMLHttpRequests in your own unload logic that can block and interfere with the web video SDK session end logic.
Global constructor __IASVANS creates an instance of the web video SDK.
On each instance, the public methods initFW and initCM, respectively, initialize Open Web or CM measurement for an ad session.
Do not invoke more than one initialization method per web video SDK instance.
Create a new web video SDK instance for each Open Web or CM ad session for each video ad measured. Send all events and data for an ad session to its web video SDK instance(s).
Measuring a single ad with CM:
// CORRECT
// create the instance
var cmInstance = new __IASVANS();
// initialize CM ad session
cmInstance.initCM(/*arguments*/);
// as events come in from your SDK, send them
cmInstance.sendEvent(/*arguments*/);
Measuring a single ad with both CM and Open Web:
// CORRECT
// instantiate the constructor twice and call one init on each instance
var cmInstance = __IASVANS();
cmInstance.initCM(/* arguments */);
var fwInstance = __IASVANS();
fwInstance.initFW(/* arguments */);
// INCORRECT
var firstVANS = __IASVANS();
// erroneously calls both initCM and initFW on the same instance
var myCMInstance = firstVANS.initCM();
var myFWInstance = firstVANS.initFW();
Measuring multiple ads with CM:
// CORRECT
// instantiate for first ad
var cmInstance = new __IASVANS();
// initialize CM ad session
cmInstance.initCM(/*arguments*/);
// as events come in from your SDK, send them
cmInstance.sendEvent(/*arguments*/);
// first ad finishes playing
cmInstance.sendEvent('AdStopped', /* eventData */);
// create a new instance for the next ad
cmInstance = new __IASVANS();
// initialize a new CM ad session
cmInstance.initCM(/*arguments*/);
// measure the second ad
cmInstance.sendEvent(/*arguments*/);
// INCORRECT
var cmInstance = new __IASVANS();
cmInstance.initCM(/*arguments*/);
cmInstance.sendEvent(/*arguments*/);
// Erroneously initializes second CM ad session on the first ad's web
video SDK instance.
cmInstance.initCM(/*arguments*/);
Initializes a CM ad session.
Arguments | Type | Description |
cmConfig | Object [Required] | Used to build the IAS CM video JavaScript tag. All property keys are case sensitive. Required property keys: anId, partner, chanId or advId (publisher and advertiser macros, respectively), ias_xps, ias_xpb, and ias_xar. Please see below for a full list of supported CM configuration properties for advertisers and publishers. |
adNode | Node [Required] | A reference to an HTML element (nodeType 1) attached to the DOM where the ad is to be rendered. Serves as the tracking node used by the web video SDK for measurement purposes. Prefer slot instead of videoSlot when integrating with a VPAID. Prefer <video> HTML element when integrating with a player or AdManager, but if the <video> element is a proxy object use the ad container <div>. |
Initializes a Open Web ad session.
Arguments | Type | Description |
fwConfig | Object [Required] | Used to build the IAS Open Web Video JavaScript tag. All property keys are case sensitive. Required property keys: pubEntityId, advEntityId, partner, ias_xps, ias_xpb, and ias_xar. Please see below for a full list of supported Open Web configuration properties. You can use new macro values in your Open Web config to receive Open Web data in your reporting |
adNode | Node [Required] | A reference to an HTML element (nodeType 1) attached to the DOM where the ad is to be rendered. Serves as the tracking node used by the web video SDK for measurement purposes. Prefer slot instead of videoSlot when integrating with a VPAID. Prefer <video> HTML element when integrating with a player or AdManager, but if the <video> element is a proxy object use the ad container <div>. |
blockingCallback | Function [Required if the integration supports blocking] | A callback function IAS calls, returning a String with the blocking response. The callback is invoked on a String result argument equal to either 'block' or 'safe', depending on the result of the IAS blocking recommendation engine. When the blocking callback is provided for a Open Web integration, send an AdImpression event in all cases (block, pass, timeout) containing the Integral-specific properties integral_timeToDecision and integral_didBlock (details below). Note: An IAS client services manager must enable blocking for the specified campaign. See below for details and examples. |
Sends an event to the web video SDK listener for measurement.
Arguments | Type | Description |
eventName | String [Required] | The VPAID Event name, for example, AdImpression. See below for a list of supported VPAID events. Note that there are events that should be sent as a resizeAd 'event'. |
params | Object [Required] | You should decorate this object with any event-associated VPAID data. See below for details on required contextual parameters. |
Note: Provide all or as many of the optional configuration options as possible.
Arguments | Type | Surfaced in IAS UI | Description |
partner | String [Required] | No | Partner identifier assigned and provided to you by IAS |
anId | String [Required] | No | Ad Network ID provided to you by IAS |
advId | String [Required] | Yes | Advertiser ID associated with the ad |
campId | String [Required] | Yes | Campaign ID associated with the ad |
ias_xps | String [Required] | No | Autoplay or click-to-play. Possible values are: "autoplayed" or "clicktoplay" |
ias_xpb | String [Required] | No | Break position (also known as video placement type). Possible values are: "1" - pre-roll, "2" - mid-roll, "3" - post-roll, "4" - stand-alone |
ias_xar | String [Required] | No | Autorefresh. Possible values are: "0" - false or "1" - true |
placementId | String [Optional] | Yes | Placement ID for the ad |
chanId | String [Optional] | Yes | Channel ID for the ad |
pubId | String [Optional] | Yes | Publisher/Primary Seller ID for the ad |
planId | String [Optional] | No | Plan ID for the ad |
creativeId | String [Optional] | No | Creative ID for the ad. Can be passed back to the client via Real-Time Signal |
uId | String [Optional] | No | User ID for the ad session |
bidurl | String [Optional] | No | Bid URL for post-bid delivery analysis |
bidPr | String [Optional] | No | Bid price for post-bid pricing analysis |
impId | String [Optional] | No | Unique impression ID for the ad session. Should be unique for each ad session across a campaign. Note: When diagnostic monitoring is enabled, the impId property is required for some monitoring at the ad session level. |
debug | Object [Optional] | No | Used to enable and configure diagnostic monitoring for the SDK itself. See below for details. |
onMeasurementComplete | Function [Optional, but recommended for VPAID integrations] | No | Callback to be invoked to handle ad-end logic once the IAS listener has completed asynchronous data transfer. See below for details and examples. |
Arguments | Type | Surfaced in IAS UI | Description |
campId | String [Required] | Yes | Size |
chanId | String [Required] | Yes | Ad unit ID |
pubOrder | String [Required] | Yes | Publisher order |
placementId | String [Required] | Yes | Line item ID |
pubCreative | String [Required] | Yes | Creative ID |
pubId | String [Required] | Yes | Advertiser ID |
ias_xps | String [Required] | Yes | Autoplay or click-to-play. Possible values include: "autoplayed" or "clicktoplay" |
ias_xpb | String [Required] | Yes | Break position (when in a video that ad played). Possible values include: "1" - pre-roll, "2" - mid-roll, "3" - post-roll, "4" - stand-alone |
ias_xar | String [Required] | Yes | Autorefresh. Possible values include: "0" - false or "1" - true |
custom | String [Optional] | Yes | Publisher-specific custom macro (for example, traffic source, page type, etc.) |
custom2 | String [Optional] | Yes | Publisher-specific custom macro (for example, traffic source, page type, etc.) |
custom3 | String [Optional] | Yes | Publisher-specific custom macro (for example, traffic source, page type, etc.) |
debug | Object [Optional] | No | Used to enable and configure diagnostic monitoring for the SDK itself. See below for more details. |
onMeasurementComplete | Function [Optional, but recommended for VPAID integrations] | No | Callback to be invoked to handle ad-end logic once an instance of the SDK has completed asynchronous data transfer. See below for details and examples. |
Arguments | Type | Surfaced in IAS UI | Description |
partner | String [Required] | No | Partner identifier assigned and provided to you by IAS |
advEntityId | String [Required] | Yes | Advertiser Entity ID provided to you by IAS |
pubEntityId | String [Required] | Yes | Publisher Entity ID provided to you by IAS |
ias_xps | String [Required] | No | Autoplay or click-to-play. Possible values include: "autoplayed" or "clicktoplay" |
ias_xpb | String [Required] | No | Break position (when in a video that ad played). Possible values include: "1" - pre-roll, "2" - mid-roll, "3" - post-roll, "4" - stand-alone |
iax_xar | String [Required] | No | Autorefresh. Possible values include: "0" - false or "1" - true |
impId | String [Optional] | No | Unique impression ID for the ad session. Should be unique for each ad session across a campaign. Note: When diagnostic monitoring is enabled, the impId property is required for some monitoring at the ad session level. |
debug | Object [Optional] | No | Used to enable and configure diagnostic monitoring for the SDK itself. See below for more details. |
onMeasurementComplete | Function [Optional, but recommended for VPAID integrations] | No | Callback to be invoked to handle ad-end logic once an instance of the SDK has completed asynchronous data transfer. See below for more details. |
ias_dataSourceId | String [Optional] | No | Maps to the entity populating the macros; for example, the DSP or Creative Server. |
ias_advId | String [Optional] | No | Advertiser or Buyer ID. |
ias_campId | String [Optional] | No | Campaign associated to specific advertiser / buyer running multiple campaigns. |
ias_pubId | String [Optional] | No | Publisher or Seller ID. |
ias_placementId | String [Optional] | No | Ad unit or Placement or Creative ID. |
ias_chanId | String [Optional] | No | Secondary Seller or Channel ID. |
ias_creativeId | String [Optional] | No | Ad unit ID. |
ias_dealId | String [Optional] | No | The ID that is assigned to a Private Market place (PMP) deal upon its creation used to identify the deal between the buyers and sellers for both targeting and reporting. |
ias_bundleId | String [Optional] | No | Mobile application bundle ID (for mobile application impressions) |
ias_impId | String [Optional] | No | Unique event identifier assigned by client system. This information is suggested for all Segment API integrations, and optional for other integrations. |
ias_dataSourceId2 | String [Optional] | No | You can append a second set of data using the same macro names but with a "2" appended to the end of the ID. |
ias_advId2 | String [Optional] | No | |
ias_campId2 | String [Optional] | No | |
ias_pubId2 | String [Optional] | No | |
ias_placementId2 | String [Optional] | No | |
ias_chanId2 | String [Optional] | No | |
ias_creativeId2 | String [Optional] | No | |
ias_dealId2 | String [Optional] | No | |
ias_bundleId2 | String [Optional] | No | |
ias_impId2 | String [Optional] | No |
Arguments | Type | Description |
enabled | Boolean [Optional] | Defaults to false. Set to true to enable diagnostic monitoring for troubleshooting purposes (coordinate with IAS). |
monDomain | String [Optional] | When provided, specifies an additional domain to receive diagnostic monitoring data. Ideally, this would be a subdomain of the same base domain from where the ad solution is being served, and the subdomain would be mapped to an IP address provided by IAS for SDK diagnostic monitoring. As an example, providing 'foo.example.com' as debug.monDomain results in the web video SDK sending diagnostic data to https://foo.example.com. HTTPS requests are the default, but if you require plain HTTP, then add the protocol to the debug.monDomain config option (for example, use 'http://foo.example.com' instead of 'foo.example.com'). You should never have to provide this unless IAS explicitly identify that as a troubleshooting strategy when experiencing problems with a live campaign. |
In the future IAS may add support for additional macro fields for compliance purposes and because of advances in technology. IAS recommends implementing the Web Video SDK config so that randomly named parameters can pass through from the tag or environment into the Web Video SDK config in the underlying integration. This ensures your integration can take advantage of additional macro fields if IAS adds them in the future. For example, adding query parameters to a VAST URL results in that parameter getting passed to VANS. That way, clients and parties who may be closer to the source of truth for information such as autoplay/break position can pass in that data downstream of where the integration is actually implemented.
When delegating ad-end destruction to onMeasurementComplete, also implement a timeout to ensure your ad-end processes can continue smoothly when the web video SDK cannot invoke the callback.
Each ad session initialization should have its own onMeasurementComplete callback, as each instance has a discrete data transfer lifecycle.
// Get reference to HTML Element
var adNode = document.getElementById('my-video');
// Instantiate web video SDK
var cmInstance = new __IASVANS();
// Create a configuration
var config = {
partner: 'Gold Street Media', anId: '12345',
advId: '6789',
campId: '3',
creativeId: '98765', placementId: '5',
chanId: '6',
impId: '76131e76e17e',
ias_xps:"autoplayed",
ias_xbp:"2",
ias_xar: "1"
onMeasurementComplete: myVPAIDAdUnit.dispose
// sends AdStopped to the player, resulting in ad destruction. See also timeout below
};
// Initialize web video SDK as CM
cmInstance.initCM(config, adNode); // Send events
cmInstance.sendEvent('AdVideoMidpoint', {
volume: 1, ad_duration: 30 // ...
}); // ad end
// your VPAID (a snippet)
myVPAIDAdUnit.stopAd = function() {
// send web video SDK event first
cmInstance.sendEvent('AdStopped', {
volume: 1, ad_duration: 30, // ...
}); // then start the timeout
var timeoutToPreventAdEndEventsLoss = setTimeout
(this.dispose, 750);
}; // under the hood:
// 1. web video SDK receives AdStopped event
// 2a. web video SDK Listener completes asynchronous data transfer to server server
// 3a. myVPAIDAdUnit.dispose is called by web video SDK
// OR
// 2b. web video SDK fails to invoke the onMeasurementComplete callback within the allotted timeout (could be due to latency, or other errors)
// 3b. myVPAIDAdUnit.dispose is called at the end of imeoutToPreventAdEndEventsLoss
When multiple instances of the web video SDK (for example, CM + CM, CM + Open Web) measure a single ad impression, the web video SDK does not wait for both instances' reporting to conclude before invoking the onMeasurementComplete callback for environment destruction.
To prevent discrepancies in reporting, implement logic to ensure the callback is only invoked after all measurement has finished.
Example: Wrapper function that synchronizes the callbacks to ensure VPAID.stopAd is invoked only once, after both instances' measurement has completed
// Wrapper function
var synchronizedMeasurementComplete = function(cbf){
var count = 0;
return function() {
count++;
if(count === 2) {
cbf();
}
}
};
// Usage
var measurementCompleteCalledOnlyOnce = synchronizedMeasurementComplete (VPAID.stopAd);
// instead of the original ad-unload callback function, the wrapped function is passed to both instances' init:
// cm config
var config = {
/* ... */
onMeasurementComplete: measurementCompleteCalledOnlyOnce };
// Open Web config
var config = {
/* ... */
onMeasurementComplete: measurementCompleteCalledOnlyOnce };
var firstInstance = new __IASVANS();
firstInstance.initCM(config);
var secondInstance = new __IASVANS();
secondInstance.initFW(config);
In an Open Web integration that uses blocking, IAS requires you to send an AdImpression in all scenarios (ad blocked, ad passed, and blocking response timed out).
To ensure blocking results are recorded, IAS requires you to add two IAS-specific properties, integral_didBlock and integral_timeToDecision, to the event parameters sent with the AdImpression:
integral_didBlock [Boolean] defines your actual blocking action taken based on IAS's blocking recommendation (true for when you block the ad and false for you proceed with showing the ad (includes timeout scenarios)).
integral_timeToDecision [Integer] is the time delta in milliseconds between initialization of Open Web and blocking recommendation signal.
To the right is an example of sending an AdImpression with all the correct contextual parameters, where integral is an instance of the web video SDK.
Example of sending an AdImpression
integral.sendEvent('AdImpression', {
'ad_duration': 30,
'volume': 1,
'integral_didBlock': false, // you did not block the ad
'integral_timeToDecision': 450
});
This table details how these required properties should be implemented based on how the blocking scenario plays out:
Property | Scenario 1: Blocking callback invoked with 'safe' and you play the ad | Scenario 2: Blocking callback invoked with 'block' and you block the ad | Scenario 3: Blocking callback not invoked in time and you play the ad anyway |
integral_didBlock | false | true | false |
integral_timeToDecision | set in blocking callback function | set in blocking callback function | set before sending non-blocked AdImpression |
var initWebVideoSDK = function(config, adNode) {
var fwInstance = new __IASVANS(),
blockingResponseReturnedOnTime;
var block = function (result) {
// set the time to decision inside the blocking callback
var integral_timeToDecision = new Date().valueOf() - blockingTimeoutStart;
if (result === 'block') {
blockingResponseReturnedOnTime = true; fwInstance.sendEvent('AdImpression', {
integral_timeToDecision, integral_didBlock: true,
/* other ad data */ });
} else {
myVPAIDAdUnit.blockAd(); // throws AdError after a 500ms timeout
blockingResponseReturnedOnTime = true;
// example is simplified and glosses over AdLoaded/AdStarted. Whenever you send the AdImpression event, ensure you add integral_timeToDecision and integral_didBlock
fwInstance.sendEvent('AdImpression', {
integral_timeToDecision,
integral_didBlock: false, /* other ad data */
});
myVPAIDAdUnit.playAd(); // sends AdImpression to player
}
};
var blockingTimeoutStart = new Date().valueOf(); fwInstance.initFW(config, adNode, block);
setTimeout(function() {
if (!blockingResponseReturnedOnTime) {
fwInstance.sendEvent('AdImpression', {
integral_timeToDecision: new Date().getTime() - blockingTimeoutStart,
integral_didBlock: false,
/* other ad data */ });
myVPAIDAdUnit.playAd(); // sends AdImpression to player
}
});
}
1) Blocking response returned in time, ad not blocked
a) See diagram #2 (Open Web mode, VPAID integration, ad not blocked) at the end of the High-Level Summary.
2) Blocking response returned in time, ad blocked
3) Blocking response timed out, ad not blocked
AdLoaded
AdStarted
AdStopped
AdSkipped
AdSkippableStateChange
AdDurationChange
AdVolumeChange
AdImpression
AdVideoStart
AdVideoFirstQuartile
AdVideoMidpoint
AdVideoThirdQuartile
AdVideoComplete
AdClickThru
AdPaused
AdPlaying
AdError
AdSizeChange
Map to resizeAd
AdExpandedChange
AdUserMinimize
Note: Although resizeAd is not a VPAID 2.0 event (but is instead a VPAID 2.0 method), the web video SDK expects to be signaled with a resizeAd event when:
a) the resizeAd method is invoked as a result of a resize;
b) on any AdSizeChange, AdExpandedChange, or AdUserMinimize.
To the right is an example of sending a resizeAd event, where integral is an instance of the web video SDK.
Example of sending a resizeAd event
integral.sendEvent('resizeAd', {
'ad_duration': 30,
'volume': 1,
'viewMode': 'normal',
});
Arguments | Type | Description |
integral_didBlock | Boolean [Required on Open Web AdImpression event] | Describes whether the ad was blocked by you (regardless of IAS blocking instructions) |
integral_timeToDecision | Integer [Required on Open Web AdImpression event] | Time elapsed, in milliseconds, between Open Web VANS initialization and the receipt of a blocking signal from IAS |
ad_duration | Integer when available; otherwise, send -2 when unavailable or -1 when not yet defined. [Required on AdVideoStart} | Total running time of the ad, in seconds. Required on the AdVideoStart event. If the ad duration is unknown on video start, send -1. IAS discourages sending nonnegative ‘fallback’ values such as 30s. |
volume | Float between 0 and 1 when available, or" -1" when not available. [Required on AdVideoStart event, and on adVolumeChange events for reporting volume changes] | Volume of the ad, expressed as a float from 0 to 1. Required on the AdVideoStart event, and if there are any changes to the volume value (e.g. volume changes from 0 to 0.5). |
url | String [Optional] | URL that a clickthrough goes to. |
viewMode | String [Required on AdVideoStart event, and on resizeAd events for reporting viewMode changes] | fullscreen or normal. Required on the AdVideoStart event, and if there are any changes to the viewMode value (e.g. video changes from “normal” to “fullscreen” viewMode). |
message | String [Optional] | Specifics about the error that the ad ran into |
Note: The event contextual properties player_dimensions, ad_offset_left, ad_offset_top, height, width, and ad_dimensions supported by previous versions of the web video SDK have been deprecated.
Work through the following list of items and check that each item is addressed before moving on and sending IAS your code for review and QA.
Have you reviewed the technical requirements?
Have you uploaded your integration code as a GitHub Gist and made it available to the IAS engineering team?
Have you contacted IAS to surface and discuss any certification requirements that you are unable to fulfill? (for example, the execution context that some of your ads run in does not support dynamic script injection; you have no way of providing a width and height property on every event; you cannot implement an ad-end timeout)
Are you instantiating the web video SDK in the right mode - for example, CM, Open Web, CM+Open Web, CM+CM? If you are unsure, please confirm with IAS.
Are you passing all necessary config properties at initialization? Are you using the IAS-supplied values for properties like anId, partner, advEntityId, and pubEntityId?
Are you passing all required video contextual parameters? “video contextual parameters, namely player state (ias_xps), break position (ias_xbp), and auto-refresh status (ias_xar).
Have you confirmed the mapping for any config properties, including ones that you are using as macro fields? (See full reference of config options.)
Are you initializing the web video SDK at the appropriate time in your solution's lifecycle?
Have you confirmed that you pass in a valid HTML DOM element (not a proxy object) that is attached to the DOM at the time of initialization for geometric measurement?
Have you confirmed diagnostic monitoring is configured initially disabled?
Are you sending all required events?
Double-check that AdSkippableStateChange is sent whenever available, as it can improve measurement
Are all the events mapped properly?
Ensure that AdSizeChange, AdExpandedChange, and AdUserMinimize are sent as resizeAd
Are you sending all required event contextual parameters?
Are all required properties ad_duration, and volume present on every event?
Is viewMode present on at least one event in every ad session, and sent with any resizeAd event?
Are you sending all ad events as they happen in real-time? Ensure that you are not aggregating the events and then sending everything at once.
Are you using the correct datatype for all events, properties, and arguments? Are you passing in all arguments for API methods in the right order? (Check the API reference.)
Are you handling multiple ads (player/AdManager integrations only) appropriately by instantiating a separate __IASVANS() for each ad?
Review your use of the __IASVANS constructor and initialization methods in the API reference.
Have you followed these best practices for ad-end handling (VPAID integrations only)?
If you are using config.onMeasurementComplete, ensure that the value is a function that handles all logic around destruction of the ad environment.
Have you confirmed that you have implemented diagnostic monitoring activation in a lightweight manner, ideally so IAS can enable it during a live campaign without needing costly code changes?
Have you properly implemented initialization? The initializations should be on separate instances of __IASVANS, not on the same instance.
Have you properly implemented event sending? Two sets of events should be sent; one to each web video SDK instance. See above for more.
If you are implementing Open Web blocking, please make sure that the blocked AdImpression is sent using BOTH the CM and Open Web instances. Ensure there are no race conditions that would lead to a blocked impression being sent unevenly.
Have you implemented measures to synchronize the config.onMeasurementCallback if you are using it?
Are you sending the AdImpression event in blocked, non-blocked, and timeout scenarios? Are you setting and sending integral_didBlock and integral_timeToDecision along with the AdImpression in all cases?
Ensure integral_didBlock reflects your blocking decision.
Ensure integral_timeToDecision equals the time delta between initFW and receipt of the blocking response from the server/timeout.
Have you implemented a timeout (IAS recommends 1500ms) before proceeding to play the ad as usual when the blocking callback is not invoked in time?
See above for implementation details.
Example of a Web Video SDK integration in Campaign Monitoring mode (publisher macros) with a hypothetical player AdManager that has a Google IMA-like API, and does not support all the events natively, and this is the reason why some event listeners are added with manual steps. Assume the plugin is instantiated once per video ad.
// Example of a Web Video SDK integration in Campaign Monitoring mode (publisher macros) with a hypothetical player AdManager that has a Google IMA-like API, and does not support all the events natively. That is why some event listeners are added with manual steps. Assume plugin is instantiated once per video ad.
var __IASVANS = function(){
/* ... */
};
var iasPlugin = (function() {
'use strict';
var cmVansInstance,
adManagerSDKEvents,
adManagerSDKErrorEvents,
iasToAdManagerSDKEventMap;
var buildEventMap = function(adManagerSDKGlobalObject) {
var adManagerAPI;
try {
adManagerAPI = adManagerSDKGlobalObject.adManagerAPI;
adManagerSDKEvents = adManagerAPI.AdEvents;
adManagerSDKErrorEvents = adManagerAPI.AdErrorEvents;
iasToAdManagerSDKEventMap = {
'AdStarted': adManagerSDKEvents.STARTED,
'AdSkipped': adManagerSDKEvents.SKIPPED,
'AdSkippableStateChange': adManagerSDKEvents.SKIPPABLE_STATE_CHANGED,
'AdVolumeChange': adManagerSDKEvents.VOLUME_CHANGED,
'AdRemainingTimeChange': adManagerSDKEvents.DURATION_CHANGE,
'AdImpression': adManagerSDKEvents.IMPRESSION,
'AdVideoStart': adManagerSDKEvents.STARTED,
'AdVideoFirstQuartile': adManagerSDKEvents.FIRST_QUARTILE,
'AdVideoMidpoint': adManagerSDKEvents.MIDPOINT,
'AdVideoThirdQuartile': adManagerSDKEvents.THIRD_QUARTILE,
'AdVideoComplete': adManagerSDKEvents.COMPLETE,
'AdClickThru': adManagerSDKEvents.CLICK,
'AdPaused': adManagerSDKEvents.PAUSED,
'AdPlaying': adManagerSDKEvents.RESUMED,
'AdError': adManagerSDKErrorEvents.AD_ERROR
};
} catch (error) {
console.error('Unable to instantiate plugin; Ad Manager SDK global object unavailable');
}
};
var getAdContext = function(adManager, adInstance) {
var adContext = {
volume: adManager.getVolume(),
ad_duration: adInstance.getDuration(),
height: adInstance.getHeight(),
width: adInstance.getWidth()
};
return adContext;
};
var addAdManagerSDKEventListener = function(adManager, iasEvent, adManagerSDKEvent) {
adManager.addEventListener(adManagerSDKEvent, function(event) {
var currentAd = event.getAd();
cmVansInstance.sendEvent(iasEvent, getAdContext(adManager, currentAd));
});
};
var addAllAdManagerEventListeners = function(adManager) {
Object.keys(iasToAdManagerSDKEventMap).forEach(function(iasEventName) {
var adManagerSDKEventName = iasToAdManagerSDKEventMap[iasEventName];
addAdManagerSDKEventListener(adManager, iasEventName, adManagerSDKEventName);
});
};
var initializeIAS = function(adManager, adSlot) {
// populate config macros as soon as ad metadata become available
adManager.addEventListener(adManagerSDKEvents.LOADED, function(event) {
var currentAd = event.getAd(),
integralConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID',
campId: currentAd.getSomeMacro(),
chanId: currentAd.getSomeMacro2(),
placementId: currentAd.getSomeMacro3(),
pubOrder: currentAd.getSomeMacro4(),
pubId: currentAd.getSomeMacro5(),
pubCreative: currentAd.getSomeMacro6(),
custom: currentAd.getSomeMacro7(),
custom2: currentAd.getSomeMacro8(),
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
try {
cmVansInstance = new __IASVANS();
cmVansInstance.initCM(integralConfig, adSlot);
cmVansInstance.sendEvent('AdLoaded', getAdContext());
} catch (error) {
console.error('Unable to instantiate IAS plugin', error);
}
});
};
var init = function(adManager) {
var adSlot = adManager.getVideoElement(); // pass in video element if the container element is not a real HTML element attached to the DOM at the time of init.
initializeIAS(adManager, adSlot);
buildEventMap(adManagerSDKGlobalObject);
addAllAdManagerEventListeners(adManager);
};
var dispose = function(adManager) {
// remove any event listeners if necessary
};
return {
init: init,
dispose: dispose
};
});
Example of a Web Video SDK integration in Campaign Monitoring mode (publisher macros) with a hypothetical player that does not have an AdManager API, but which supports all the events in PLAYER_TO_IAS_EVENT_MAP
in its SDK out-of-the-box. Handles multiple ads in a single ad break.
// Example of a Web Video SDK integration in Campaign Monitoring mode (publisher macros) with a hypothetical player that does not have an AdManager API, but which supports all the events in PLAYER_TO_IAS_EVENT_MAP in its SDK out-of-the-box. Handles multiple ads in a single ad break.
var __IASVANS = function(){
/* ... */
};
var containerElementForPlayer = document.getElementById('player-container-div');
var player = playerConstructor(containerElementForPlayer); // assume that the <video> element used for playback is managed by the player SDK as a child of the container element passed into the constructor.
var cmVansInstance;
var currentAd;
// every time a new video ad is loaded, we instantiate a new VANS and add listeners for it.
player.on('videoMetadataLoaded', function(event) {
// remove existing event listeners if there's a new ad being played
if (currentAd !== undefined) {
player.removeAllEventListeners();
}
currentAd = player.getCurrentAd();
// populate config macros as soon as metadata become available
var integralConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID',
campId: currentAd.getSomeMacro(),
chanId: currentAd.getSomeMacro2(),
placementId: currentAd.getSomeMacro3(),
pubOrder: currentAd.getSomeMacro4(),
pubId: currentAd.getSomeMacro5(),
pubCreative: currentAd.getSomeMacro6(),
custom: currentAd.getSomeMacro7(),
custom2: currentAd.getSomeMacro8(),
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
// instantiate the integration
cmVansInstance = new __IASVANS();
cmVansInstance.initCM(integralConfig, containerElementForPlayer);
// add event listeners for player
addIasEventListeners(player);
});
var PLAYER_TO_IAS_EVENT_MAP = {
'ad_loaded': 'AdLoaded',
'ad_started': 'AdStarted',
'first_quartile': 'AdVideoFirstQuartile',
'midpoint': 'AdVideoMidpoint',
'third_quartile': 'AdVideoThirdQuartile',
'ad_end': 'AdVideoComplete',
'interaction_pause': 'AdPaused',
'interaction_resume': 'AdPlaying',
'interaction_click': 'AdClickThru',
'volume_change': 'AdVolumeChange',
'interaction_skip': 'AdSkipped',
'skip_available': 'AdSkippableStateChange',
'stop': 'AdStopped',
'impression': 'AdImpression',
'size_change': 'resizeAd',
'fullscreen-change': 'resizeAd',
'error': 'AdError'
};
function addIasEventListeners(player) {
Object.keys(PLAYER_TO_IAS_EVENT_MAP).forEach(function(playerEventName) {
player.on(playerEventName, function(event) {
var iasEventName = PLAYER_TO_IAS_EVENT_MAP[playerEventName];
var adContext = createIntegralAdContext(iasEventName);
sendIasEvent(iasEventName, adContext);
});
});
}
function createIntegralAdContext(iasEventName) {
var integralAdContext = {
ad_duration: player.getCurrentAd().getAdDuration(),
width: player.getWidth(),
height: player.getHeight(),
volume: player.getVolume()
};
if (iasEventName === 'resizeAd') {
integralAdContext.viewMode = player.getViewMode();
}
return integralAdContext;
}
function sendIasEvent(eventName, adContext) {
if (cmVansInstance) {
console.log('Sending IAS event: ' + iasEventName);
cmVansInstance.sendEvent(iasEventName, adContext);
}
}
Example of a Web Video SDK integration in Campaign Monitoring mode (publisher macros) with a hypothetical publisher player has a videojs-like plugin API, and does not support all the events natively. That is why some event listeners are added with manual steps. Assume plugin is instantiated once per video ad.
// Example of a Web Video SDK integration in Campaign Monitoring mode (publisher macros) with a hypothetical publisher player has a videojs-like plugin API, and does not support all the events natively. That is why some event listeners are added with manual steps. Assume plugin is instantiated once per video ad.
var __IASVANS = function(){
/* ... */
};
playerSDK.addPlugin('integralIntegration',function(dataPassedToPluginInitialization){
if (typeof(dataPassedToPluginInitialization) === 'undefined') {
return;
}
var player = this;
player.on(playerSDK.AD_EVENTS.AD_LOADED, function(event){
var currentAd = player.ads.ad;
// populate config macros as soon as ad metadata become available
var integralConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID',
campId: player.ads.ad.getSomeMacro(),
chanId: player.ads.ad.getSomeMacro2(),
placementId: player.ads.ad.getSomeMacro3(),
pubOrder: player.ads.ad.getSomeMacro4(),
pubId: player.ads.ad.getSomeMacro5(),
pubCreative: currentAd.getSomeMacro6(),
custom: currentAd.getSomeMacro7(),
custom2: currentAd.getSomeMacro8(),
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
player.integral.getAdContext = function() {
var adContext = {
ad_duration: player.ads.ad.getDuration(),
width: player.getWidth(),
height: player.getHeight(),
volume: player.getVolume()
};
return adContext;
};
player.integral.cmVansInstance = new __IASVANS();
player.integral.cmVansInstance.initCM(integralConfig, player.containerElement()); // assume that the <video> element used for playback is managed by the player SDK as a child of this container element.
// add additional event listeners to support events that are not in the player SDK
player.on('fullscreenchange', player.integral.FullscreenChangeListener);
player.on('volumechange', player.integral.VolumeChangeListener);
// send events not supported in the player SDK but which are needed for IAS measurement
player.integral.cmVansInstance.sendEvent('AdImpression', player.integral.getAdContext());
player.integral.cmVansInstance.sendEvent('AdVideoStart', player.integral.getAdContext());
});
player.on(playerSDK.AD_EVENTS.FIRST_QUARTILE, function(){
player.integral.cmVansInstance.sendEvent('AdVideoFirstQuartile', player.integral.getAdContext());
});
player.on(playerSDK.AD_EVENTS.MIDPOINT, function(){
player.integral.cmVansInstance.sendEvent('AdVideoMidpoint', player.integral.getAdContext());
});
player.on(playerSDK.AD_EVENTS.THIRD_QUARTILE, function(){
player.integral.cmVansInstance.sendEvent('AdVideoThirdQuartile', player.integral.getAdContext());
});
player.on(playerSDK.AD_EVENTS.PAUSE, function(){
player.integral.cmVansInstance.sendEvent('AdPaused', player.integral.getAdContext());
});
player.on(playerSDK.AD_EVENTS.RESUME, function(){
player.integral.cmVansInstance.sendEvent('AdPlaying',player.integral.getAdContext());
});
player.on(playerSDK.AD_EVENTS.CLICK, function(){
player.integral.cmVansInstance.sendEvent('AdClickThru', player.integral.getAdContext());
});
player.on(playerSDK.AD_EVENTS.AD_ENDED, function(){
player.integral.cmVansInstance.sendEvent('AdVideoComplete', player.integral.getAdContext());
// remove event listeners when not needed anymore
player.off('volumechange', player.integral.VolumeChangeListener);
player.off('fullscreenchange', player.integral.FullscreenChangeListener);
});
player.on(playerSDK.AD_EVENTS.SKIP, function(){
player.integral.cmVansInstance.sendEvent('AdVideoComplete', player.integral.getAdContext());
// remove event listeners when not needed anymore
player.off('volumechange', player.integral.VolumeChangeListener);
player.off('fullscreenchange', player.integral.FullscreenChangeListener);
});
player.integral.VolumeChangeListener = function() {
player.integral.cmVansInstance.sendEvent('AdVolumeChange', player.integral.getAdContext());
};
player.integral.FullscreenChangeListener = function() {
var isFullscreen = (document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement),
iasContext = player.integral.getAdContext();
if (isFullscreen) {
iasContext.viewMode = 'fullscreen';
} else {
iasContext.viewMode = 'normal';
}
player.integral.cmVansInstance.sendEvent('resizeAd', iasContext);
};
});
Example of a VPAID Ad Unit integration with the Web Video SDK measuring each ad impression with both Open Web mode (blocking supported) and Campaign Monitoring mode (advertiser macros). Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
// Example of a VPAID Ad Unit integration with the Web Video SDK measuring each ad impression with both Open Web mode (blocking supported) and Campaign Monitoring mode (advertiser macros). Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
var __IASVANS = function(){
/* ... */
};
/**
* @constructor
*/
var VpaidVideoPlayer = function() {
/**
* The slot is the div element on the main page that the ad is supposed to
* occupy.
* @type {Object}
* @private
*/
this.slot_ = null;
/**
* The video slot is the video element used by the ad to render video content.
* @type {Object}
* @private
*/
this.videoSlot_ = null;
/**
* An object containing all registered events. These events are all
* callbacks for use by the VPAID ad.
* @type {Object}
* @private
*/
this.eventsCallbacks_ = {};
/**
* A list of getable and setable attributes.
* @type {Object}
* @private
*/
this.attributes_ = {
'companions' : '',
'desiredBitrate' : 256,
'duration' : 10,
'expanded' : false,
'height' : 0,
'icons' : '',
'linear' : true,
'remainingTime' : 10,
'skippableState' : false,
'viewMode' : 'normal',
'width' : 0,
'volume' : 1.0
};
/**
* A set of ad playback events to be reported.
* @type {Object}
* @private
*/
this.quartileEvents_ = [
{event: 'AdVideoStart', value: 0},
{event: 'AdVideoFirstQuartile', value: 25},
{event: 'AdVideoMidpoint', value: 50},
{event: 'AdVideoThirdQuartile', value: 75},
{event: 'AdVideoComplete', value: 100}
];
/**
* @type {number} An index into what quartile was last reported.
* @private
*/
this.nextQuartileIndex_ = 0;
/**
* Parameters passed in from the AdParameters section of the VAST.
* Used for video URL and MIME type.
*
* @type {!object}
* @private
*/
this.parameters_ = {};
};
/**
* Returns the supported VPAID version.
* @param {string} version
* @return {string}
*/
VpaidVideoPlayer.prototype.handshakeVersion = function(version) {
return ('2.0');
};
/**
* Initializes all attributes in the ad. The ad will not start until startAd is\
* called.
*
* @param {number} width The ad width.
* @param {number} height The ad height.
* @param {string} viewMode The ad view mode.
* @param {number} desiredBitrate The desired bitrate.
* @param {Object} creativeData Data associated with the creative.
* @param {Object} environmentVars Runtime variables associated with the
* creative like the slot and video slot.
*/
VpaidVideoPlayer.prototype.initAd = function(
width,
height,
viewMode,
desiredBitrate,
creativeData,
environmentVars) {
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.attributes_['desiredBitrate'] = desiredBitrate;
// slot and videoSlot are passed as part of the environmentVars
this.slot_ = environmentVars.slot;
this.videoSlot_ = environmentVars.videoSlot;
// Parse the incoming ad parameters.
this.parameters_ = JSON.parse(creativeData['AdParameters']);
this.log('initAd ' + width + 'x' + height +
' ' + viewMode + ' ' + desiredBitrate);
this.updateVideoSlot_();
this.videoSlot_.addEventListener(
'timeupdate',
this.timeUpdateHandler_.bind(this),
false);
this.videoSlot_.addEventListener(
'loadedmetadata',
this.loadedMetadata_.bind(this),
false);
this.videoSlot_.addEventListener(
'ended',
this.stopAd.bind(this),
false);
/* START IAS Integration-Related Code */
// VPAID events to pass to IAS VANS
this.iasRequiredEvents_ = [
'AdStarted',
'AdStopped',
'AdImpression',
'AdVideoStart',
'AdVideoFirstQuartile',
'AdVideoMidpoint',
'AdVideoThirdQuartile',
'AdVideoComplete',
'AdUserMinimize',
'AdUserClose',
'AdPaused',
'AdPlaying',
'AdLinearChange',
'AdExpandedChange',
'AdVolumeChange',
'AdClickThru',
'AdError',
'AdSizeChange'
];
// same arg for both CM and Open Web
var adNode = this._slot;
// wrapper to synchronize callbacks
// Wrapper function
var synchronizedMeasurementComplete = function(cbf){
var count = 0;
return function() {
count++;
if(count === 2) {
cbf();
}
}
};
var measurementCompleteCalledOnlyOnce = synchronizedMeasurementComplete(function(){
this.stopAd();
}).bind(this);
// init VANS
this.cmVansInstance_ = __IASVANS();
// advertiser
var cmConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID',
advId: 'PROVIDE-YOUR-OWN-ADV-ID',
campId: 'PROVIDE-YOUR-OWN-CAMP-ID',
creativeId: 'PROVIDE-YOUR-OWN-CREATIVE-ID',
placementId: 'PROVIDE-YOUR-OWN-PLACEMENT-ID',
chanId: 'PROVIDE-YOUR-OWN-CHANNEL-ID',
impId: 'PROVIDE-YOUR-OWN-IMPRESSION-ID',
onMeasurementComplete: measurementCompleteCalledOnlyOnce,
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
this.cmVansInstance_.initCM(config, adNode);
// Open Web init
this.fwVansInstance_ = __IASVANS();
// Open Web blocking
var fwConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
advEntityId: 'YOUR-IAS-PROVIDED-ADV-ENTITY-ID',
pubEntityId: 'YOUR-IAS-PROVIDED-PUB-ENTITY-ID',
impId: 'PROVIDE-YOUR-OWN-IMPRESSION-ID',
onMeasurementComplete: measurementCompleteCalledOnlyOnce,
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
// proceed with ad if IAS blocking instructions are not received in time.
var blockingInstructionsTimeout = setTimeout(this.callEvent_('AdLoaded'), 1500);
// provide a blocking callback
var blockingCallback = function (result) {
if (result === 'block') {
this.integral_timeout_ = new Date().valueOf() - blockingTimeoutStart;
this.callEvent_('AdBlocked');
}
else if (result === 'safe') {
this.callEvent_('AdLoaded');
}
};
// start the blocking timeout before initFW
var blockingTimeoutStart = new Date().valueOf();
this.fwVansInstance_.initFW(config, adNode, blockingCallback);
/* END IAS Integration-Related Code */
this.callEvent_('AdLoaded');
};
/**
* Called by the video element when video metadata is loaded.
* @private
*/
VpaidVideoPlayer.prototype.loadedMetadata_ = function() {
// The ad duration is not known until the media metadata is loaded.
// Then, update the player with the duration change.
this.attributes_['duration'] = this.videoSlot_.duration;
this.callEvent_('AdDurationChange');
};
/**
* Called by the video element when the video reaches specific points during
* playback.
* @private
*/
VpaidVideoPlayer.prototype.timeUpdateHandler_ = function() {
if (this.nextQuartileIndex_ >= this.quartileEvents_.length) {
return;
}
var percentPlayed =
this.videoSlot_.currentTime * 100.0 / this.videoSlot_.duration;
if (percentPlayed >= this.quartileEvents_[this.nextQuartileIndex_].value) {
var lastQuartileEvent = this.quartileEvents_[this.nextQuartileIndex_].event;
this.eventsCallbacks_[lastQuartileEvent]();
this.nextQuartileIndex_ += 1;
}
if (this.videoSlot_.duration > 0) {
this.attributes_['remainingTime'] =
this.videoSlot_.duration - this.videoSlot_.currentTime;
}
};
/**
* Creates or updates the video slot and fills it with a supported video.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoSlot_ = function() {
if (this.videoSlot_ == null) {
this.videoSlot_ = document.createElement('video');
this.log('Warning: No video element passed to ad, creating element.');
this.slot_.appendChild(this.videoSlot_);
}
this.updateVideoPlayerSize_();
var foundSource = false;
var videos = this.parameters_.videos || [];
for (var i = 0; i < videos.length; i++) {
// Choose the first video with a supported mimetype.
if (this.videoSlot_.canPlayType(videos[i].mimetype) != '') {
this.videoSlot_.setAttribute('src', videos[i].url);
foundSource = true;
break;
}
}
if (!foundSource) {
// Unable to find a source video.
this.callEvent_('AdError');
}
};
/**
* Helper function to update the size of the video player.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoPlayerSize_ = function() {
this.videoSlot_.setAttribute('width', this.attributes_['width']);
this.videoSlot_.setAttribute('height', this.attributes_['height']);
};
/**
* Called by the wrapper to start the ad.
*/
VpaidVideoPlayer.prototype.startAd = function() {
this.log('Starting ad');
this.videoSlot_.play();
this.callEvent_('AdStarted');
this.callEvent_('AdImpression'); // this implementation has AdImpression on video start
};
/**
* Called by the wrapper to stop the ad.
*/
VpaidVideoPlayer.prototype.stopAd = function() {
this.log('Stopping ad');
// Calling AdStopped immediately terminates the ad. Setting a timeout allows
// events to go through.
var callback = this.callEvent_.bind(this);
/* START IAS Integration-Related Code */
// This VPAID ad implementation assumes that stopAd is the only method call that results in ad context being destroyed.
setTimeout(callback, 50, ['AdStopped']);
/* END IAS Integration-Related Code */
};
/**
* Called when the video player changes the width/height of the container.
*
* @param {number} width The new width.
* @param {number} height A new height.
* @param {string} viewMode A new view mode.
*/
VpaidVideoPlayer.prototype.resizeAd = function(width, height, viewMode) {
this.log('resizeAd ' + width + 'x' + height + ' ' + viewMode);
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.updateVideoPlayerSize_();
this.callEvent_('AdSizeChange');
};
/**
* Pauses the ad.
*/
VpaidVideoPlayer.prototype.pauseAd = function() {
this.log('pauseAd');
this.videoSlot_.pause();
this.callEvent_('AdPaused');
};
/**
* Resumes the ad.
*/
VpaidVideoPlayer.prototype.resumeAd = function() {
this.log('resumeAd');
this.videoSlot_.play();
this.callEvent_('AdPlaying');
};
/**
* Expands the ad.
*/
VpaidVideoPlayer.prototype.expandAd = function() {
this.log('expandAd');
this.attributes_['expanded'] = true;
this.callEvent_('AdExpanded');
};
/**
* Collapses the ad.
*/
VpaidVideoPlayer.prototype.collapseAd = function() {
this.log('collapseAd');
this.attributes_['expanded'] = false;
};
/**
* Skips the ad.
*/
VpaidVideoPlayer.prototype.skipAd = function() {
this.log('skipAd');
var skippableState = this.attributes_['skippableState'];
if (skippableState) {
this.callEvent_('AdSkipped');
}
};
/**
* Registers a callback for an event.
*
* @param {Function} aCallback The callback function.
* @param {string} eventName The callback type.
* @param {Object} aContext The context for the callback.
*/
VpaidVideoPlayer.prototype.subscribe = function(
aCallback,
eventName,
aContext) {
this.log('Subscribe ' + eventName);
var callBack = aCallback.bind(aContext);
this.eventsCallbacks_[eventName] = callBack;
};
/**
* Removes a callback based on the eventName.
*
* @param {string} eventName The callback type.
*/
VpaidVideoPlayer.prototype.unsubscribe = function(eventName) {
this.log('unsubscribe ' + eventName);
this.eventsCallbacks_[eventName] = null;
};
/**
* Returns whether the ad is linear.
*
* @return {boolean} True if the ad is a linear, false for non linear.
*/
VpaidVideoPlayer.prototype.getAdLinear = function() {
return this.attributes_['linear'];
};
/**
* Returns ad width.
*
* @return {number} The ad width.
*/
VpaidVideoPlayer.prototype.getAdWidth = function() {
return this.attributes_['width'];
};
/**
* Returns ad height.
*
* @return {number} The ad height.
*/
VpaidVideoPlayer.prototype.getAdHeight = function() {
return this.attributes_['height'];
};
/**
* Returns true if the ad is expanded.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdExpanded = function() {
this.log('getAdExpanded');
return this.attributes_['expanded'];
};
/**
* Returns the skippable state of the ad.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdSkippableState = function() {
this.log('getAdSkippableState');
return this.attributes_['skippableState'];
};
/**
* Returns the remaining ad time, in seconds.
*
* @return {number} The time remaining in the ad.
*/
VpaidVideoPlayer.prototype.getAdRemainingTime = function() {
return this.attributes_['remainingTime'];
};
/**
* Returns the duration of the ad, in seconds.
*
* @return {number} The duration of the ad.
*/
VpaidVideoPlayer.prototype.getAdDuration = function() {
return this.attributes_['duration'];
};
/**
* Returns the ad volume.
*
* @return {number} The volume of the ad.
*/
VpaidVideoPlayer.prototype.getAdVolume = function() {
this.log('getAdVolume');
return this.attributes_['volume'];
};
/**
* Sets the ad volume.
*
* @param {number} value The volume in percentage.
*/
VpaidVideoPlayer.prototype.setAdVolume = function(value) {
this.attributes_['volume'] = value;
this.log('setAdVolume ' + value);
this.callEvent_('AdVolumeChange');
};
/**
* Returns a list of companion ads for the ad.
*
* @return {string} List of companions in VAST XML.
*/
VpaidVideoPlayer.prototype.getAdCompanions = function() {
return this.attributes_['companions'];
};
/**
* Returns a list of icons.
*
* @return {string} A list of icons.
*/
VpaidVideoPlayer.prototype.getAdIcons = function() {
return this.attributes_['icons'];
};
/**
* Logs events and messages.
*
* @param {string} message
*/
VpaidVideoPlayer.prototype.log = function(message) {
console.log(message);
};
/**
* Calls an event if there is a callback.
*
* @param {string} eventType
* @private
*/
VpaidVideoPlayer.prototype.callEvent_ = function(eventType) {
/* START IAS Integration-Related Code */
// Send data to IAS first
if (this.fwVansInstance_ && this.cmVansInstance_) {
var vansEventName,
adContext = {
ad_duration: this.getAdDuration(),
width: this.getAdWidth(),
height: this.getAdHeight(),
volume: this.getAdVolume()
};
if (eventType === 'AdSizeChange') {
// add viewMode when it is necessary for context
adContext.viewMode = this.attributes_['viewMode'];
}
// remap name of event sent to IAS when needed
if (['AdSizeChange', 'AdExpanded', 'AdUserMinimize'].indexOf(eventType) > 0) { // no adUserMinimize in this implementation of VPAID
vansEventName = 'resizeAd';
} else {
vansEventName = eventType;
}
// add additional attributes to Open Web ad impression
if (eventType === 'AdImpression') {
var timeToDecisionWhenTimedOut = new Date().valueOf();
adContext.integral_timeToDecision = this.integral_timeout_ || timeToDecisionWhenTimedOut;
// indicate to IAS that you did not block the ad
adContext.integral_didBlock = false;
}
if (eventType === 'AdBlocked') {
adContext.integral_timeToDecision = this.integral_timeout_;
adContext.integral_didBlock = true;
vansEventName = 'AdImpression'; // send to VANS as an AdImpression event
// this.sendAdErrorWithAdBlockedMessage is not implemented here.
// This section primarily serves to underline that you should add a timeout before sending the AdBlocked notification to the player.
var sendAdErrorToPlayerAfterTimeout = setTimeout(this.sendAdErrorWithAdBlockedMessage, 500);
}
this.fwVansInstance_.sendEvent(vansEventName, adContext);
this.cmVansInstance_.sendEvent(vansEventName, adContext);
}
if (eventType in this.eventsCallbacks_) {
// send data to player, optionally with timeout
if (eventType === 'AdStopped' || eventType === 'AdSkipped' || 'AdError') {
setTimeout(this.eventsCallbacks_[eventType].bind(this), 500);
} else {
this.eventsCallbacks_[eventType]();
}
}
};
/**
* Main function called by wrapper to get the VPAID ad.
*
* @return {Object} The VPAID compliant ad.
*/
var getVPAIDAd = function() {
return new VpaidVideoPlayer();
};
Example of a VPAID Ad Unit integration with the Web Video SDK measuring in Campaign Monitoring mode, with advertiser macros. Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
// Example of a VPAID Ad Unit integration with the Web Video SDK measuring in Campaign Monitoring mode, with advertiser macros. Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
var __IASVANS = function(){
/* ... */
};
/**
* @constructor
*/
var VpaidVideoPlayer = function() {
/**
* The slot is the div element on the main page that the ad is supposed to
* occupy.
* @type {Object}
* @private
*/
this.slot_ = null;
/**
* The video slot is the video element used by the ad to render video content.
* @type {Object}
* @private
*/
this.videoSlot_ = null;
/**
* An object containing all registered events. These events are all
* callbacks for use by the VPAID ad.
* @type {Object}
* @private
*/
this.eventsCallbacks_ = {};
/**
* A list of getable and setable attributes.
* @type {Object}
* @private
*/
this.attributes_ = {
'companions' : '',
'desiredBitrate' : 256,
'duration' : 10,
'expanded' : false,
'height' : 0,
'icons' : '',
'linear' : true,
'remainingTime' : 10,
'skippableState' : false,
'viewMode' : 'normal',
'width' : 0,
'volume' : 1.0
};
/**
* A set of ad playback events to be reported.
* @type {Object}
* @private
*/
this.quartileEvents_ = [
{event: 'AdVideoStart', value: 0},
{event: 'AdVideoFirstQuartile', value: 25},
{event: 'AdVideoMidpoint', value: 50},
{event: 'AdVideoThirdQuartile', value: 75},
{event: 'AdVideoComplete', value: 100}
];
/**
* @type {number} An index into what quartile was last reported.
* @private
*/
this.nextQuartileIndex_ = 0;
/**
* Parameters passed in from the AdParameters section of the VAST.
* Used for video URL and MIME type.
*
* @type {!object}
* @private
*/
this.parameters_ = {};
};
/**
* Returns the supported VPAID version.
* @param {string} version
* @return {string}
*/
VpaidVideoPlayer.prototype.handshakeVersion = function(version) {
return ('2.0');
};
/**
* Initializes all attributes in the ad. The ad will not start until startAd is\
* called.
*
* @param {number} width The ad width.
* @param {number} height The ad height.
* @param {string} viewMode The ad view mode.
* @param {number} desiredBitrate The desired bitrate.
* @param {Object} creativeData Data associated with the creative.
* @param {Object} environmentVars Runtime variables associated with the
* creative like the slot and video slot.
*/
VpaidVideoPlayer.prototype.initAd = function(
width,
height,
viewMode,
desiredBitrate,
creativeData,
environmentVars) {
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.attributes_['desiredBitrate'] = desiredBitrate;
// slot and videoSlot are passed as part of the environmentVars
this.slot_ = environmentVars.slot;
this.videoSlot_ = environmentVars.videoSlot;
// Parse the incoming ad parameters.
this.parameters_ = JSON.parse(creativeData['AdParameters']);
this.log('initAd ' + width + 'x' + height +
' ' + viewMode + ' ' + desiredBitrate);
this.updateVideoSlot_();
this.videoSlot_.addEventListener(
'timeupdate',
this.timeUpdateHandler_.bind(this),
false);
this.videoSlot_.addEventListener(
'loadedmetadata',
this.loadedMetadata_.bind(this),
false);
this.videoSlot_.addEventListener(
'ended',
this.stopAd.bind(this),
false);
/* START IAS Integration-Related Code */
// VPAID events to pass to IAS VANS
this.iasRequiredEvents_ = [
'AdStarted',
'AdStopped',
'AdImpression',
'AdVideoStart',
'AdVideoFirstQuartile',
'AdVideoMidpoint',
'AdVideoThirdQuartile',
'AdVideoComplete',
'AdUserMinimize',
'AdUserClose',
'AdPaused',
'AdPlaying',
'AdLinearChange',
'AdExpandedChange',
'AdVolumeChange',
'AdClickThru',
'AdError',
'AdSizeChange'
];
// init VANS
this.cmVansInstance_ = __IASVANS();
var adNode = this._slot;
// advertiser
var cmConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID',
advId: 'PROVIDE-YOUR-OWN-ADV-ID',
campId: 'PROVIDE-YOUR-OWN-CAMP-ID',
creativeId: 'PROVIDE-YOUR-OWN-CREATIVE-ID',
placementId: 'PROVIDE-YOUR-OWN-PLACEMENT-ID',
chanId: 'PROVIDE-YOUR-OWN-CHANNEL-ID',
impId: 'PROVIDE-YOUR-OWN-IMPRESSION-ID',
onMeasurementComplete: this.stopAd.bind(this),
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
this.cmVansInstance_.initCM(config, adNode);
/* END IAS Integration-Related Code */
this.callEvent_('AdLoaded');
};
/**
* Called by the video element when video metadata is loaded.
* @private
*/
VpaidVideoPlayer.prototype.loadedMetadata_ = function() {
// The ad duration is not known until the media metadata is loaded.
// Then, update the player with the duration change.
this.attributes_['duration'] = this.videoSlot_.duration;
this.callEvent_('AdDurationChange');
};
/**
* Called by the video element when the video reaches specific points during
* playback.
* @private
*/
VpaidVideoPlayer.prototype.timeUpdateHandler_ = function() {
if (this.nextQuartileIndex_ >= this.quartileEvents_.length) {
return;
}
var percentPlayed =
this.videoSlot_.currentTime * 100.0 / this.videoSlot_.duration;
if (percentPlayed >= this.quartileEvents_[this.nextQuartileIndex_].value) {
var lastQuartileEvent = this.quartileEvents_[this.nextQuartileIndex_].event;
this.eventsCallbacks_[lastQuartileEvent]();
this.nextQuartileIndex_ += 1;
}
if (this.videoSlot_.duration > 0) {
this.attributes_['remainingTime'] =
this.videoSlot_.duration - this.videoSlot_.currentTime;
}
};
/**
* Creates or updates the video slot and fills it with a supported video.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoSlot_ = function() {
if (this.videoSlot_ == null) {
this.videoSlot_ = document.createElement('video');
this.log('Warning: No video element passed to ad, creating element.');
this.slot_.appendChild(this.videoSlot_);
}
this.updateVideoPlayerSize_();
var foundSource = false;
var videos = this.parameters_.videos || [];
for (var i = 0; i < videos.length; i++) {
// Choose the first video with a supported mimetype.
if (this.videoSlot_.canPlayType(videos[i].mimetype) != '') {
this.videoSlot_.setAttribute('src', videos[i].url);
foundSource = true;
break;
}
}
if (!foundSource) {
// Unable to find a source video.
this.callEvent_('AdError');
}
};
/**
* Helper function to update the size of the video player.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoPlayerSize_ = function() {
this.videoSlot_.setAttribute('width', this.attributes_['width']);
this.videoSlot_.setAttribute('height', this.attributes_['height']);
};
/**
* Called by the wrapper to start the ad.
*/
VpaidVideoPlayer.prototype.startAd = function() {
this.log('Starting ad');
this.videoSlot_.play();
this.callEvent_('AdStarted');
this.callEvent_('AdImpression'); // this implementation has AdImpression on video start
};
/**
* Called by the wrapper to stop the ad.
*/
VpaidVideoPlayer.prototype.stopAd = function() {
this.log('Stopping ad');
// Calling AdStopped immediately terminates the ad. Setting a timeout allows
// events to go through.
var callback = this.callEvent_.bind(this);
/* START IAS Integration-Related Code */
// This VPAID ad implementation assumes that stopAd is the only method call that results in ad context being destroyed.
setTimeout(callback, 50, ['AdStopped']);
/* END IAS Integration-Related Code */
};
/**
* Called when the video player changes the width/height of the container.
*
* @param {number} width The new width.
* @param {number} height A new height.
* @param {string} viewMode A new view mode.
*/
VpaidVideoPlayer.prototype.resizeAd = function(width, height, viewMode) {
this.log('resizeAd ' + width + 'x' + height + ' ' + viewMode);
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.updateVideoPlayerSize_();
this.callEvent_('AdSizeChange');
};
/**
* Pauses the ad.
*/
VpaidVideoPlayer.prototype.pauseAd = function() {
this.log('pauseAd');
this.videoSlot_.pause();
this.callEvent_('AdPaused');
};
/**
* Resumes the ad.
*/
VpaidVideoPlayer.prototype.resumeAd = function() {
this.log('resumeAd');
this.videoSlot_.play();
this.callEvent_('AdPlaying');
};
/**
* Expands the ad.
*/
VpaidVideoPlayer.prototype.expandAd = function() {
this.log('expandAd');
this.attributes_['expanded'] = true;
this.callEvent_('AdExpanded');
};
/**
* Collapses the ad.
*/
VpaidVideoPlayer.prototype.collapseAd = function() {
this.log('collapseAd');
this.attributes_['expanded'] = false;
};
/**
* Skips the ad.
*/
VpaidVideoPlayer.prototype.skipAd = function() {
this.log('skipAd');
var skippableState = this.attributes_['skippableState'];
if (skippableState) {
this.callEvent_('AdSkipped');
}
};
/**
* Registers a callback for an event.
*
* @param {Function} aCallback The callback function.
* @param {string} eventName The callback type.
* @param {Object} aContext The context for the callback.
*/
VpaidVideoPlayer.prototype.subscribe = function(
aCallback,
eventName,
aContext) {
this.log('Subscribe ' + eventName);
var callBack = aCallback.bind(aContext);
this.eventsCallbacks_[eventName] = callBack;
};
/**
* Removes a callback based on the eventName.
*
* @param {string} eventName The callback type.
*/
VpaidVideoPlayer.prototype.unsubscribe = function(eventName) {
this.log('unsubscribe ' + eventName);
this.eventsCallbacks_[eventName] = null;
};
/**
* Returns whether the ad is linear.
*
* @return {boolean} True if the ad is a linear, false for non linear.
*/
VpaidVideoPlayer.prototype.getAdLinear = function() {
return this.attributes_['linear'];
};
/**
* Returns ad width.
*
* @return {number} The ad width.
*/
VpaidVideoPlayer.prototype.getAdWidth = function() {
return this.attributes_['width'];
};
/**
* Returns ad height.
*
* @return {number} The ad height.
*/
VpaidVideoPlayer.prototype.getAdHeight = function() {
return this.attributes_['height'];
};
/**
* Returns true if the ad is expanded.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdExpanded = function() {
this.log('getAdExpanded');
return this.attributes_['expanded'];
};
/**
* Returns the skippable state of the ad.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdSkippableState = function() {
this.log('getAdSkippableState');
return this.attributes_['skippableState'];
};
/**
* Returns the remaining ad time, in seconds.
*
* @return {number} The time remaining in the ad.
*/
VpaidVideoPlayer.prototype.getAdRemainingTime = function() {
return this.attributes_['remainingTime'];
};
/**
* Returns the duration of the ad, in seconds.
*
* @return {number} The duration of the ad.
*/
VpaidVideoPlayer.prototype.getAdDuration = function() {
return this.attributes_['duration'];
};
/**
* Returns the ad volume.
*
* @return {number} The volume of the ad.
*/
VpaidVideoPlayer.prototype.getAdVolume = function() {
this.log('getAdVolume');
return this.attributes_['volume'];
};
/**
* Sets the ad volume.
*
* @param {number} value The volume in percentage.
*/
VpaidVideoPlayer.prototype.setAdVolume = function(value) {
this.attributes_['volume'] = value;
this.log('setAdVolume ' + value);
this.callEvent_('AdVolumeChange');
};
/**
* Returns a list of companion ads for the ad.
*
* @return {string} List of companions in VAST XML.
*/
VpaidVideoPlayer.prototype.getAdCompanions = function() {
return this.attributes_['companions'];
};
/**
* Returns a list of icons.
*
* @return {string} A list of icons.
*/
VpaidVideoPlayer.prototype.getAdIcons = function() {
return this.attributes_['icons'];
};
/**
* Logs events and messages.
*
* @param {string} message
*/
VpaidVideoPlayer.prototype.log = function(message) {
console.log(message);
};
/**
* Calls an event if there is a callback.
*
* @param {string} eventType
* @private
*/
VpaidVideoPlayer.prototype.callEvent_ = function(eventType) {
/* START IAS Integration-Related Code */
var sendDataToIas = function(eventType) {
if (eventShouldBeReportedToIas()) {
var iasEventName = getIasEventName(eventType),
iasAdContext = createIasAdContext.call(this, eventType);
this.cmVansInstance_.sendEvent(iasEventName, iasAdContext);
}
};
var eventShouldBeReportedToIas = this.cmVansInstance_ && this.iasRequiredEvents_.indexOf(eventType) > 0;
var getIasEventName = function(eventType) {
var VPAID_TO_IAS_EVENT_MAP = {
'AdSizeChange': 'resizeAd',
'AdExpanded': 'resizeAd',
'AdUserMinimize': 'resizeAd' // no adUserMinimize in this implementation of VPAID
};
var remappedEventName = VPAID_TO_IAS_EVENT_MAP[eventType];
return remappedEventName === undefined ? remappedEventName : eventType;
};
var createIasAdContext = function(eventType) {
var adContext = {
ad_duration: this.getAdDuration(),
width: this.getAdWidth(),
height: this.getAdHeight(),
volume: this.getAdVolume()
};
// add required event-specific context properties
if (eventType === 'AdSizeChange') {
adContext.viewMode = this.attributes_['viewMode'];
}
return adContext;
};
sendDataToIas.call(this, eventType);
if (eventType in this.eventsCallbacks_) {
// send data to player, optionally with timeout
if (eventType === 'AdStopped' || eventType === 'AdSkipped' || 'AdError') {
setTimeout(this.eventsCallbacks_[eventType].bind(this), 500);
} else {
this.eventsCallbacks_[eventType]();
}
}
/* END IAS Integration-Related Code */
};
/**
* Main function called by wrapper to get the VPAID ad.
*
* @return {Object} The VPAID compliant ad.
*/
var getVPAIDAd = function() {
return new VpaidVideoPlayer();
};
Example of a VPAID Ad Unit integration with the Web Video SDK measuring in Campaign Monitoring mode, with publisher macros. Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
// Example of a VPAID Ad Unit integration with the Web Video SDK measuring in Campaign Monitoring mode, with publisher macros. Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
var __IASVANS = function(){
/* ... */
};
/**
* @constructor
*/
var VpaidVideoPlayer = function() {
/**
* The slot is the div element on the main page that the ad is supposed to
* occupy.
* @type {Object}
* @private
*/
this.slot_ = null;
/**
* The video slot is the video element used by the ad to render video content.
* @type {Object}
* @private
*/
this.videoSlot_ = null;
/**
* An object containing all registered events. These events are all
* callbacks for use by the VPAID ad.
* @type {Object}
* @private
*/
this.eventsCallbacks_ = {};
/**
* A list of getable and setable attributes.
* @type {Object}
* @private
*/
this.attributes_ = {
'companions' : '',
'desiredBitrate' : 256,
'duration' : 10,
'expanded' : false,
'height' : 0,
'icons' : '',
'linear' : true,
'remainingTime' : 10,
'skippableState' : false,
'viewMode' : 'normal',
'width' : 0,
'volume' : 1.0
};
/**
* A set of ad playback events to be reported.
* @type {Object}
* @private
*/
this.quartileEvents_ = [
{event: 'AdVideoStart', value: 0},
{event: 'AdVideoFirstQuartile', value: 25},
{event: 'AdVideoMidpoint', value: 50},
{event: 'AdVideoThirdQuartile', value: 75},
{event: 'AdVideoComplete', value: 100}
];
/**
* @type {number} An index into what quartile was last reported.
* @private
*/
this.nextQuartileIndex_ = 0;
/**
* Parameters passed in from the AdParameters section of the VAST.
* Used for video URL and MIME type.
*
* @type {!object}
* @private
*/
this.parameters_ = {};
};
/**
* Returns the supported VPAID version.
* @param {string} version
* @return {string}
*/
VpaidVideoPlayer.prototype.handshakeVersion = function(version) {
return ('2.0');
};
/**
* Initializes all attributes in the ad. The ad will not start until startAd is\
* called.
*
* @param {number} width The ad width.
* @param {number} height The ad height.
* @param {string} viewMode The ad view mode.
* @param {number} desiredBitrate The desired bitrate.
* @param {Object} creativeData Data associated with the creative.
* @param {Object} environmentVars Runtime variables associated with the
* creative like the slot and video slot.
*/
VpaidVideoPlayer.prototype.initAd = function(
width,
height,
viewMode,
desiredBitrate,
creativeData,
environmentVars) {
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.attributes_['desiredBitrate'] = desiredBitrate;
// slot and videoSlot are passed as part of the environmentVars
this.slot_ = environmentVars.slot;
this.videoSlot_ = environmentVars.videoSlot;
// Parse the incoming ad parameters.
this.parameters_ = JSON.parse(creativeData['AdParameters']);
this.log('initAd ' + width + 'x' + height +
' ' + viewMode + ' ' + desiredBitrate);
this.updateVideoSlot_();
this.videoSlot_.addEventListener(
'timeupdate',
this.timeUpdateHandler_.bind(this),
false);
this.videoSlot_.addEventListener(
'loadedmetadata',
this.loadedMetadata_.bind(this),
false);
this.videoSlot_.addEventListener(
'ended',
this.stopAd.bind(this),
false);
/* START IAS Integration-Related Code */
// init VANS
this.cmVansInstance_ = __IASVANS();
var adNode = this._slot;
// publisher
var cmConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID',
campId: 'PROVIDE-YOUR-OWN-CAMP-ID',
chanId: 'PROVIDE-YOUR-OWN-CHAN-ID',
placementId: 'PROVIDE-YOUR-OWN-PLACEMENT-ID',
pubOrder: 'PROVIDE-YOUR-OWN-PUB-ORDER',
pubId: 'PROVIDE-YOUR-OWN-PUB-ID',
pubCreative: 'PROVIDE-YOUR-OWN-PUB-CREATIVE',
custom: 'YOUR-CUSTOM-MACRO-1',
custom2: 'YOUR-CUSTOM-MACRO-2',
onMeasurementComplete: this.stopAd.bind(this),
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
this.cmVansInstance_.initCM(config, adNode);
/* END IAS Integration-Related Code */
this.callEvent_('AdLoaded');
};
/**
* Called by the video element when video metadata is loaded.
* @private
*/
VpaidVideoPlayer.prototype.loadedMetadata_ = function() {
// The ad duration is not known until the media metadata is loaded.
// Then, update the player with the duration change.
this.attributes_['duration'] = this.videoSlot_.duration;
this.callEvent_('AdDurationChange');
};
/**
* Called by the video element when the video reaches specific points during
* playback.
* @private
*/
VpaidVideoPlayer.prototype.timeUpdateHandler_ = function() {
if (this.nextQuartileIndex_ >= this.quartileEvents_.length) {
return;
}
var percentPlayed =
this.videoSlot_.currentTime * 100.0 / this.videoSlot_.duration;
if (percentPlayed >= this.quartileEvents_[this.nextQuartileIndex_].value) {
var lastQuartileEvent = this.quartileEvents_[this.nextQuartileIndex_].event;
this.eventsCallbacks_[lastQuartileEvent]();
this.nextQuartileIndex_ += 1;
}
if (this.videoSlot_.duration > 0) {
this.attributes_['remainingTime'] =
this.videoSlot_.duration - this.videoSlot_.currentTime;
}
};
/**
* Creates or updates the video slot and fills it with a supported video.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoSlot_ = function() {
if (this.videoSlot_ == null) {
this.videoSlot_ = document.createElement('video');
this.log('Warning: No video element passed to ad, creating element.');
this.slot_.appendChild(this.videoSlot_);
}
this.updateVideoPlayerSize_();
var foundSource = false;
var videos = this.parameters_.videos || [];
for (var i = 0; i < videos.length; i++) {
// Choose the first video with a supported mimetype.
if (this.videoSlot_.canPlayType(videos[i].mimetype) != '') {
this.videoSlot_.setAttribute('src', videos[i].url);
foundSource = true;
break;
}
}
if (!foundSource) {
// Unable to find a source video.
this.callEvent_('AdError');
}
};
/**
* Helper function to update the size of the video player.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoPlayerSize_ = function() {
this.videoSlot_.setAttribute('width', this.attributes_['width']);
this.videoSlot_.setAttribute('height', this.attributes_['height']);
};
/**
* Called by the wrapper to start the ad.
*/
VpaidVideoPlayer.prototype.startAd = function() {
this.log('Starting ad');
this.videoSlot_.play();
this.callEvent_('AdStarted');
this.callEvent_('AdImpression'); // this implementation has AdImpression on video start
};
/**
* Called by the wrapper to stop the ad.
*/
VpaidVideoPlayer.prototype.stopAd = function() {
this.log('Stopping ad');
// Calling AdStopped immediately terminates the ad. Setting a timeout allows
// events to go through.
var callback = this.callEvent_.bind(this);
/* START IAS Integration-Related Code */
// This VPAID ad implementation assumes that stopAd is the only method call that results in ad context being destroyed.
setTimeout(callback, 50, ['AdStopped']);
/* END IAS Integration-Related Code */
};
/**
* Called when the video player changes the width/height of the container.
*
* @param {number} width The new width.
* @param {number} height A new height.
* @param {string} viewMode A new view mode.
*/
VpaidVideoPlayer.prototype.resizeAd = function(width, height, viewMode) {
this.log('resizeAd ' + width + 'x' + height + ' ' + viewMode);
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.updateVideoPlayerSize_();
this.callEvent_('AdSizeChange');
};
/**
* Pauses the ad.
*/
VpaidVideoPlayer.prototype.pauseAd = function() {
this.log('pauseAd');
this.videoSlot_.pause();
this.callEvent_('AdPaused');
};
/**
* Resumes the ad.
*/
VpaidVideoPlayer.prototype.resumeAd = function() {
this.log('resumeAd');
this.videoSlot_.play();
this.callEvent_('AdPlaying');
};
/**
* Expands the ad.
*/
VpaidVideoPlayer.prototype.expandAd = function() {
this.log('expandAd');
this.attributes_['expanded'] = true;
this.callEvent_('AdExpanded');
};
/**
* Collapses the ad.
*/
VpaidVideoPlayer.prototype.collapseAd = function() {
this.log('collapseAd');
this.attributes_['expanded'] = false;
};
/**
* Skips the ad.
*/
VpaidVideoPlayer.prototype.skipAd = function() {
this.log('skipAd');
var skippableState = this.attributes_['skippableState'];
if (skippableState) {
this.callEvent_('AdSkipped');
}
};
/**
* Registers a callback for an event.
*
* @param {Function} aCallback The callback function.
* @param {string} eventName The callback type.
* @param {Object} aContext The context for the callback.
*/
VpaidVideoPlayer.prototype.subscribe = function(
aCallback,
eventName,
aContext) {
this.log('Subscribe ' + eventName);
var callBack = aCallback.bind(aContext);
this.eventsCallbacks_[eventName] = callBack;
};
/**
* Removes a callback based on the eventName.
*
* @param {string} eventName The callback type.
*/
VpaidVideoPlayer.prototype.unsubscribe = function(eventName) {
this.log('unsubscribe ' + eventName);
this.eventsCallbacks_[eventName] = null;
};
/**
* Returns whether the ad is linear.
*
* @return {boolean} True if the ad is a linear, false for non linear.
*/
VpaidVideoPlayer.prototype.getAdLinear = function() {
return this.attributes_['linear'];
};
/**
* Returns ad width.
*
* @return {number} The ad width.
*/
VpaidVideoPlayer.prototype.getAdWidth = function() {
return this.attributes_['width'];
};
/**
* Returns ad height.
*
* @return {number} The ad height.
*/
VpaidVideoPlayer.prototype.getAdHeight = function() {
return this.attributes_['height'];
};
/**
* Returns true if the ad is expanded.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdExpanded = function() {
this.log('getAdExpanded');
return this.attributes_['expanded'];
};
/**
* Returns the skippable state of the ad.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdSkippableState = function() {
this.log('getAdSkippableState');
return this.attributes_['skippableState'];
};
/**
* Returns the remaining ad time, in seconds.
*
* @return {number} The time remaining in the ad.
*/
VpaidVideoPlayer.prototype.getAdRemainingTime = function() {
return this.attributes_['remainingTime'];
};
/**
* Returns the duration of the ad, in seconds.
*
* @return {number} The duration of the ad.
*/
VpaidVideoPlayer.prototype.getAdDuration = function() {
return this.attributes_['duration'];
};
/**
* Returns the ad volume.
*
* @return {number} The volume of the ad.
*/
VpaidVideoPlayer.prototype.getAdVolume = function() {
this.log('getAdVolume');
return this.attributes_['volume'];
};
/**
* Sets the ad volume.
*
* @param {number} value The volume in percentage.
*/
VpaidVideoPlayer.prototype.setAdVolume = function(value) {
this.attributes_['volume'] = value;
this.log('setAdVolume ' + value);
this.callEvent_('AdVolumeChange');
};
/**
* Returns a list of companion ads for the ad.
*
* @return {string} List of companions in VAST XML.
*/
VpaidVideoPlayer.prototype.getAdCompanions = function() {
return this.attributes_['companions'];
};
/**
* Returns a list of icons.
*
* @return {string} A list of icons.
*/
VpaidVideoPlayer.prototype.getAdIcons = function() {
return this.attributes_['icons'];
};
/**
* Logs events and messages.
*
* @param {string} message
*/
VpaidVideoPlayer.prototype.log = function(message) {
console.log(message);
};
/**
* Calls an event if there is a callback.
*
* @param {string} eventType
* @private
*/
VpaidVideoPlayer.prototype.callEvent_ = function(eventType) {
/* START IAS Integration-Related Code */
// Send data to IAS
if (this.cmVansInstance_) {
var vansEventName,
adContext = {
ad_duration: this.getAdDuration(),
width: this.getAdWidth(),
height: this.getAdHeight(),
volume: this.getAdVolume()
};
if (eventType === 'AdSizeChange') {
// add viewMode when it is necessary for context
adContext.viewMode = this.attributes_['viewMode'];
}
// remap name of event sent to IAS when needed
if (['AdSizeChange', 'AdExpanded', 'AdUserMinimize'].indexOf(eventType) > 0) { // no adUserMinimize in this implementation of VPAID
vansEventName = 'resizeAd';
} else {
vansEventName = eventType;
}
this.cmVansInstance_.sendEvent(vansEventName, adContext);
}
if (eventType in this.eventsCallbacks_) {
// send data to player, optionally with timeout
if (eventType === 'AdStopped' || eventType === 'AdSkipped' || 'AdError') {
setTimeout(this.eventsCallbacks_[eventType].bind(this), 500);
} else {
this.eventsCallbacks_[eventType]();
}
}
/* END IAS Integration-Related Code */
};
/**
* Main function called by wrapper to get the VPAID ad.
*
* @return {Object} The VPAID compliant ad.
*/
var getVPAIDAd = function() {
return new VpaidVideoPlayer();
};
Example of a VPAID Ad Unit integration with the Web Video SDK measuring in Open Web mode, with blocking support. Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
// Example of a VPAID Ad Unit integration with the Web Video SDK measuring in Open Web mode, with blocking support. Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
var __IASVANS = function(){
/* ... */
};
/**
* @constructor
*/
var VpaidVideoPlayer = function() {
/**
* The slot is the div element on the main page that the ad is supposed to
* occupy.
* @type {Object}
* @private
*/
this.slot_ = null;
/**
* The video slot is the video element used by the ad to render video content.
* @type {Object}
* @private
*/
this.videoSlot_ = null;
/**
* An object containing all registered events. These events are all
* callbacks for use by the VPAID ad.
* @type {Object}
* @private
*/
this.eventsCallbacks_ = {};
/**
* A list of getable and setable attributes.
* @type {Object}
* @private
*/
this.attributes_ = {
'companions' : '',
'desiredBitrate' : 256,
'duration' : 10,
'expanded' : false,
'height' : 0,
'icons' : '',
'linear' : true,
'remainingTime' : 10,
'skippableState' : false,
'viewMode' : 'normal',
'width' : 0,
'volume' : 1.0
};
/**
* A set of ad playback events to be reported.
* @type {Object}
* @private
*/
this.quartileEvents_ = [
{event: 'AdVideoStart', value: 0},
{event: 'AdVideoFirstQuartile', value: 25},
{event: 'AdVideoMidpoint', value: 50},
{event: 'AdVideoThirdQuartile', value: 75},
{event: 'AdVideoComplete', value: 100}
];
/**
* @type {number} An index into what quartile was last reported.
* @private
*/
this.nextQuartileIndex_ = 0;
/**
* Parameters passed in from the AdParameters section of the VAST.
* Used for video URL and MIME type.
*
* @type {!object}
* @private
*/
this.parameters_ = {};
};
/**
* Returns the supported VPAID version.
* @param {string} version
* @return {string}
*/
VpaidVideoPlayer.prototype.handshakeVersion = function(version) {
return ('2.0');
};
/**
* Initializes all attributes in the ad. The ad will not start until startAd is\
* called.
*
* @param {number} width The ad width.
* @param {number} height The ad height.
* @param {string} viewMode The ad view mode.
* @param {number} desiredBitrate The desired bitrate.
* @param {Object} creativeData Data associated with the creative.
* @param {Object} environmentVars Runtime variables associated with the
* creative like the slot and video slot.
*/
VpaidVideoPlayer.prototype.initAd = function(
width,
height,
viewMode,
desiredBitrate,
creativeData,
environmentVars) {
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.attributes_['desiredBitrate'] = desiredBitrate;
// slot and videoSlot are passed as part of the environmentVars
this.slot_ = environmentVars.slot;
this.videoSlot_ = environmentVars.videoSlot;
// Parse the incoming ad parameters.
this.parameters_ = JSON.parse(creativeData['AdParameters']);
this.log('initAd ' + width + 'x' + height +
' ' + viewMode + ' ' + desiredBitrate);
this.updateVideoSlot_();
this.videoSlot_.addEventListener(
'timeupdate',
this.timeUpdateHandler_.bind(this),
false);
this.videoSlot_.addEventListener(
'loadedmetadata',
this.loadedMetadata_.bind(this),
false);
this.videoSlot_.addEventListener(
'ended',
this.stopAd.bind(this),
false);
/* START IAS Integration-Related Code */
// init VANS
this.fwVansInstance_ = __IASVANS();
var adNode = this._slot;
// Open Web blocking
var fwConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
advEntityId: 'YOUR-IAS-PROVIDED-ADV-ENTITY-ID',
pubEntityId: 'YOUR-IAS-PROVIDED-PUB-ENTITY-ID',
impId: 'PROVIDE-YOUR-OWN-IMPRESSION-ID',
onMeasurementComplete: this.stopAd.bind(this),
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
// proceed with ad if IAS blocking instructions are not received in time.
var blockingInstructionsTimeout = setTimeout(this.callEvent_('AdLoaded'), 1500);
// provide a blocking callback
var blockingCallback = function (result) {
if (result === 'block') {
this.integral_timeout_ = new Date().valueOf() - blockingTimeoutStart;
this.callEvent_('AdBlocked');
}
else if (result === 'safe') {
this.callEvent_('AdLoaded');
}
};
// start the blocking timeout before initFW
var blockingTimeoutStart = new Date().valueOf();
this.fwVansInstance_.initFW(config, adNode, blockingCallback);
/* END IAS Integration-Related Code */
};
/**
* Called by the video element when video metadata is loaded.
* @private
*/
VpaidVideoPlayer.prototype.loadedMetadata_ = function() {
// The ad duration is not known until the media metadata is loaded.
// Then, update the player with the duration change.
this.attributes_['duration'] = this.videoSlot_.duration;
this.callEvent_('AdDurationChange');
};
/**
* Called by the video element when the video reaches specific points during
* playback.
* @private
*/
VpaidVideoPlayer.prototype.timeUpdateHandler_ = function() {
if (this.nextQuartileIndex_ >= this.quartileEvents_.length) {
return;
}
var percentPlayed =
this.videoSlot_.currentTime * 100.0 / this.videoSlot_.duration;
if (percentPlayed >= this.quartileEvents_[this.nextQuartileIndex_].value) {
var lastQuartileEvent = this.quartileEvents_[this.nextQuartileIndex_].event;
this.eventsCallbacks_[lastQuartileEvent]();
this.nextQuartileIndex_ += 1;
}
if (this.videoSlot_.duration > 0) {
this.attributes_['remainingTime'] =
this.videoSlot_.duration - this.videoSlot_.currentTime;
}
};
/**
* Creates or updates the video slot and fills it with a supported video.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoSlot_ = function() {
if (this.videoSlot_ == null) {
this.videoSlot_ = document.createElement('video');
this.log('Warning: No video element passed to ad, creating element.');
this.slot_.appendChild(this.videoSlot_);
}
this.updateVideoPlayerSize_();
var foundSource = false;
var videos = this.parameters_.videos || [];
for (var i = 0; i < videos.length; i++) {
// Choose the first video with a supported mimetype.
if (this.videoSlot_.canPlayType(videos[i].mimetype) != '') {
this.videoSlot_.setAttribute('src', videos[i].url);
foundSource = true;
break;
}
}
if (!foundSource) {
// Unable to find a source video.
this.callEvent_('AdError');
}
};
/**
* Helper function to update the size of the video player.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoPlayerSize_ = function() {
this.videoSlot_.setAttribute('width', this.attributes_['width']);
this.videoSlot_.setAttribute('height', this.attributes_['height']);
};
/**
* Called by the wrapper to start the ad.
*/
VpaidVideoPlayer.prototype.startAd = function() {
this.log('Starting ad');
this.videoSlot_.play();
this.callEvent_('AdStarted');
this.callEvent_('AdImpression'); // this implementation has AdImpression on video start
};
/**
* Called by the wrapper to stop the ad.
*/
VpaidVideoPlayer.prototype.stopAd = function() {
this.log('Stopping ad');
// Calling AdStopped immediately terminates the ad. Setting a timeout allows
// events to go through.
var callback = this.callEvent_.bind(this);
/* START IAS Integration-Related Code */
// This VPAID ad implementation assumes that stopAd is the only method call that results in ad context being destroyed.
setTimeout(callback, 50, ['AdStopped']);
/* END IAS Integration-Related Code */
};
/**
* Called when the video player changes the width/height of the container.
*
* @param {number} width The new width.
* @param {number} height A new height.
* @param {string} viewMode A new view mode.
*/
VpaidVideoPlayer.prototype.resizeAd = function(width, height, viewMode) {
this.log('resizeAd ' + width + 'x' + height + ' ' + viewMode);
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.updateVideoPlayerSize_();
this.callEvent_('AdSizeChange');
};
/**
* Pauses the ad.
*/
VpaidVideoPlayer.prototype.pauseAd = function() {
this.log('pauseAd');
this.videoSlot_.pause();
this.callEvent_('AdPaused');
};
/**
* Resumes the ad.
*/
VpaidVideoPlayer.prototype.resumeAd = function() {
this.log('resumeAd');
this.videoSlot_.play();
this.callEvent_('AdPlaying');
};
/**
* Expands the ad.
*/
VpaidVideoPlayer.prototype.expandAd = function() {
this.log('expandAd');
this.attributes_['expanded'] = true;
this.callEvent_('AdExpanded');
};
/**
* Collapses the ad.
*/
VpaidVideoPlayer.prototype.collapseAd = function() {
this.log('collapseAd');
this.attributes_['expanded'] = false;
};
/**
* Skips the ad.
*/
VpaidVideoPlayer.prototype.skipAd = function() {
this.log('skipAd');
var skippableState = this.attributes_['skippableState'];
if (skippableState) {
this.callEvent_('AdSkipped');
}
};
/**
* Registers a callback for an event.
*
* @param {Function} aCallback The callback function.
* @param {string} eventName The callback type.
* @param {Object} aContext The context for the callback.
*/
VpaidVideoPlayer.prototype.subscribe = function(
aCallback,
eventName,
aContext) {
this.log('Subscribe ' + eventName);
var callBack = aCallback.bind(aContext);
this.eventsCallbacks_[eventName] = callBack;
};
/**
* Removes a callback based on the eventName.
*
* @param {string} eventName The callback type.
*/
VpaidVideoPlayer.prototype.unsubscribe = function(eventName) {
this.log('unsubscribe ' + eventName);
this.eventsCallbacks_[eventName] = null;
};
/**
* Returns whether the ad is linear.
*
* @return {boolean} True if the ad is a linear, false for non linear.
*/
VpaidVideoPlayer.prototype.getAdLinear = function() {
return this.attributes_['linear'];
};
/**
* Returns ad width.
*
* @return {number} The ad width.
*/
VpaidVideoPlayer.prototype.getAdWidth = function() {
return this.attributes_['width'];
};
/**
* Returns ad height.
*
* @return {number} The ad height.
*/
VpaidVideoPlayer.prototype.getAdHeight = function() {
return this.attributes_['height'];
};
/**
* Returns true if the ad is expanded.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdExpanded = function() {
this.log('getAdExpanded');
return this.attributes_['expanded'];
};
/**
* Returns the skippable state of the ad.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdSkippableState = function() {
this.log('getAdSkippableState');
return this.attributes_['skippableState'];
};
/**
* Returns the remaining ad time, in seconds.
*
* @return {number} The time remaining in the ad.
*/
VpaidVideoPlayer.prototype.getAdRemainingTime = function() {
return this.attributes_['remainingTime'];
};
/**
* Returns the duration of the ad, in seconds.
*
* @return {number} The duration of the ad.
*/
VpaidVideoPlayer.prototype.getAdDuration = function() {
return this.attributes_['duration'];
};
/**
* Returns the ad volume.
*
* @return {number} The volume of the ad.
*/
VpaidVideoPlayer.prototype.getAdVolume = function() {
this.log('getAdVolume');
return this.attributes_['volume'];
};
/**
* Sets the ad volume.
*
* @param {number} value The volume in percentage.
*/
VpaidVideoPlayer.prototype.setAdVolume = function(value) {
this.attributes_['volume'] = value;
this.log('setAdVolume ' + value);
this.callEvent_('AdVolumeChange');
};
/**
* Returns a list of companion ads for the ad.
*
* @return {string} List of companions in VAST XML.
*/
VpaidVideoPlayer.prototype.getAdCompanions = function() {
return this.attributes_['companions'];
};
/**
* Returns a list of icons.
*
* @return {string} A list of icons.
*/
VpaidVideoPlayer.prototype.getAdIcons = function() {
return this.attributes_['icons'];
};
/**
* Logs events and messages.
*
* @param {string} message
*/
VpaidVideoPlayer.prototype.log = function(message) {
console.log(message);
};
/**
* Calls an event if there is a callback.
*
* @param {string} eventType
* @private
*/
VpaidVideoPlayer.prototype.callEvent_ = function(eventType) {
/* START IAS Integration-Related Code */
// Send data to IAS
if (this.fwVansInstance_) {
var vansEventName,
adContext = {
ad_duration: this.getAdDuration(),
width: this.getAdWidth(),
height: this.getAdHeight(),
volume: this.getAdVolume()
};
if (eventType === 'AdSizeChange') {
// add viewMode when it is necessary for context
adContext.viewMode = this.attributes_['viewMode'];
}
// remap name of event sent to IAS when needed
if (['AdSizeChange', 'AdExpanded', 'AdUserMinimize'].indexOf(eventType) > 0) { // no adUserMinimize in this implementation of VPAID
vansEventName = 'resizeAd';
} else {
vansEventName = eventType;
}
// add additional attributes to Open Web ad impression
if (eventType === 'AdImpression') {
var timeToDecisionWhenTimedOut = new Date().valueOf();
adContext.integral_timeToDecision = this.integral_timeout_ || timeToDecisionWhenTimedOut;
// indicate to IAS that you did not block the ad
adContext.integral_didBlock = false;
}
if (eventType === 'AdBlocked') {
adContext.integral_timeToDecision = this.integral_timeout_;
adContext.integral_didBlock = true;
vansEventName = 'AdImpression'; // send to VANS as an AdImpression event
// this.sendAdErrorWithAdBlockedMessage is not implemented here.
// This section primarily serves to underline that you should add a timeout before sending the AdBlocked notification to the player.
var sendAdErrorToPlayerAfterTimeout = setTimeout(this.sendAdErrorWithAdBlockedMessage, 500);
}
this.fwVansInstance_.sendEvent(vansEventName, adContext);
}
if (eventType in this.eventsCallbacks_) {
// send data to player, optionally with timeout
if (eventType === 'AdStopped' || eventType === 'AdSkipped' || 'AdError') {
setTimeout(this.eventsCallbacks_[eventType].bind(this), 500);
} else {
this.eventsCallbacks_[eventType]();
}
}
/* END IAS Integration-Related Code */
};
/**
* Main function called by wrapper to get the VPAID ad.
*
* @return {Object} The VPAID compliant ad.
*/
var getVPAIDAd = function() {
return new VpaidVideoPlayer();
};
Example of a VPAID Ad Unit integration with the Web Video SDK measuring in Open Web mode, without blocking support (i.e. 'Open Web monitoring' mode). Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
// Example of a VPAID Ad Unit integration with the Web Video SDK measuring in Open Web mode, without blocking support (i.e. 'Open Web monitoring' mode). Integration code in VpaidVideoPlayer.initAd, and VpaidVideoPlayer.callEvent_ methods. Adapted from https://github.com/googleads/googleads-ima-html5/blob/master/vpaid/VpaidVideoAd.js
var __IASVANS = function(){
/* ... */
};
/**
* @constructor
*/
var VpaidVideoPlayer = function() {
/**
* The slot is the div element on the main page that the ad is supposed to
* occupy.
* @type {Object}
* @private
*/
this.slot_ = null;
/**
* The video slot is the video element used by the ad to render video content.
* @type {Object}
* @private
*/
this.videoSlot_ = null;
/**
* An object containing all registered events. These events are all
* callbacks for use by the VPAID ad.
* @type {Object}
* @private
*/
this.eventsCallbacks_ = {};
/**
* A list of getable and setable attributes.
* @type {Object}
* @private
*/
this.attributes_ = {
'companions' : '',
'desiredBitrate' : 256,
'duration' : 10,
'expanded' : false,
'height' : 0,
'icons' : '',
'linear' : true,
'remainingTime' : 10,
'skippableState' : false,
'viewMode' : 'normal',
'width' : 0,
'volume' : 1.0
};
/**
* A set of ad playback events to be reported.
* @type {Object}
* @private
*/
this.quartileEvents_ = [
{event: 'AdVideoStart', value: 0},
{event: 'AdVideoFirstQuartile', value: 25},
{event: 'AdVideoMidpoint', value: 50},
{event: 'AdVideoThirdQuartile', value: 75},
{event: 'AdVideoComplete', value: 100}
];
/**
* @type {number} An index into what quartile was last reported.
* @private
*/
this.nextQuartileIndex_ = 0;
/**
* Parameters passed in from the AdParameters section of the VAST.
* Used for video URL and MIME type.
*
* @type {!object}
* @private
*/
this.parameters_ = {};
};
/**
* Returns the supported VPAID version.
* @param {string} version
* @return {string}
*/
VpaidVideoPlayer.prototype.handshakeVersion = function(version) {
return ('2.0');
};
/**
* Initializes all attributes in the ad. The ad will not start until startAd is\
* called.
*
* @param {number} width The ad width.
* @param {number} height The ad height.
* @param {string} viewMode The ad view mode.
* @param {number} desiredBitrate The desired bitrate.
* @param {Object} creativeData Data associated with the creative.
* @param {Object} environmentVars Runtime variables associated with the
* creative like the slot and video slot.
*/
VpaidVideoPlayer.prototype.initAd = function(
width,
height,
viewMode,
desiredBitrate,
creativeData,
environmentVars) {
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.attributes_['desiredBitrate'] = desiredBitrate;
// slot and videoSlot are passed as part of the environmentVars
this.slot_ = environmentVars.slot;
this.videoSlot_ = environmentVars.videoSlot;
// Parse the incoming ad parameters.
this.parameters_ = JSON.parse(creativeData['AdParameters']);
this.log('initAd ' + width + 'x' + height +
' ' + viewMode + ' ' + desiredBitrate);
this.updateVideoSlot_();
this.videoSlot_.addEventListener(
'timeupdate',
this.timeUpdateHandler_.bind(this),
false);
this.videoSlot_.addEventListener(
'loadedmetadata',
this.loadedMetadata_.bind(this),
false);
this.videoSlot_.addEventListener(
'ended',
this.stopAd.bind(this),
false);
/* START IAS Integration-Related Code */
// init VANS
this.fwVansInstance_ = __IASVANS();
var adNode = this._slot;
// Open Web monitoring
var fwConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
advEntityId: 'YOUR-IAS-PROVIDED-ADV-ENTITY-ID',
pubEntityId: 'YOUR-IAS-PROVIDED-PUB-ENTITY-ID',
impId: 'PROVIDE-YOUR-OWN-IMPRESSION-ID',
onMeasurementComplete: this.stopAd.bind(this),
debug: {
enabled: false, // should be false by default
monDomain: '' // only used in debugging; IAS will advise on usage
}
};
// no need for blocking callback because of Open Web monitoring
this.fwVansInstance_.initFW(config, adNode);
/* END IAS Integration-Related Code */
this.callEvent_('AdLoaded');
};
/**
* Called by the video element when video metadata is loaded.
* @private
*/
VpaidVideoPlayer.prototype.loadedMetadata_ = function() {
// The ad duration is not known until the media metadata is loaded.
// Then, update the player with the duration change.
this.attributes_['duration'] = this.videoSlot_.duration;
this.callEvent_('AdDurationChange');
};
/**
* Called by the video element when the video reaches specific points during
* playback.
* @private
*/
VpaidVideoPlayer.prototype.timeUpdateHandler_ = function() {
if (this.nextQuartileIndex_ >= this.quartileEvents_.length) {
return;
}
var percentPlayed =
this.videoSlot_.currentTime * 100.0 / this.videoSlot_.duration;
if (percentPlayed >= this.quartileEvents_[this.nextQuartileIndex_].value) {
var lastQuartileEvent = this.quartileEvents_[this.nextQuartileIndex_].event;
this.eventsCallbacks_[lastQuartileEvent]();
this.nextQuartileIndex_ += 1;
}
if (this.videoSlot_.duration > 0) {
this.attributes_['remainingTime'] =
this.videoSlot_.duration - this.videoSlot_.currentTime;
}
};
/**
* Creates or updates the video slot and fills it with a supported video.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoSlot_ = function() {
if (this.videoSlot_ == null) {
this.videoSlot_ = document.createElement('video');
this.log('Warning: No video element passed to ad, creating element.');
this.slot_.appendChild(this.videoSlot_);
}
this.updateVideoPlayerSize_();
var foundSource = false;
var videos = this.parameters_.videos || [];
for (var i = 0; i < videos.length; i++) {
// Choose the first video with a supported mimetype.
if (this.videoSlot_.canPlayType(videos[i].mimetype) != '') {
this.videoSlot_.setAttribute('src', videos[i].url);
foundSource = true;
break;
}
}
if (!foundSource) {
// Unable to find a source video.
this.callEvent_('AdError');
}
};
/**
* Helper function to update the size of the video player.
* @private
*/
VpaidVideoPlayer.prototype.updateVideoPlayerSize_ = function() {
this.videoSlot_.setAttribute('width', this.attributes_['width']);
this.videoSlot_.setAttribute('height', this.attributes_['height']);
};
/**
* Called by the wrapper to start the ad.
*/
VpaidVideoPlayer.prototype.startAd = function() {
this.log('Starting ad');
this.videoSlot_.play();
this.callEvent_('AdStarted');
this.callEvent_('AdImpression'); // this implementation has AdImpression on video start
};
/**
* Called by the wrapper to stop the ad.
*/
VpaidVideoPlayer.prototype.stopAd = function() {
this.log('Stopping ad');
// Calling AdStopped immediately terminates the ad. Setting a timeout allows
// events to go through.
var callback = this.callEvent_.bind(this);
/* START IAS Integration-Related Code */
// This VPAID ad implementation assumes that stopAd is the only method call that results in ad context being destroyed.
setTimeout(callback, 50, ['AdStopped']);
/* END IAS Integration-Related Code */
};
/**
* Called when the video player changes the width/height of the container.
*
* @param {number} width The new width.
* @param {number} height A new height.
* @param {string} viewMode A new view mode.
*/
VpaidVideoPlayer.prototype.resizeAd = function(width, height, viewMode) {
this.log('resizeAd ' + width + 'x' + height + ' ' + viewMode);
this.attributes_['width'] = width;
this.attributes_['height'] = height;
this.attributes_['viewMode'] = viewMode;
this.updateVideoPlayerSize_();
this.callEvent_('AdSizeChange');
};
/**
* Pauses the ad.
*/
VpaidVideoPlayer.prototype.pauseAd = function() {
this.log('pauseAd');
this.videoSlot_.pause();
this.callEvent_('AdPaused');
};
/**
* Resumes the ad.
*/
VpaidVideoPlayer.prototype.resumeAd = function() {
this.log('resumeAd');
this.videoSlot_.play();
this.callEvent_('AdPlaying');
};
/**
* Expands the ad.
*/
VpaidVideoPlayer.prototype.expandAd = function() {
this.log('expandAd');
this.attributes_['expanded'] = true;
this.callEvent_('AdExpanded');
};
/**
* Collapses the ad.
*/
VpaidVideoPlayer.prototype.collapseAd = function() {
this.log('collapseAd');
this.attributes_['expanded'] = false;
};
/**
* Skips the ad.
*/
VpaidVideoPlayer.prototype.skipAd = function() {
this.log('skipAd');
var skippableState = this.attributes_['skippableState'];
if (skippableState) {
this.callEvent_('AdSkipped');
}
};
/**
* Registers a callback for an event.
*
* @param {Function} aCallback The callback function.
* @param {string} eventName The callback type.
* @param {Object} aContext The context for the callback.
*/
VpaidVideoPlayer.prototype.subscribe = function(
aCallback,
eventName,
aContext) {
this.log('Subscribe ' + eventName);
var callBack = aCallback.bind(aContext);
this.eventsCallbacks_[eventName] = callBack;
};
/**
* Removes a callback based on the eventName.
*
* @param {string} eventName The callback type.
*/
VpaidVideoPlayer.prototype.unsubscribe = function(eventName) {
this.log('unsubscribe ' + eventName);
this.eventsCallbacks_[eventName] = null;
};
/**
* Returns whether the ad is linear.
*
* @return {boolean} True if the ad is a linear, false for non linear.
*/
VpaidVideoPlayer.prototype.getAdLinear = function() {
return this.attributes_['linear'];
};
/**
* Returns ad width.
*
* @return {number} The ad width.
*/
VpaidVideoPlayer.prototype.getAdWidth = function() {
return this.attributes_['width'];
};
/**
* Returns ad height.
*
* @return {number} The ad height.
*/
VpaidVideoPlayer.prototype.getAdHeight = function() {
return this.attributes_['height'];
};
/**
* Returns true if the ad is expanded.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdExpanded = function() {
this.log('getAdExpanded');
return this.attributes_['expanded'];
};
/**
* Returns the skippable state of the ad.
*
* @return {boolean}
*/
VpaidVideoPlayer.prototype.getAdSkippableState = function() {
this.log('getAdSkippableState');
return this.attributes_['skippableState'];
};
/**
* Returns the remaining ad time, in seconds.
*
* @return {number} The time remaining in the ad.
*/
VpaidVideoPlayer.prototype.getAdRemainingTime = function() {
return this.attributes_['remainingTime'];
};
/**
* Returns the duration of the ad, in seconds.
*
* @return {number} The duration of the ad.
*/
VpaidVideoPlayer.prototype.getAdDuration = function() {
return this.attributes_['duration'];
};
/**
* Returns the ad volume.
*
* @return {number} The volume of the ad.
*/
VpaidVideoPlayer.prototype.getAdVolume = function() {
this.log('getAdVolume');
return this.attributes_['volume'];
};
/**
* Sets the ad volume.
*
* @param {number} value The volume in percentage.
*/
VpaidVideoPlayer.prototype.setAdVolume = function(value) {
this.attributes_['volume'] = value;
this.log('setAdVolume ' + value);
this.callEvent_('AdVolumeChange');
};
/**
* Returns a list of companion ads for the ad.
*
* @return {string} List of companions in VAST XML.
*/
VpaidVideoPlayer.prototype.getAdCompanions = function() {
return this.attributes_['companions'];
};
/**
* Returns a list of icons.
*
* @return {string} A list of icons.
*/
VpaidVideoPlayer.prototype.getAdIcons = function() {
return this.attributes_['icons'];
};
/**
* Logs events and messages.
*
* @param {string} message
*/
VpaidVideoPlayer.prototype.log = function(message) {
console.log(message);
};
/**
* Calls an event if there is a callback.
*
* @param {string} eventType
* @private
*/
VpaidVideoPlayer.prototype.callEvent_ = function(eventType) {
/* START IAS Integration-Related Code */
// Send data to IAS
if (this.fwVansInstance_) {
var vansEventName,
adContext = {
ad_duration: this.getAdDuration(),
width: this.getAdWidth(),
height: this.getAdHeight(),
volume: this.getAdVolume()
};
if (eventType === 'AdSizeChange') {
// add viewMode when it is necessary for context
adContext.viewMode = this.attributes_['viewMode'];
}
// remap name of event sent to IAS when needed
if (['AdSizeChange', 'AdExpanded', 'AdUserMinimize'].indexOf(eventType) > 0) { // no adUserMinimize in this implementation of VPAID
vansEventName = 'resizeAd';
} else {
vansEventName = eventType;
}
this.fwVansInstance_.sendEvent(vansEventName, adContext);
}
if (eventType in this.eventsCallbacks_) {
// send data to player, optionally with timeout
if (eventType === 'AdStopped' || eventType === 'AdSkipped' || 'AdError') {
setTimeout(this.eventsCallbacks_[eventType].bind(this), 500);
} else {
this.eventsCallbacks_[eventType]();
}
}
/* END IAS Integration-Related Code */
};
/**
* Main function called by wrapper to get the VPAID ad.
*
* @return {Object} The VPAID compliant ad.
*/
var getVPAIDAd = function() {
return new VpaidVideoPlayer();
};
integral1.sendEvent('resizeAd', {
'ad_duration': 30,
'volume': 1,
'viewMode': 'normal',
});
Example of initializing the Web Video SDK in Campaign Monitoring mode in the context of a VPAID Ad Unit integration, with diagnostic monitoring enabled.
// Example of initializing the Web Video SDK in Campaign Monitoring mode in the context of a VPAID Ad Unit integration, with diagnostic monitoring enabled
// init VANS
this.cmVansInstance_ = __IASVANS();
var adNode = this.environmentVars.slot;
// advertiser
var cmConfig = {
partner: 'YOUR-IAS-PROVIDED-PARTNER-CODE',
anId: 'YOUR-IAS-PROVIDED-AD-NETWORK-ID',
advId: 'PROVIDE-YOUR-OWN-ADV-ID',
campId: 'PROVIDE-YOUR-OWN-CAMP-ID',
creativeId: 'PROVIDE-YOUR-OWN-CREATIVE-ID',
placementId: 'PROVIDE-YOUR-OWN-PLACEMENT-ID',
chanId: 'PROVIDE-YOUR-OWN-CHANNEL-ID',
impId: 'PROVIDE-YOUR-OWN-IMPRESSION-ID',
onMeasurementComplete: this.stopAd.bind(this),
debug: {
enabled: true, // enables IAS diagnostic monitoring framework
monDomain: 'your-impression-domain.com' // should not be used, unless diagnostic pixels to IAS's domain are being blocked and we need to send the pixels to the (non-blocked) impression domain.
}
};
this.cmVansInstance_.initCM(config, adNode);
Example Blocking Implementation, including how to correctly set params to be passed with AdImpression
event.
// Example Blocking Implementation, including how to correctly set params to be passed with `AdImpression` event
var initWebVideoSDK = function(config, adNode) {
var fwInstance = new __IASVANS(),
blockingResponseReturnedOnTime;
var block = function (result) {
// set the time to decision inside the blocking callback
var integral_timeToDecision = new Date().valueOf() - blockingTimeoutStart;
if (result === 'block') {
blockingResponseReturnedOnTime = true;
fwInstance.sendEvent('AdImpression', {
integral_timeToDecision: integral_timeToDecision,
integral_didBlock: true,
/* other ad data */
});
myVPAIDAdUnit.blockAd(); // throws AdError after a 500ms timeout
} else {
blockingResponseReturnedOnTime = true;
// example is simplified and glosses over AdLoaded/AdStarted. Whenever you send the AdImpression event, ensure you add integral_timeToDecision and integral_didBlock
fwInstance.sendEvent('AdImpression', {
integral_timeToDecision: integral_timeToDecision,
integral_didBlock: false,
/* other ad data */
});
myVPAIDAdUnit.playAd(); // sends AdImpression to player
}
};
var blockingTimeoutStart = new Date().valueOf();
fwInstance.initFW(config, adNode, block);
setTimeout(function() {
if (!blockingResponseReturnedOnTime) {
fwInstance.sendEvent('AdImpression', {
integral_timeToDecision: new Date().getTime() - blockingTimeoutStart,
integral_didBlock: false,
/* other ad data */
});
myVPAIDAdUnit.playAd(); // sends AdImpression to player
}
});
}
Example of measuring a single ad with a Campaign Monitoring instance of the Web Video SDK.
// Example of measuring a single ad with a Campaign Monitoring instance of the Web Video SDK:
// CORRECT
// create the instance
var cmInstance = new __IASVANS();
// initialize Campaign Monitoring ad session
cmInstance.initCM(/*arguments*/);
// as events come in from your SDK, send them
cmInstance.sendEvent(/*arguments*/);
// Example of measuring a single ad with both Campaign Monitoring and Open Web instances of the Web Video SDK:
// CORRECT
// instantiate the constructor twice and call one init on each instance
var cmInstance = __IASVANS();
cmInstance.initCM(/* arguments */);
var fwInstance = __IASVANS();
fwInstance.initFW(/* arguments */);
// INCORRECT
var firstVANS = __IASVANS();
// erroneously calls both initCM and initFW on the same instance
var myCMInstance = firstVANS.initCM();
var myFWInstance = firstVANS.initFW();
Example of how to measure multiple ads with a Campaign Monitoring instance of the Web Video SDK.
// Example of how to measure multiple ads with a Campaign Monitoring instance of the Web Video SDK.
// CORRECT
// instantiate for first ad
var cmInstance = new __IASVANS();
// initialize Campaign Monitoring ad session
cmInstance.initCM(/*arguments*/);
// as events come in from your SDK, send them
cmInstance.sendEvent(/*arguments*/);
// first ad finishes playing
cmInstance.sendEvent('AdStopped', /* eventData */);
// create a new instance for the next ad
cmInstance = new __IASVANS();
// initialize a new CM ad session
cmInstance.initCM(/*arguments*/);
// measure the second ad
cmInstance.sendEvent(/*arguments*/);
// INCORRECT
var cmInstance = new __IASVANS();
cmInstance.initCM(/*arguments*/);
cmInstance.sendEvent(/*arguments*/);
// initializes second CM ad session on the first ad's Web Video SDK instance. This is wrong
cmInstance.initCM(/*arguments*/);
Example of passing onMeasurementComplete callback to a Campaign Monitoring instance of the Web Video SDK in the context of a VPAID integration.
// Example of passing onMeasurementComplete callback to a Campaign Monitoring instance of the Web Video SDK in the context of a VPAID integration
// Get reference to HTML Element
var adNode = document.getElementById('my-video');
// Instantiate Web Video SDK
var cmInstance = new __IASVANS();
// Create a configuration
var config = {
partner: 'Gold Street Media',
anId: '12345',
advId: '6789',
campId: '3',
creativeId: '98765',
placementId: '5',
chanId: '6',
impId: '76131e76e17e',
onMeasurementComplete: myVPAIDAdUnit.dispose // sends AdStopped to the player, resulting in ad destruction. See also timeout below
};
// Initialize Web Video SDK as CM
cmInstance.initCM(config, adNode);
// Send events
cmInstance.sendEvent('AdVideoMidpoint', {
volume: 1,
ad_duration: 30
// ...
});
// Ad end
// your VPAID (a snippet)
myVPAIDAdUnit.stopAd = function() {
// send Web Video SDK event first
cmInstance.sendEvent('AdStopped', {
volume: 1,
ad_duration: 30,
// ...
});
// then start the timeout
var timeoutToPreventAdEndEventsLoss = setTimeout(this.dispose.bind(this), 750);
};
// under the hood:
// 1. Web Video SDK receives AdStopped event
// 2a. Web Video SDK Listener completes asynchronous data transfer to server
// 3a. myVPAIDAdUnit.dispose is called by Web Video SDK
// OR
// 2b. Web Video SDK fails to invoke the onMeasurementComplete callback within the allotted timeout (could be due to latency, or other errors)
// 3b. myVPAIDAdUnit.dispose is called at the end of timeoutToPreventAdEndEventsLoss
Example of a Wrapper function that synchronizes the callbacks to ensure VPAID.stopAd is invoked only once, after both Web Video SDK instances’ measurement has completed.
// Example: Wrapper function that synchronizes the callbacks to ensure VPAID.stopAd is invoked only once, after both Web Video SDK instances’ measurement has completed
// Wrapper function
var synchronizedMeasurementComplete = function(cbf){
var count = 0;
return function() {
count++;
if(count === 2) {
cbf();
}
}
};
// Usage
var measurementCompleteCalledOnlyOnce = synchronizedMeasurementComplete(VPAID.stopAd);
// instead of the original ad-unload callback function, the wrapped function is passed to both instances’ init:
// cm config
var config = {
/* ... */
onMeasurementComplete: measurementCompleteCalledOnlyOnce
};
// Open Web config
var config = {
/* ... */
onMeasurementComplete: measurementCompleteCalledOnlyOnce
};
var firstInstance = new __IASVANS();
firstInstance.initCM(config);
var secondInstance = new __IASVANS();
secondInstance.initFW(config);
Example of sending an AdImpression event in a blocking Open Web integration, where integral
is an instance of the Web Video SDK.
// Example of sending an AdImpression event in a blocking Open Web integration, where `integral` is an instance of the Web Video SDK:
integral.sendEvent('AdImpression', {
'ad_duration': 30,
'height': '400',
'width': '600',
'volume': 1,
'integral_didBlock': false, // you did not block the ad
'integral_timeToDecision': 450
});
Example of sending an AdVolumeChange event, where integral is a Web Video SDK Open Web or Campaign Monitoring instance.
// Example of sending an AdVolumeChange event, where integral is a Web Video SDK Open Web or Campaign Monitoring instance:
integral.sendEvent('AdVolumeChange', {
volume: 1,
ad_duration: 30,
width: 300,
height: 250,
viewMode: 'normal'
});
Example of sending a resizeAd event, where integral
is an instance of the Web Video SDK.
// Example of sending a resizeAd event, where `integral` is an instance of the Web Video SDK:
integral.sendEvent('resizeAd', {
'ad_duration': 30,
'volume': 1,
'viewMode': 'normal',
'height': 324,
'width': 400
});
Create an IAS case with details of your inquiry to receive help from our internal support team.