vastlint

VAST XML for Video.js

Video.js is a popular open-source HTML5 video player. Video.js itself does not parse VAST — ad support is added via plugins. The two most common integrations are videojs-ima (which wraps the Google IMA SDK) and videojs-contrib-ads (a lower-level ad framework that pairs with custom VAST clients). Your VAST requirements depend on which plugin is in use.

Quick reference

VAST versions2.0–4.3 via videojs-ima; 2.0–3.0 via contrib-ads
VPAID2.0 JS on desktop web (via videojs-ima). Not on mobile.
Wrapper chain limit4 hops (videojs-ima / IMA SDK limit)
Media formatsMP4 H.264, WebM VP8/VP9, HLS (browser-dependent)
HTTPSRequired (browser mixed-content blocking)

Installation and setup

The recommended way to use videojs-ima is via npm. Both videojs-contrib-ads and videojs-ima are needed.

npm install videojs-ima

In your JavaScript entry point, import both packages and configure the plugin:

import videojs from 'video.js';
import 'videojs-contrib-ads';
import 'videojs-ima';

const player = videojs('content_video', {
  controls: true,
  sources: [{ src: 'https://example.com/video.mp4', type: 'video/mp4' }],
});

player.ima({
  adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?...',
});

// On mobile devices, initializeAdDisplayContainer must be called as
// the result of a user action (e.g. a button click).
// player.ima.initializeAdDisplayContainer();

Your HTML needs the IMA SDK script loaded before the player script, and a <video>element as the playback target:

<link rel="stylesheet" href="https://vjs.zencdn.net/8.3.0/video-js.css" />
<video id="content_video" class="video-js vjs-default-skin" controls>
  <source src="https://example.com/video.mp4" type="video/mp4" />
</video>
<script src="//imasdk.googleapis.com/js/sdkloader/ima3.js"></script>

Plugin options

The player.ima() call accepts an options object. Key options:

OptionTypeDescription
adTagUrlstringURL returning a VAST, VMAP, or ad rules response. Overrides adsResponse.
numRedirectsnumberMaximum VAST wrapper redirects before the ad load is aborted. Directly affects latency. Default: IMA SDK default (4).
vpaidModeVpaidModeVPAID mode. Defaults to ENABLED. Set to DISABLED or INSECURE as needed. Overrides the deprecated vpaidAllowed.
vastLoadTimeoutnumberOverride for default VAST load timeout in milliseconds per wrapper hop. Default: 5000 ms.
showCountdownbooleanWhether to show the ad countdown timer. Defaults to true.
autoPlayAdBreaksbooleanWhether to automatically play VMAP or ad rules ad breaks. Defaults to true. Set to false for manual control.
disableAdControlsbooleanHide the play/pause, volume, and fullscreen controls during ad playback. Defaults to false.
omidVendorAccessobjectEnables the Open Measurement SDK. Keys are OMID vendor enum values; values are OMID access mode.
ppidstringPublisher-provided ID for frequency capping and audience targeting.
sessionIdstringIMA session ID for deduplication and debugging.
localestringLocale for ad UI localization (e.g. en, de).
adsRenderingSettingsobjectIMA AdsRenderingSettings JSON object for fine-grained rendering control.

Ad events

The videojs-ima plugin emits the following events on the Video.js player instance. Listen with player.on(eventName, handler).

EventEvent stringPayload
Ad Startedads-ad-startednone
Ads Managerads-managergoogle.ima.AdsManager
Ads Loaderads-loadergoogle.ima.AdsLoader
Ads Requestads-requestgoogle.ima.AdsRequest
player.on('ads-manager', function(response) {
  const adsManager = response.adsManager;
  // Access the IMA AdsManager directly for advanced use
});

player.on('ads-ad-started', function() {
  // Ad started playing
});

Manual ad break control

By default, videojs-ima plays VMAP / ad rules breaks automatically. In some cases (e.g. custom ad scheduling, deferred playback) you may want to control when breaks play:

  1. Set autoPlayAdBreaks: false in the plugin options.
  2. Provide a listener via player.ima.setAdBreakReadyListener(callback).
  3. Call player.ima.playAdBreak() inside the listener when ready.
player.ima({
  adTagUrl: 'YOUR_VMAP_TAG',
  autoPlayAdBreaks: false,
});

player.ima.setAdBreakReadyListener(function() {
  // Called when an ad break is ready to play.
  // Do any pre-break logic here, then:
  player.ima.playAdBreak();
});

videojs-ima vs videojs-contrib-ads

PluginVAST engineVAST versionsVPAID
videojs-imaGoogle IMA SDK2.0–4.3Desktop web only
videojs-contrib-ads + custom clientVariesUsually 2.0–3.0Depends on client

If you don't know which plugin a publisher uses, target VAST 3.0 with MP4 H.264 only and no VPAID to ensure compatibility with both paths.

VPAID

When using videojs-ima, VPAID 2.0 JavaScript is supported on desktop web. It is not supported on mobile browsers (Chrome for Android, Safari for iOS), because IMA SDK blocks VPAID on mobile. Always include a non-VPAID MP4 fallback.

→ vastlint rule: VAST-4.1-vpaid-in-interactive-context

Media files

Video.js uses the browser's native video capabilities. MP4 H.264 is supported in all major browsers. WebM VP8/VP9 is supported in Chrome and Firefox. HLS requires either a native browser implementation (Safari) or an MSE-based library like hls.js.

<MediaFiles>
  <MediaFile type="video/mp4" width="1920" height="1080"
             bitrate="4500" delivery="progressive">
    <![CDATA[https://cdn.example.com/ad-1080p.mp4]]>
  </MediaFile>
  <MediaFile type="video/webm" width="1920" height="1080"
             bitrate="3500" delivery="progressive">
    <![CDATA[https://cdn.example.com/ad-1080p.webm]]>
  </MediaFile>
  <MediaFile type="video/mp4" width="1280" height="720"
             bitrate="1500" delivery="progressive">
    <![CDATA[https://cdn.example.com/ad-720p.mp4]]>
  </MediaFile>
</MediaFiles>

HTTPS and mixed-content

Video.js runs in a browser — all browser mixed-content rules apply. If the page is served over HTTPS (which it should be), all VAST URLs must also use HTTPS. HTTP media files, impression pixels, and tracking URLs will be blocked by the browser before Video.js can load them.

Duration format

Both videojs-ima and most contrib-ads VAST clients require <Duration> in HH:MM:SS format. Bare integers will cause parsing failures or incorrect ad countdown timers.

→ vastlint rule: VAST-2.0-duration-format

Skippable ads

Skippable ads are supported via skipoffset on <Linear>when using videojs-ima (IMA SDK renders the skip button). With contrib-ads, skip support depends on the publisher's implementation.

Pre-flight checklist for Video.js

  • Confirm whether the publisher uses videojs-ima or contrib-ads
  • Include MP4 H.264 fallback if using VPAID
  • All URLs use HTTPS
  • Wrapper chain ≤ 4 hops (set numRedirects to cap at a lower value)
  • MP4 H.264 <MediaFile> at multiple bitrates
  • <Duration> in HH:MM:SS format
  • <Impression> with HTTPS URL present
  • version attribute on root <VAST> element
  • On mobile: call player.ima.initializeAdDisplayContainer() from a user gesture
  • For VMAP: use output=xml_vmap1 in the GAM tag URL

References

Validate your tag against all 118 IAB rules →