VPAID has been deprecated since VAST 4.1. There will not be a VPAID 3.0. It cannot execute in server-side ad insertion, it cannot execute on connected TV, and the IAB has published two separate replacement standards for the two things it used to do.
None of that stops it from being in your tags. Deprecation is a statement about a specification. It has no effect on the XML your ad server emitted this morning.
So the useful question is not "should we move off VPAID," which was settled years ago. It is "how much of it are we still serving, and where is it costing us fill." That is answerable in an afternoon.
Why it stopped working, briefly
Four independent reasons, and they compound:
It runs in your page's JavaScript context. A VPAID unit has full access to the publisher's DOM, cookies and globals. That is not a sandbox with holes, it is the absence of a sandbox, and it was routinely used for exactly what you would expect.
SSAI has no JavaScript runtime. Server-side ad insertion stitches the ad into the media stream at the server. There is no browser there. VPAID cannot run in principle, not as an implementation gap.
CTV has no browser-compatible JavaScript runtime either. Smart TVs, sticks and set-top boxes use native media players. VPAID is not slow on CTV, it is non-executable. And CTV is where premium video budget went.
It costs latency on every impression that does work. Because the VPAID script controls media loading, the player cannot pre-cache the video. Every impression waits for the unit to initialise before anything can buffer.
The replacements split the job. SIMID handles interactivity in a sandboxed iframe talking over postMessage, so the player keeps control of the media. OMID handles verification and viewability. Neither one needs access to your page.
The four signatures
VPAID does not announce itself in one place, which is why audits miss it. There are four distinct patterns, and a tag can match some without the others.
1. The explicit declaration
<MediaFile delivery="progressive" type="application/javascript"
apiFramework="VPAID" width="640" height="360">
<![CDATA[https://cdn.example.com/vpaid-unit.js]]>
</MediaFile>
apiFramework="VPAID" is the honest case. Easy to grep, easy to count.
2. The JavaScript media file with no apiFramework
<MediaFile delivery="progressive" type="application/javascript">
<![CDATA[https://cdn.example.com/unit.js]]>
</MediaFile>
A <MediaFile> whose type is application/javascript or application/x-javascript is a script, not a video, whatever it declares. Some ad servers omit apiFramework here, and a search that only looks for the string "VPAID" will miss every one of them.
Same for application/x-shockwave-flash, which you will still find in long-tail inventory and which has been unplayable in every browser since 2021.
3. VPAID sitting next to its own replacement
<MediaFiles>
<MediaFile type="application/javascript" apiFramework="VPAID">...</MediaFile>
<MediaFile type="video/mp4">...</MediaFile>
<InteractiveCreativeFile type="text/html" apiFramework="SIMID">...</InteractiveCreativeFile>
</MediaFiles>
This is the most common shape in tags that have been half-migrated. Both the old and new interactive paths are present. On a player that supports SIMID it works fine. On one that prefers VPAID you are back to the original problem, and on CTV the VPAID entry is dead weight that some stitchers reject the whole tag over.
4. AdParameters with no interactive file
<AdParameters> exists to pass configuration into an interactive unit. A tag with <AdParameters> and no <InteractiveCreativeFile> is almost always feeding a VPAID creative, even if nothing else in the document says so.
Counting it
Grep gets you the first pass over a corpus of saved tags:
$ grep -rlE 'apiFramework="VPAID"|application/(x-)?javascript|x-shockwave-flash' tags/ | wc -l
That undercounts signature 4 and overcounts anything that mentions those strings in a tracking URL, so for a real number use a validator that understands the document structure. Running the half-migrated example above through vastlint:
$ vastlint check vpaid.xml
vpaid.xml VAST 4.2
warning apiFramework="VPAID" is deprecated as of VAST 4.1, use SIMID or OMID instead
VAST-4.1-vpaid-apiframework
/VAST/Ad[0]/InLine/Creatives/Creative[0]/Linear/MediaFiles/MediaFile[0]:20:15
warning <MediaFile apiFramework="VPAID"> alongside <InteractiveCreativeFile>, VPAID is not
supported in CTV and should be removed when SIMID/OMID is present
VAST-4.1-vpaid-in-interactive-context
/VAST/Ad[0]/InLine/Creatives/Creative[0]/Linear/MediaFiles/MediaFile[0]:20:15
✓ 0 errors, 2 warnings, 1 info
Note that both are warnings, not errors. A VPAID tag is still perfectly valid VAST. The schema has no opinion about deprecation, which is exactly why this survives in inventory: nothing in the validation path fails, so nothing forces the cleanup.
Over a directory, with JSON out so you can count by rule:
$ vastlint check --format json tags/*.xml \
| jq -r '.issues[].id' | sort | uniq -c | sort -rn
2 VAST-4.1-vpaid-in-interactive-context
2 VAST-4.1-vpaid-apiframework
2 VAST-4.1-mezzanine-recommended
(JSON mode emits one object per file, so jq reads it as a stream rather than an array.)
Install with cargo install vastlint, brew install aleksUIX/tap/vastlint, or a pre-built binary from the releases page. There is a WASM build on npm as vastlint if you would rather call it from Node than shell out.
What each signature costs
Not all of these are equally urgent, and treating them as one bucket is how audits stall.
| Signature | CTV | SSAI | Desktop web | Priority |
|---|---|---|---|---|
| VPAID with no video fallback | No fill | No fill | Plays | Fix now |
| VPAID alongside an MP4 | Falls back | Falls back | Plays VPAID | Fix soon |
| VPAID next to SIMID | Depends on player | Falls back | Ambiguous | Remove the VPAID entry |
| Flash media file | No fill | No fill | No fill | Delete |
The first row is the one that is actually costing money right now. A creative whose only rendition is a VPAID script gets zero fill on the majority of premium video inventory, and because it is a no-bid rather than an error, it shows up in your reporting as absence rather than failure.
The third row is the cheapest fix in the table: the SIMID path already exists, so removing the VPAID <MediaFile> is a deletion, not a migration.
Doing the migration
The full path is documented here, and the VPAID reference has the version history and the compatibility matrix by VAST version. Compressed:
- Interactivity moves to
<InteractiveCreativeFile apiFramework="SIMID">. - Verification and viewability move to
<AdVerifications>with OMID. - Anything you were tracking from inside the VPAID unit moves to
<TrackingEvents>, which the player fires and which works in SSAI. - Every creative gets a real video
<MediaFile>, so there is always something to play. - Declare the VAST version you are actually emitting.
Step 4 is the one to do first if you do nothing else. A native rendition alongside the VPAID unit turns a zero-fill creative into one that at least serves as video everywhere, and it does not require touching the interactive build at all.
The honest summary
VPAID is not going to stop working on a particular date. It stopped working in the environments that matter, gradually, over several years, and it will keep half-working on desktop web indefinitely. That is worse than a hard cutoff, because there is never a day when the problem becomes visible.
The signal to watch is not an error rate. It is fill on CTV and SSAI inventory for creatives that carry a script where a video should be. Count those first.
Top comments (0)