VASTlint
Back to blog
CTV economics/9 min read

CTV Sells 65 Percent of Its Ad Capacity. The Headroom Sits in the Formats With the Shortest Delivery Track Record.

Omdia published a $0.21 per viewing hour monetisation benchmark for ad-supported CTV on 29 July. The two utilisation figures behind it point at different problems, and the larger half of the upside can only come from pause, screensaver, overlay, squeezeback and in-scene inventory. Those are the formats whose VAST payload shipped two weeks ago.

Author

Alex Sekowski

Published

July 31, 2026

Reading time

9 min read

CTVAd loadCTV Ad PortfolioVAST errorsMonetisation

A benchmark, and what it is measuring

Omdia published Video Advertising KPI Benchmarks: Monetization on 29 July 2026. The headline number is that ad-supported connected TV services could average $0.21 per hour of viewing if every available advertising slot were sold, measured across hybrid VoD, AVoD, FAST and broadcaster VoD, and derived from 2025 advertising loads in the UK, the US, Australia, Brazil, Canada, France, Germany and Mexico.

Hour of viewing is a better unit than the industry usually gets. Ad load per hour differs by a factor of several between a FAST channel that runs near broadcast density and an ad-light subscription tier that runs four minutes, so revenue per user or revenue per impression compares almost nothing when you put those two services in the same table. Normalising on viewing time makes the comparison mean something.

The report carries two utilisation figures alongside the benchmark. Services are running at roughly 65 percent of their commercial capacity, and at 32 percent of the maximum regulatory advertising capacity that applies to broadcast linear television. Omdia puts the resulting upside at two to three times.

Those two percentages are not the same gap

Most of the trade coverage ran them together. They describe different problems and they have different fixes.

Sixty-five percent of commercial capacity is a fill problem. The slots exist, the service is willing to sell them, and they go unsold. Closing that gap alone is worth roughly one and a half times, not two to three.

Thirty-two percent of linear's regulatory ceiling is a load problem. It says streaming shows far fewer ad minutes per hour than a broadcaster is legally permitted to show, which is a decision about the product rather than a failure of the sales team. Getting from 32 percent toward that ceiling is where the rest of the two to three times lives.

So the larger half of the upside requires more advertising minutes per viewing hour, not just better fill on the minutes already there. That is the part worth thinking about carefully if you ship tags for a living.

You cannot get there with more mid-rolls

Streaming runs at a third of linear's permitted load for a reason, and the reason is not that anyone forgot. Ad-supported tiers compete on tolerability against an ad-free tier of the same service, one click away in the same account settings. Tripling mid-roll minutes is a churn experiment that most of these services have already run at smaller increments and stopped running.

If the minutes cannot come from interrupting content, they have to come from advertising time that sits outside the content: the pause screen, the idle screensaver, an overlay during play, a squeezeback around the frame, an in-scene placement, and QR codes attached to any of them.

That is the same list IAB Tech Lab standardised in the CTV Ad Portfolio. The signaling guidance was finalised on 22 July 2026 and the creative payloads landed in the VAST repository on 17 July, in one pull request carrying both a VAST 4.4 draft schema and a set of VAST 2.0 extension documents.

The answer to where the two to three times comes from and the answer to what the standards body shipped two weeks ago are the same list. That is not a coincidence, it is the industry routing around a constraint it already understands. It does mean the revenue headroom is concentrated in exactly the formats with the least delivery history.

Unsold capacity is recoverable. The break comes round again next hour. A slot that filled and then failed is gone, and in the seller's own reporting it looks identical to a slot nobody bid on.

vastlint

Sold is not played, and hour of viewing is measured after the fact

The $0.21 ceiling is explicitly defined as every available slot being sold. The realised figure is booked revenue divided by viewing hours, and revenue books against a tracked impression, not against a win notice.

Everything between those two events is the VAST path. Fetch the tag, resolve however many wrappers are in the chain, pick a MediaFile the device can actually decode, render it, fire the impression and the quartiles. A failure anywhere in that sequence produces an Error ping with a code in it and nothing else that anyone downstream counts.

The slot still consumed its position in the break. The viewing hour still elapsed. No impression was booked. In a monetisation-per-hour view that slot is non-revenue viewing time, which is the same thing the report is calling unsold capacity.

Which is the point. The 35 percentage points Omdia measures as unfilled commercial capacity contain an unknown quantity of slots that were sold and did not deliver, and the prescribed remedy of growing the advertiser base does nothing whatsoever for that portion. More demand on a path that drops one in fifty responses produces more revenue and the same drop rate.

Which failures scale with ad load, and which scale worse

Some VAST failures are per-impression and grow linearly as you add slots. A creative with no playable MediaFile fails at the same rate whether it is the first ad of the hour or the ninth.

Pod-level failures do not behave that way. A pod has one deadline, set by the break length or by the stitching window, and every slot in it draws down the same budget. A wrapper chain that resolves comfortably in a two-slot pre-roll starts colliding with that deadline at six slots, because the chains resolve in sequence against a fixed wall clock.

That is the failure mode to watch as load rises: the same tags, the same partners, the same chain depth, and a timeout rate that climbs because you changed the pod and not the tag.

VAST error codes, and how each behaves as slots per hour go up
text
102  VAST version not supported     New formats push responses onto 4.x paths. Device fleets that     parse 2.0 fine will reject them. Scales with format mix, not slots. 301  Timeout of VAST URI provided in Wrapper302  Wrapper limit reached     Superlinear in pod depth. One shared deadline, sequential chains.     Adding slots shortens the budget available to every chain in the pod. 403  Could not find a MediaFile supported by this player     A pause ad now carries video, image and sometimes an interactive     SIMID file. A player that ignores the extension it arrived in has     no renditions at all, not a degraded one. 201  Player expecting different linearity     A portfolio format delivered as NonLinearAds into a slot the     player opened expecting Linear. Rises with format mix. 501  NonLinear dimensions do not align with the display area     Rare while NonLinear meant a small overlay banner. Squeezeback,     in-scene and QR all resolve a rectangle against the ad view.     This becomes a common code, not an exotic one. 900  Undefined error     What most players report when they meet a payload shape they were     not built for. Rises first, and tells you least.

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

The new formats have two delivery paths and neither has a track record

The 17 July pull request shipped the portfolio twice. The VAST 4.4 draft schema carries the formats natively, one AdCOM signal per Extension element. The VAST 2.0 extension documents carry the same six formats and the same QR metadata inside a single named container, alongside the media, because VAST 2.0 is what parses on the long tail of devices that will still be in living rooms when 4.4 is final.

Both are current. They are not interchangeable, and a validator built for one reports nothing at all on the other. We wrote that up separately.

The delivery consequence is easy to underestimate. A pause ad used to be a JPEG in a NonLinear StaticResource. It is now a creative with a duration, a MediaFiles list, optional interactive content and quartile tracking. Every failure mode that has ever applied to a linear creative now applies to a pause screen, on hardware that has never rendered one, through an extension mechanism whose whole design property is that unaware players ignore it silently.

Silent is the operative word. An extension a player does not recognise is not a parse error and does not fire an Error ping. It renders the native NonLinear fallback if the ad server included one, and nothing if it did not.

Why the first year of a format is the expensive one to get wrong

A mid-roll that fails costs one impression against a baseline that is years deep and well understood. Nobody reprices mid-roll inventory because of it.

A new format that fails in its first year costs the renewal. Buyers have no baseline to average against, so early delivery evidence is the entire evidence base, and a pause ad that did not render is not read as an integration bug. It is read as a fact about pause ads.

Omdia's own recommendation names the dependency. Reaching the benchmark, the report says, requires growing the advertiser base to maximise fill rates and improving advertising context protocols. The first half is a sales problem. The second half is a specification and conformance problem, and it is the one that determines whether the inventory the sales team sells actually arrives.

What to verify before you raise ad load

  • Test the pod, not the tag. Chain depth that resolves inside a two-slot break can miss the deadline at six. Measure wrapper resolution time against the actual pod duration you are moving to, not against a single-impression timeout.
  • Decide which portfolio encoding each partner expects, and ask rather than assume. The 4.x per-signal pattern and the VAST 2.0 container pattern are both live and a parser built for one sees nothing in the other.
  • Always send a native NonLinear fallback resource alongside a 2.0 portfolio extension. Without it, a player that ignores the extension renders nothing and reports nothing.
  • Treat error 501 as a launch blocker for squeezeback, in-scene and QR. Those formats resolve a rectangle against the ad view, and a rectangle that does not fit is the failure mode the code was written for.
  • Split your error reporting by format before you scale the format. An aggregate error rate that looks fine because mid-rolls dominate the denominator will hide a pause-ad path that is failing most of the time.
  • Watch code 900 specifically during the first weeks of a new format. Undefined error is what a player reports when it meets a payload shape it was not built for, so it rises first and explains least.
  • Reconcile unfilled against sold-and-errored on the same report. If those two numbers live in different systems, the gap the benchmark describes is not measurable in your own data either.

The part that is in your control

Fill rate depends on demand, on floors, on how many buyers have your inventory whitelisted, and on macroeconomic conditions nobody in ad ops sets. It is worth pursuing and it is largely someone else's job.

Whether a tag that wins renders correctly is entirely an engineering property of the tag, the chain and the player, and it is knowable before launch rather than after. That asymmetry is why the delivery half of this deserves attention out of proportion to how often it gets discussed. It is the half you can fix on a Tuesday.

The benchmark is genuinely useful and the headroom is genuinely there. Just be clear that the industry is about to push its growth through the newest, least tested formats in the catalogue, on the most fragmented device population in digital advertising, and that the metric everyone will use to score it cannot see the difference between an empty slot and a broken one.

Check a CTV Ad Portfolio tag before you scale the format

Paste a tag into the validator for structural, media file, macro and tracking findings, plus the CTV Ad Portfolio and VAST 4.4 rules on the 4.x signaling path. It runs locally in the browser and nothing is stored.

Open the validator

Sources and further reading

The 29 July 2026 announcement of Video Advertising KPI Benchmarks: Monetization, including the $0.21 HOV benchmark, the 65 percent commercial capacity and 32 percent regulatory capacity figures, and the markets covered.

Trade coverage of the same report, with the two to three times revenue framing.

CTV Ad PortfolioIAB Tech Lab

The standard defining Pause, Screensaver, Overlay, Squeezeback, In-Scene and QR formats. Signaling guidance finalised 22 July 2026.

The two encodings that landed in the same pull request, why a validator built for one reports nothing on the other, and the CreativeId binding rule.

The draft schema behind the native 4.x delivery path for the portfolio formats.

The per-impression version of the same argument: what a one percent silent failure rate costs at CTV prices, failure by failure.

The buy-side half of the same report: why unsold and unparseable land in the same bucket in a seller's fill rate.

Every rule vastlint checks, including the CTV Ad Portfolio and VAST 4.4 rules.

Keep reading

Related stories

All posts