DEV Community

Aleksander Sekowski
Aleksander Sekowski

Posted on

VPAID Is Deprecated. Here Is How to Find Out How Much You Are Still Serving.

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

(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:

  1. Interactivity moves to <InteractiveCreativeFile apiFramework="SIMID">.
  2. Verification and viewability move to <AdVerifications> with OMID.
  3. Anything you were tracking from inside the VPAID unit moves to <TrackingEvents>, which the player fires and which works in SSAI.
  4. Every creative gets a real video <MediaFile>, so there is always something to play.
  5. 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)