IAB Tech Lab finalized CTV Ad Portfolio signaling in July 2026 with a blunt operational requirement: SSAI vendors, exchanges, and measurement partners have to carry the same VAST and AdCOM enumerations as client-side players. That is not a cosmetic metadata upgrade. It is an admission that two delivery rails read the same campaign name and not the same creative contract. One rail fetches a tag in the living room. The other pulls a master into a transcode farm before the break airs. When fill drops on CTV but desktop web looks fine, the mismatch is usually between those two payloads, not a mysterious SSP bug.
What SSAI ingest actually consumes
In server-side ad insertion, the ad decision may still start from a VAST URL, but the money moment is transcode and splice. The stitcher wants a mezzanine or a high-bitrate master it can normalize to the publisher's ladder, a Duration that fits the pod slot, HTTPS-delivered media, and often a UniversalAdId block so downstream reconciliation can tie the stitched bytes back to the trafficking row. VPAID and other script-based apiFramework values are dead on arrival: there is no JavaScript runtime in the packager.
That is a different readiness bar than "the IMA SDK played an MP4 in Chrome." A tag can validate against VAST 4.x, expose a single progressive MediaFile, and never include <Mezzanine> at all. Browsers do not need the mezzanine child; many SSAI pipelines treat its absence as a hard reject before the first frame is encoded. The same InLine can also declare a Duration of :30 while the mezzanine asset is :29.97, which passes XML schema checks and still breaks slot math on the stitcher.
Tracking is part of the contract too. SSAI often fires quartile and complete URLs from the packager's clock, not from the player's JavaScript timer. If your QA only watches the client-side VAST response, you may never notice that midpoint or complete beacons were authored for a player that never runs in the SSAI path. The midpoint event doc is a reminder that those URLs are pixels on the wire whether the stitcher or the device fires them.
What CSAI and browser QA actually test
Client-side insertion is the path most trafficking teams know. You paste a VAST URL into a tag tester, the player selects a MediaFile, and someone watches quartiles tick in the network panel. Wrappers get peeled until an InLine appears. Click-through and verification resources load in a real DOM.
That workflow is valuable. It is also incomplete for any inventory that monetizes through SSAI on CTV. The tag the browser resolves may be a wrapper chain whose final InLine is optimized for desktop bitrates. The mezzanine the stitcher needed might live only on an upstream hop your QA never fetched, or never existed because the creative was built for CSAI-only supply. Verification markup can load in a web player while the stitched stream carries no measurable verification resource at all, because the transcode step stripped interactive files the living-room device never executes.
Teams migrating off deprecated APIs feel this split directly. A VPAID migration guide matters because the interactive file that survives browser QA is exactly what SSAI cannot run. Passing validation on the client tag is not evidence the CTV break will accept the creative.
Where the two paths disagree without looking "broken"
Same trafficking ID, two environments, four common divergences:
| Check | CSAI / browser QA | SSAI ingest |
|---|---|---|
| Primary media | First playable MediaFile
|
Mezzanine or approved master |
| Interactive API | VPAID or SIMID may load | Script APIs rejected |
| Duration | Player tolerance | Pod slot and ad server clock |
| Identity | Optional in older tags |
UniversalAdId for reconciliation |
None of these rows fail XML schema by themselves. That is why the problem shows up as silent fill loss on CTV while reporting still shows the creative as "ready."
New portfolio formats make the split sharper. Pause, overlay, and squeezeback buys expect NonLinear VAST shapes and AdCOM placement signals that a linear-only CSAI tag never exercised. Preparing for VAST 4.4 CTV formats is about proving partner acceptance on the path you will actually use, not only proving a desktop wrapper parses. When you QA portfolio NonLinear delivery, the IAB-style VAST tester (an independent fork, not an IAB Tech Lab product) exercises SIMID studio and sample creatives alongside host transport logs.
How you catch it
An LLM or MCP task can emit VAST that looks plausible and still miss mezzanine, duration drift, or HTTPS on the master URL. The wire contract does not move because the tool call returned OK. You still need a deterministic check on the creative the buy claimed.
Start with the live tag URL in the VAST tag tester: fetch, preview, and confirm tracking and media URLs resolve the way a player would. Then run the same entry point through the VAST inspector so wrapper hops surface the InLine the stitcher would see, not just the first response your browser cached.
vastlint (cargo install vastlint, npm install vastlint, or the MCP server) applies versioned rules to the XML itself: mezzanine expectations on SSAI-bound tags, deprecated API frameworks, duration and media consistency. It is independent of IAB Tech Lab and of AgenticAdvertising.org; it is the package that owns the VAST payload after your agent or trafficking UI emits it.
When verification vendors QA the tag separately from the video team, align on what the verification manager actually checks versus what the stitcher transcodes. Measurement OK in a browser is not SSAI readiness.
Where to go next
- VPAID migration for VAST 4.1+ when interactive files still ride the tag SSAI will reject.
- Validate OMID inside VAST AdVerifications before you assume CTV measurement survives transcode.
- Prepare VAST 4.4 CTV formats before you commit portfolio traffic to partners that only tested linear CSAI tags.
Fill on CTV is not a single tag. It is the ingest path you never opened in the browser.
Top comments (0)