<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aleksander Sekowski</title>
    <description>The latest articles on DEV Community by Aleksander Sekowski (@aleksuix).</description>
    <link>https://dev.to/aleksuix</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3866734%2F559a0a69-3c28-49e2-91c7-503810b941ba.png</url>
      <title>DEV Community: Aleksander Sekowski</title>
      <link>https://dev.to/aleksuix</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aleksuix"/>
    <language>en</language>
    <item>
      <title>The 10 VAST Errors That Silently Kill Your CTV Ad Revenue</title>
      <dc:creator>Aleksander Sekowski</dc:creator>
      <pubDate>Wed, 08 Apr 2026 01:35:58 +0000</pubDate>
      <link>https://dev.to/aleksuix/the-10-vast-errors-that-silently-kill-your-ctv-ad-revenue-25i8</link>
      <guid>https://dev.to/aleksuix/the-10-vast-errors-that-silently-kill-your-ctv-ad-revenue-25i8</guid>
      <description>&lt;p&gt;&lt;a href="https://medium.com/@aleksander-sekowski/the-10-vast-errors-that-silently-kill-your-ctv-ad-revenue" rel="noopener noreferrer"&gt;Originally published on Medium.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Samsung TV Plus just crossed 100 million monthly active users. Netflix ended 2024 with 277.6 million subscribers worldwide, 70 million on its ad-supported tier. Amazon Prime Video had 230 million users. Roku reported 89.8 million active accounts in Q4 2024. The ad spend flowing through all of it: $33 billion in the US alone in 2024 runs on VAST XML.&lt;/p&gt;

&lt;p&gt;Every impression, every pixel, every billing event depends on a tag being parsed correctly by players, ad servers, and measurement vendors that were built by different teams to different tolerances. Penthera found that 40% of VOD ads fail. Google Ad Manager flags any gap larger than 25% between impressions served and impressions counted as a sign of systemic VAST errors. Most of these failures trace back to a handful of tag-level mistakes that are trivially detectable before the ad ever reaches a player.&lt;/p&gt;

&lt;p&gt;I built an open-source tool that catches all errors mentioned below: vastlint. 108 rules across VAST 2.0 through 4.3. Free, no account, runs in CI in about 100 microseconds per tag.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/aleksUIX" rel="noopener noreferrer"&gt;
        aleksUIX
      &lt;/a&gt; / &lt;a href="https://github.com/aleksUIX/vastlint" rel="noopener noreferrer"&gt;
        vastlint
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;vastlint&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://crates.io/crates/vastlint-cli" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2beb5b5855b57656861b67861574aecb4cee782d97520ddfa281e7698b6b629d/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f766173746c696e742d636c692e7376673f6c6162656c3d6372617465732e696f" alt="crates.io"&gt;&lt;/a&gt;
&lt;a href="https://crates.io/crates/vastlint-core" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a72af7d00fdcded39a6a5c8dff3c947cabcea697d93e6ca79d588d146ccdae79/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f766173746c696e742d636f72652e7376673f6c6162656c3d766173746c696e742d636f7265" alt="crates.io"&gt;&lt;/a&gt;
&lt;a href="https://docs.rs/vastlint-core" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2e66f1a456a606735a90cc9cc47c2b60e78d103706a464beed69a6b0912e8b93/68747470733a2f2f646f63732e72732f766173746c696e742d636f72652f62616467652e737667" alt="docs.rs"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/vastlint" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/f57064e4b17dcbd17fc10fce20ffadc141f9da635abec86d173144a8c552d152/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f766173746c696e742e7376673f6c6162656c3d6e706d" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://github.com/aleksUIX/vastlint/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/25a5325411ddfdd46094f1e6a698dac67891eaf213c5891a8a6c76f3466091fe/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f766173746c696e742d636c692e737667" alt="license"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A VAST XML validator. Checks ad tags against the IAB Tech Lab VAST specification so you don't have to read it. Over $30 billion in annual CTV and video ad spend flows through VAST XML, and malformed tags are one of the most common causes of lost impressions, broken tracking, and revenue discrepancies between platforms. There is no widely adopted open-source tool that validates VAST XML against the full IAB specification across all published versions.&lt;/p&gt;
&lt;p&gt;Validates VAST documents against:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://iabtechlab.com/standards/vast/" rel="nofollow noopener noreferrer"&gt;IAB Tech Lab VAST&lt;/a&gt; 2.0, 3.0, 4.0, 4.1, 4.2, and 4.3 -- structural rules derived from the published XSD schemas and spec prose&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.w3.org/TR/xml/" rel="nofollow noopener noreferrer"&gt;W3C XML 1.0&lt;/a&gt; well-formedness (malformed documents are rejected before any spec rule runs)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rfc-editor.org/rfc/rfc3986" rel="nofollow noopener noreferrer"&gt;RFC 3986&lt;/a&gt; URI syntax (all URL fields)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.iana.org/assignments/media-types/" rel="nofollow noopener noreferrer"&gt;IANA Media Types&lt;/a&gt; (MediaFile and resource MIME types)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.iso.org/iso-4217-currency-codes.html" rel="nofollow noopener noreferrer"&gt;ISO 4217&lt;/a&gt; currency codes (Pricing elements)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ad-id.org/" rel="nofollow noopener noreferrer"&gt;Ad-ID&lt;/a&gt; registry format (UniversalAdId)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;108 rules across required fields, schema validation, structural correctness…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/aleksUIX/vastlint" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Here are the ten I see most often.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Missing  attributes&lt;br&gt;
delivery, type, width, height — all four are required. Leave one out and the player guesses. CTV devices don't guess well. A tag that plays fine in Chrome fails on Roku because the device won't infer the delivery method from context. The XML is valid. The spec is violated. The blank slot is yours.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP media URLs on HTTPS inventory&lt;br&gt;
A  pointing at http:// gets blocked by mixed-content policies on any HTTPS page or app. The ad doesn't play, the impression doesn't fire, fill rate drops. The tag is valid XML. It's technically spec-compliant. It just won't work on most real inventory. This one is invisible to any validator that only checks structure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bad  format&lt;br&gt;
The spec requires HH:MM:SS or HH:MM:SS.mmm. Tags show up with 00:30, 30s, plain 30, or empty. Strict players reject the creative outright. Loose players guess wrong and fire progress events — firstQuartile, midpoint, complete — at the wrong times. Your reporting looks fine but the measurement is off.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No  element&lt;br&gt;
No  URL means the ad plays but nobody gets paid. The DSP doesn't know it rendered, the SSP can't bill. Both sides pull discrepancy reports and argue. On wrapper chains it's worse. A missing impression at any level means that link in the transaction goes unrecorded. The outer wrapper fires, the inner wrapper doesn't, the numbers never reconcile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wrapper without &lt;br&gt;
A  with no redirect URL is a dead end. The slot goes unfilled, no error fires, the demand partner reports zero delivery. Usually happens when a template renders a wrapper variant but the URL variable is null or empty. At scale, that's thousands of lost impressions per minute with nothing in the logs pointing at the cause.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt; missing or malformed&lt;br&gt;
Required on every  since VAST 4.0. Needs an idRegistry attribute and a non-empty value. Without it, frequency capping and competitive separation break. The ad server can't tell two creatives apart, so it can't enforce exclusion rules between competing brands or cap a user who's already seen the ad five times. The ads still serve. The contracts you're supposed to be honoring don't.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;VPAID apiFramework on VAST 4.1+ tags&lt;br&gt;
VPAID was deprecated in VAST 4.1. Google, Amazon, and most major SSPs block VPAID execution entirely. Tags declaring apiFramework="VPAID" pass XML validation. They may even pass some linting tools that only check structure. They get filtered before reaching a screen. Fill rate craters and the root cause is a single attribute value that no one thought to check.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tracking event typos&lt;br&gt;
The spec defines a fixed set: creativeView, start, firstQuartile, midpoint, thirdQuartile, complete, and so on. Misspell one — Midpoint, mid_point, MidPoint — and no player fires it. The pixel silently never calls. VAST 4.0 also removed fullscreen and exitFullscreen. Tags copied from 3.0 templates still carry those events. They worked. They don't anymore.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Malformed XML&lt;br&gt;
Unescaped &amp;amp;, unclosed elements, bad UTF-8. Common when tags are assembled by string concatenation instead of an XML library. Many ad servers have lenient parsers that silently fix this. CTV devices don't. You debug a blank slot for an afternoon and the problem is &amp;amp; instead of &amp;amp; in a click URL buried three wrappers deep.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Version declaration doesn't match content&lt;br&gt;
The tag says  but contains  and , which are 4.x elements. The player applies 2.0 parsing rules and skips what it doesn't recognize. Happens constantly when templates are copied between projects without updating the version attribute. Everything looks fine in dev. In production the player is running a different code path than you think.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every one of these is detectable before the tag reaches a player. None of them require a live ad server, a real device, or a debugging session.&lt;/p&gt;

</description>
      <category>adtech</category>
      <category>rust</category>
      <category>node</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
