VASTlint
Back to blog
CTV delivery/7 min read

SSAI Rewrites Your VAST. Validate What Comes Out, Not What Went In

In CTV, the tag you authored is not the tag that runs. Server-side ad insertion unwraps your wrapper chain, transcodes your media, rewrites your trackers, and fires your beacons from a data center. Five stitch-time failure modes, and the points in the pipeline where validation actually prevents them.

Author

Alex Sekowski

Published

July 15, 2026

Reading time

7 min read

SSAICTVVAST macrosMeasurementTracking

The tag you authored is not the tag that runs

Most CTV ad delivery now runs through server-side ad insertion. A stitcher sits between the ad server and the device, fetches your VAST on the server, splices the creative directly into the content stream, and hands the device one continuous video. The device may never see your XML at all.

Almost all VAST QA happens on the document you built: the tag is validated at authoring time, certified with a partner, and archived in a ticket. Between that QA and the glass, the stitcher unwraps it, transcodes it, rewrites it, and often takes over firing its trackers. Each of those transformations is a place where a valid tag becomes a broken delivery, and none of them show up in the QA you did upstream.

What a stitcher actually does to your VAST

The stitcher fetches the tag server-side and walks the wrapper chain itself, so redirect latency and depth limits play out in a data center rather than on the device. It selects a media file, or transcodes one, to match the content stream's resolution, bitrate, and codec. VAST 4.0 added the Mezzanine element for exactly this consumer: a mastering-quality source the stitcher can transcode cleanly instead of upscaling a compressed MediaFile.

Then it handles tracking, in one of two modes. In client-side beaconing, the stitcher passes tracking metadata to the player SDK and the device fires events. In server-side beaconing, the stitcher fires impressions and quartiles itself on the device's behalf. Every failure mode below traces back to one of these transformations.

Failure one: macros nobody expanded

VAST 4.1 standardized the macro vocabulary: [TIMESTAMP], [CACHEBUSTING], [DEVICEUA], [IFA], and the rest. In client-side playback the player expands them at fire time. In SSAI the stitcher has to do it, and the handoff is where it breaks. The classic symptom is a tracker URL that arrives at the ad server with the literal string [CACHEBUSTING] or [TIMESTAMP] still in it.

Unexpanded macros are not cosmetic. A missing cache buster means intermediaries dedupe distinct impressions. A missing timestamp breaks sequential attribution. A device macro left literal means the measurement vendor receives a beacon it cannot attribute to any device class. Validate the macro syntax in every tracker URL before the tag enters a stitcher's cache, and audit served beacons for literal bracket strings after.

Failure two: beacons from a data center

In server-side beaconing mode, your impression pixel fires from the stitcher's infrastructure: a cloud IP and a server user agent. To every downstream system that was built for client-fired beacons, that traffic pattern is indistinguishable from a bot farm, because mechanically it is one.

IAB Tech Lab's SSAI guidance defines the fix: the stitcher forwards the original device context on every beacon, X-Forwarded-For for the device IP and X-Device-User-Agent for the device UA, plus the standardized VAST macros carrying device identity. When those headers are missing, ad servers cannot dedupe across devices, IVT filters flag the traffic, measurement vendors discard it, and CPMs follow. If you buy or sell through SSAI, beacon header forwarding is a certification item, not a nice-to-have.

Failure three: the schedule is not the playback

A stitcher knows when it inserted an ad into the stream. It does not necessarily know whether the device kept playing. Pure server-side quartile firing reports what the schedule intended, not what the viewer saw: a user who backs out at second three can still generate a server-fired complete.

This is why the Media Rating Council's SSAI guidance pushes measurement toward client-side confirmation, and why serious CTV pipelines run hybrid beaconing, with the device confirming playback events even when the server manages the rest. When you evaluate an SSAI partner, the question to ask is precise: which events fire from the server, which from the device, and what happens to quartiles when the session dies mid-pod.

Get VAST spec updates, platform guides, and release notes in your inbox.

Failure four: verification and interactivity go blind

AdVerifications carries JavaScript that expects to execute in a client runtime and observe rendering. There is no browser inside a stitcher. Unless the device-side player integrates the OM SDK for CTV and executes the verification resource, OMID measurement on an SSAI path is a field in the XML and nothing else. The same applies to interactive layers: a SIMID creative needs a client player that loads it, and a stitcher that flattens the ad into the stream has nowhere to run it.

The failure is contractual as much as technical. Deals get signed on measured viewability against inventory where the delivery path cannot execute the measurement. If verification matters to the buy, the SSAI path needs an explicit answer for where the verification code runs.

Failure five: the cache serves yesterday's tag

Stitchers cache aggressively, both transcoded creatives and resolved VAST documents, because stitch-time budgets are tight. The cost is staleness: a campaign that ended, a tracker that rotated, or a creative that was replaced can keep serving from cache until eviction. If your trackers are versioned or your creatives legally time-boxed, the stitcher's cache TTL is part of your compliance surface. Ask for it in writing.

Where validation actually helps

  • At creative onboarding, before the tag enters anyone's cache: full spec validation, version-appropriate structure, and macro syntax in every tracker URL.
  • Before stitch execution: confirm a Mezzanine or transcode-suitable MediaFile exists, wrapper depth fits the stitcher's fetch budget, and every tracker is https.
  • On the served output: pull what the stitcher actually delivers and validate that document, because unwrapping and re-rendering can drop elements your QA verified upstream.
  • On the beacon stream: sample served beacons for literal macro brackets, missing forwarding headers, and data-center-only IPs on impression events.
  • An Error tracker in the tag, always, so that when something does fail at stitch time, it reports instead of vanishing.

Lint the tag at every handoff

The CI guide covers running vastlint at onboarding, before cache insertion, and against served output, so the document that reaches the stitcher is the document you certified.

Validate VAST in CI

Sources and further reading

The IAB Tech Lab guidance on macro expansion and device context forwarding for server-side beacons.

Workshop takeaways on where SSAI implementations diverge and what standardization is still missing.

MRC's measurement requirements for SSAI delivery, including client-side confirmation.

The standardized macro list, expansion rules, and validation checks vastlint runs on tracker URLs.

The wider map of CTV delivery loss that stitch-time failures sit inside.

The upstream half of this story: why authoring-time QA misses delivery-time failures.

Keep reading

Related stories

All posts