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 versions | 2.0–4.3 via videojs-ima; 2.0–3.0 via contrib-ads |
| VPAID | 2.0 JS on desktop web (via videojs-ima). Not on mobile. |
| Wrapper chain limit | 4 hops (videojs-ima / IMA SDK limit) |
| Media formats | MP4 H.264, WebM VP8/VP9, HLS (browser-dependent) |
| HTTPS | Required (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-imaIn 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:
| Option | Type | Description |
|---|---|---|
adTagUrl | string | URL returning a VAST, VMAP, or ad rules response. Overrides adsResponse. |
numRedirects | number | Maximum VAST wrapper redirects before the ad load is aborted. Directly affects latency. Default: IMA SDK default (4). |
vpaidMode | VpaidMode | VPAID mode. Defaults to ENABLED. Set to DISABLED or INSECURE as needed. Overrides the deprecated vpaidAllowed. |
vastLoadTimeout | number | Override for default VAST load timeout in milliseconds per wrapper hop. Default: 5000 ms. |
showCountdown | boolean | Whether to show the ad countdown timer. Defaults to true. |
autoPlayAdBreaks | boolean | Whether to automatically play VMAP or ad rules ad breaks. Defaults to true. Set to false for manual control. |
disableAdControls | boolean | Hide the play/pause, volume, and fullscreen controls during ad playback. Defaults to false. |
omidVendorAccess | object | Enables the Open Measurement SDK. Keys are OMID vendor enum values; values are OMID access mode. |
ppid | string | Publisher-provided ID for frequency capping and audience targeting. |
sessionId | string | IMA session ID for deduplication and debugging. |
locale | string | Locale for ad UI localization (e.g. en, de). |
adsRenderingSettings | object | IMA 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).
| Event | Event string | Payload |
|---|---|---|
| Ad Started | ads-ad-started | none |
| Ads Manager | ads-manager | google.ima.AdsManager |
| Ads Loader | ads-loader | google.ima.AdsLoader |
| Ads Request | ads-request | google.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:
- Set
autoPlayAdBreaks: falsein the plugin options. - Provide a listener via
player.ima.setAdBreakReadyListener(callback). - 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
| Plugin | VAST engine | VAST versions | VPAID |
|---|---|---|---|
videojs-ima | Google IMA SDK | 2.0–4.3 | Desktop web only |
videojs-contrib-ads + custom client | Varies | Usually 2.0–3.0 | Depends 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-imaorcontrib-ads - Include MP4 H.264 fallback if using VPAID
- All URLs use HTTPS
- Wrapper chain ≤ 4 hops (set
numRedirectsto cap at a lower value) - MP4 H.264
<MediaFile>at multiple bitrates <Duration>inHH:MM:SSformat<Impression>with HTTPS URL presentversionattribute on root<VAST>element- On mobile: call
player.ima.initializeAdDisplayContainer()from a user gesture - For VMAP: use
output=xml_vmap1in the GAM tag URL