Open-Measurement-SDKJS

OM SDK for Web Video Documentation

This guide goes over how to integrate the OM SDK for Web Video into your website or ads SDK. Throughout this document, the website or ads SDK is referred to as “the integration”, and the organization owning the integration (you, the reader) as “the integrator”.

Support and Compatibility

OM SDK for Web Video supports video ads on desktop and mobile Chrome, Firefox, Safari, and Edge.

Background

For integrators, the OM SDK is two parts:

Both of these will need to be incorporated into the integration as the next sections explain.

Initial Setup

Acquiring the OM SDK

These instructions assume you will be acquiring the minified, production-ready OM SDK from the IAB Tech Lab Tools Portal. However, it is possible to build the OM SDK JS Session Client from source, which may be more flexible depending on your build system. See the GitHub repo for instructions on how to build it from source, which this guide will not cover. The OM SDK Service Script must always be obtained from the IAB Tech Lab.

  1. Navigate to the Open Measurement SDK in the IAB Tech Lab Tools Portal.
  2. Select the ‘Web Video’ tab
  3. Download the latest zip file, labeled omweb-js-${VERSION}
  4. Extract the files at /Service/omweb-v1.js and /Session-Client/omid-session-client-v1.js.
  5. Host these files on the integration’s CDN.

Importing the OM SDK

Service Script

To incorporate omweb-v1.js, use a <script> tag:

<html>
  <head><title>My Website</title></head>
  <body>
    <video id="video-creative-element" />
    <script src="mycdn.example/path/to/omweb-v1.js"></script>
  </body>
</html>

Integrations must not concatenate or compile the Service Script into other scripts. It will not work correctly unless loaded in its own <script> tag.

JS Session Client

Again, if building from source, the JS Session Client can be compiled into your site’s scripts directly, with systems like CommonJS or the Closure Compiler. The following instructions assumed you have acquired omid-session-client-v1.js from the IAB Tech Lab Tools Portal.

To incorporate omid-session-client-v1.js, you can either use a <script> tag:

<html>
  ...
    <script src="mycdn.example/path/to/omweb-v1.js"></script>
    <script src="mycdn.example/path/to/omid-session-client-v1.js"></script>
    <script src="mycdn.example/path/to/my-integration.js"></script>
  </body>
</html>

where my-integration.js is the code we’ll walk through in this guide to call the JS Session Client library and interact with the OM SDK. Alternatively, you can simply concatenate omid-session-client-v1.js to the beginning of my-integration.js.

Make sure that omweb-v1.js is loaded before the integration and JS Session Client for best results.

OM SDK for Web Video and <iframe>

See OM SDK for Web Video and Iframes for guidance on setups involving <iframe> tags. This guidance must be reviewed if you are planning to load the Service Script and/or JS Session Client in a same-origin or cross-origin iframe relative to the top-level integration.

Initializing the OM SDK

The following global will now be available in my-integration.js:

const OmidSessionClient = OmidSessionClient && OmidSessionClient['default'];

Ad Format Implementation Steps

At a high-level, integrators of OM SDK for Web Video will need to do a few things differently than OM SDK for Apps:

The following steps walk through code that would, in this example, be contained in my-integration.js.

Video

1. Obtain the SessionClient Classes

Obtain the SessionClient classes, which you will use to control sessions, signal events, and surface metadata.

let sessionClient;
try {
  sessionClient = OmidSessionClient['default'];
} catch (e) { /* Can't use OM SDK :( */ return; }
if (!sessionClient) { /* Can't use OM SDK :( */ return; }

const AdSession = sessionClient.AdSession;
const Partner = sessionClient.Partner;
const Context = sessionClient.Context;
const VerificationScriptResource = sessionClient.VerificationScriptResource;
const AdEvents = sessionClient.AdEvents;
const MediaEvents = sessionClient.MediaEvents;

2. Identify your Integration

For the content URL, choose a URL that best represents the content of the page where the ad is being run. Make sure to exclude any sensitive or personally identifying information. This will vary based on the page your script and the OM SDK are loaded on.

The IAB Tech Lab will assign a unique partner name to you when registering on the site, so this is the value you should use instead of “ExamplePartnerName”. The version string should represent the integration version in semantic versioning format. For an ads SDK, this should be the same as your SDK’s semantic version. For an app publisher, this should be the same as your app version.

const CONTENT_URL = 'https://example.com/articles/2019/lottery-winner';
const PARTNER_NAME = 'ExamplePartnerName';
const PARTNER_VERSION = '1.0.4';

const partner = new Partner(PARTNER_NAME, PARTNER_VERSION);

3. Create the Context

In this example, the OM SDK Service Script was loaded in the top window, and the integrator has chosen to load verification scripts in full access mode.

const OMSDK_SERVICE_WINDOW = window.top;
const VIDEO_ELEMENT = document.getElementById('video-creative-element');

// Assuming you have an `ad` object roughly following VAST 4.1 schema.
const resources = ad.adVerifications.map((verification) => {
  const scriptUrl = verification.javaScriptResource.cdata;
  const accessMode = 'full';
  return new VerificationScriptResource(scriptUrl, verification.vendor,
      verification.verificationParameters, accessMode);
});

const context = new Context(partner, resources, CONTENT_URL);
context.setVideoElement(VIDEO_ELEMENT);
context.setServiceWindow(OMSDK_SERVICE_WINDOW);

4. Create and Start the AdSession

Starting the session does not trigger an impression yet – it only prepares the service and verification scripts for event tracking. It is important to start the session before dispatching any events.

const adSession = new AdSession(context);
adSession.setCreativeType('video');

// See impression type documentation to determine which type you should use.
adSession.setImpressionType('beginToRender');

if (!adSession.isSupported()) {
  return;
}

adSession.start();

If the ad session was not supported, communication with the service script failed in some way. Inspect the console for any logs or errors.

5. Signal Ad Load Event.

When the media has loaded, signal the load event and pass through the following metadata:

adSession.registerSessionObserver((event) => {
  if (event.type === "sessionStart") {
    // load event
    const isSkippable = ad.creative.linear.skipOffset != null;
    const skipOffset = ad.creative.linear.skipOffset;
    const vastProperties = new VastProperties(isSkippable, skipOffset,
      /* isAutoPlay= */ true, /* position= */ 'preroll');
    adEvents.loaded(vastProperties);
    // other event code
    ...
  } else if (event.type === "sessionError") {
    // handle error
  } else if (event.type === "sessionFinish") {
    // clean up
  }
});

Note that we are dispatching the event within the session observer callback. This is to ensure that we do not dispatch any events until we’ve received session start. You should also check the event type to ensure you handle each event type appropriately.

6. Signal the Impression Event.

When you are ready, signal the impression event using the events object you created in the previous step. For video, an impression is generally accepted to occur when the first frame of the video successfully plays. It should only be dispatched once, and attempting to trigger it multiple times is an error. As noted in the previous step, you must also ensure that you don’t dispatch the impression event until after you’ve received the session start event.

// this should be within the same callback as the load event from the previous step
adSession.registerSessionObserver((event) => {
  if (event.type === "sessionStart") {
    ...
    adEvents.impressionOccurred();
    ...
  } else if (event.type === "sessionError") {
    // handle error
  } else if (event.type === "sessionFinish") {
    // clean up
  }
})

7. Signal Media Events

The example below adds videoDidCrossQuartile. One common way to do this is by adding event listeners to the video element for the timeupdate events that then call this function appropriately. See the Reference App for a complete example on how to do this.

const mediaEvents = new MediaEvents(adSession);

/**
 * Called when the video ad has crossed quartile thresholds during playback.
 * @param {number} quartile The video quartile crossed, where 0 is first frame
 * and 4 is completion.
 */
function videoDidCrossQuartile(quartile) {
  switch (quartile) {
    case 0:
      mediaEvents.start(ad.creative.linear.duration, VIDEO_ELEMENT.volume);
      break;
    case 1:
      mediaEvents.firstQuartile();
      break;
    case 2:
      mediaEvents.midpoint();
      break;
    case 3:
      mediaEvents.thirdQuartile();
      break;
    case 4:
      mediaEvents.complete();
      break;
    default:
      break;
  }
}

Volume events

With respect to volume changes, you are responsible for notifying creative volume changes.

VIDEO_ELEMENT.addEventListener('volumechange', () => {
  mediaEvents.volumeChange(VIDEO_ELEMENT.volume);
});

User interaction

You are also responsible for notifying user interaction when there is click on video to open advertiser landing page.

VIDEO_ELEMENT.addEventListener('click', () => {
  mediaEvents.adUserInteraction(InteractionType.CLICK);
});

State changes

Finally, you are also responsible for signaling any player state changes. If the player can expand to fullscreen as well as exit fullscreen, you will want to signal these state changes as follows:

['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'msfullscreenchange'].forEach((eventType) => {
  VIDEO_ELEMENT.addEventListener(
  eventType, (event) => videoPlayerStateChange(event));
});

function videoPlayerStateChange(event) {
  const state = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullScreen;
  const playerState = state ? VideoPlayerState.FULLSCREEN : VideoPlayerState.NORMAL;
  mediaEvents.playerStateChange(playerState);
}

8. Finish the AdSession

Finish the session when playback has completed or when the ad will be destroyed. Note that after you’ve stopped the session it is an error to attempt to start it again or trigger any other events.

adSession.finish();

9. Repeat and Cleanup

In the case where you have multiple video ads on a single page (e.g a pod of instream video ads), reuse the same service script, but create a new AdSession.

Once all expected ad sessions on the page have finished, it is good practice to reclaim memory by unloading the OM SDK Service Script. If the OM SDK Service Script was loaded in an iframe, you can do this by removing the iframe element and dropping all references to it in script. When doing so, you must wait at least 3 seconds after the last adSession.finish() call. This gives verification scripts the opportunity to make any last HTTP requests before they are destroyed. Not doing so will risk invalid and incomplete measurement.

See the Reference App for a more advanced example of event signaling and service script loading.

Audio ads

The setup for an audio ad is similar to the corresponding video ad, with minor exceptions…

Validation

Validating your integration is an important part of the process. Follow the instructions in Validation.

Further Reading