Audio and podcast ads in VAST XML
Audio ads run on VAST. DAAST, the separate audio standard, was deprecated and folded into VAST 4.1 in 2018, and since then an audio ad tag has been an ordinary VAST document whose MediaFile happens to carry an audio mime type. There is no audio-only element set to learn.
The markup is ordinary. What makes audio different is how long a mistake survives. A broken video ad produces a black screen somebody notices. A broken audio ad produces silence, or the previous segment continuing, and the listener assumes the episode had no ad in it. Nothing escalates, and the failure surfaces weeks later as a delivery shortfall nobody can explain.
Quick reference
| Standard | VAST 4.1 and later. DAAST is deprecated |
| Creative element | <Linear>, same as video |
| MediaFile type | audio/mpeg, audio/mp4, audio/aac, audio/ogg |
| Duration format | HH:MM:SS, required on Linear |
| Break scheduling | VMAP or the insertion platform |
A minimal audio ad tag
<VAST version="4.2" xmlns="http://www.iab.com/VAST">
<Ad id="audio-1">
<InLine>
<AdSystem version="1.0">My Audio Ad Server</AdSystem>
<AdTitle>30s mid-roll</AdTitle>
<AdServingId>5e21-aud-0198</AdServingId>
<Impression><![CDATA[https://track.example.com/imp?cb=[CACHEBUSTING]]]></Impression>
<Creatives>
<Creative id="c1" sequence="1">
<UniversalAdId idRegistry="Ad-ID">AUD1234</UniversalAdId>
<Linear>
<Duration>00:00:30</Duration>
<TrackingEvents>
<Tracking event="start"><![CDATA[https://track.example.com/start]]></Tracking>
<Tracking event="firstQuartile"><![CDATA[https://track.example.com/q1]]></Tracking>
<Tracking event="midpoint"><![CDATA[https://track.example.com/mid]]></Tracking>
<Tracking event="thirdQuartile"><![CDATA[https://track.example.com/q3]]></Tracking>
<Tracking event="complete"><![CDATA[https://track.example.com/complete]]></Tracking>
</TrackingEvents>
<MediaFiles>
<MediaFile delivery="progressive" type="audio/mpeg" bitrate="128" width="0" height="0">
<![CDATA[https://cdn.example.com/spot-128.mp3]]>
</MediaFile>
<MediaFile delivery="progressive" type="audio/aac" bitrate="64" width="0" height="0">
<![CDATA[https://cdn.example.com/spot-64.aac]]>
</MediaFile>
</MediaFiles>
</Linear>
</Creative>
</Creatives>
</InLine>
</Ad>
</VAST>The MediaFile type is where audio tags break
VAST expects a type attribute on every MediaFile, and players filter on it before downloading anything. An audio creative served with a video mime type, or with no type at all, is skipped by a strict player without an error the buyer ever sees.
Dynamic insertion platforms are unusually good at producing this bug, because the transcode target and the declared type are set in different parts of the pipeline. A platform configured to transcode to AAC while its tag template still declares audio/mpeg ships a mismatch on every impression.
Note also that width and height are required attributes on MediaFile in every 4.x schema, and mean nothing for audio. The convention is to send zeros. Omitting them is a schema error even though no player will ever read them, which surprises people building an audio tag from scratch rather than adapting a video one.
Duration is a format, not a number
<Duration> is required on a Linear creative and its format is HH:MM:SS. An ad server that emits 30 instead of 00:00:30 produces a document that fails to parse in a strict player and gets interpreted inconsistently in a permissive one.
In video this surfaces quickly. In audio it surfaces as a completion rate that cannot be right, discovered during a reconciliation two weeks after launch.
Ad pods in a podcast break
Podcast and streaming audio breaks are usually pods: two or three spots played in order. The mechanics are the same as video, using the sequence attribute on <Ad>, and the same failure modes apply. See the ad pods guide for the full treatment.
One audio-specific consideration: pod position matters more than in video, because listeners cannot skip and the drop-off through a three-spot break is steep. If your reporting cannot distinguish spot one from spot three, the tracking event set is the reason, not the medium.
<!-- Two-spot mid-roll break. Sequence decides play order. -->
<Ad id="slot-1" sequence="1">
<InLine>
<AdSystem version="1.0">My Audio Ad Server</AdSystem>
<AdTitle>Spot 1 of 2</AdTitle>
<AdServingId>5e21-aud-0198</AdServingId>
<Impression><![CDATA[https://track.example.com/imp?slot=1]]></Impression>
<Creatives>
<Creative id="c1">
<UniversalAdId idRegistry="Ad-ID">AUD1234</UniversalAdId>
<Linear>
<Duration>00:00:30</Duration>
<TrackingEvents>
<Tracking event="start"><![CDATA[https://track.example.com/start?slot=1]]></Tracking>
<Tracking event="complete"><![CDATA[https://track.example.com/complete?slot=1]]></Tracking>
</TrackingEvents>
<MediaFiles>
<MediaFile delivery="progressive" type="audio/mpeg" bitrate="128" width="0" height="0">
<![CDATA[https://cdn.example.com/spot-a.mp3]]>
</MediaFile>
</MediaFiles>
</Linear>
</Creative>
</Creatives>
</InLine>
</Ad>
<Ad id="slot-2" sequence="2">
<!-- same shape, its own Impression and its own trackers -->
</Ad>VAST XML fragment only. This excerpt belongs inside a complete VAST document, so standalone validation will fail until it is wrapped in a full <VAST>response.
Each ad in the pod fires its own <Impression>. Slot identity has to come from a parameter you put on the URLs, since VAST has no field that reports which position an ad played in. Teams that skip that parameter discover it after the first campaign, when the advertiser asks why every spot performed identically.
What server-side measurement cannot see
Podcast measurement counts downloads from server logs, because most podcast applications never confirm playback to anyone. The IAB Tech Lab Podcast Technical Measurement Guidelines are built on that constraint, and version 2.3 went out for public comment in July 2026 with clearer handling of duplicates, measurement windows and video podcasts.
For ad tags the consequence is direct. A download is counted before the ad ever plays, so a malformed VAST tag leaves the download count untouched while the impression count comes back at zero or wrong. The discrepancy then gets attributed to methodology. Some of it genuinely is methodology, since a download and a fired impression are different events. The rest is the tag, and only one of those two explanations can be fixed.
Video podcasts make the split visible, because a streaming video surface has a real player that fires real events. The same show, sometimes the same ad, is measured as a download on one distribution path and as a VAST impression with quartiles on the other.
The audio checklist
- MediaFile type is an audio type and matches what the CDN actually serves.
- At least two renditions at different bitrates, so a constrained connection has something to fall back to.
- Duration in HH:MM:SS, matching the real asset length.
- Full quartile set, not just an impression. Without quartiles there is no way to distinguish a played spot from a fetched one.
- HTTPS on every tracking and impression URL, with macros correctly encoded.
- Wrapper chains that terminate. Audio chains get long, and the depth limit is the same one that applies to video. See wrapper chains.
- No leftover DAAST markup. Documents migrated from DAAST sometimes carry elements that no longer exist in the version they now declare. See the DAAST reference.
Validate the tag, because nothing else will
Every check above runs on the document, before a single listener is involved. Audio is the simplest surface VAST supports and also the one where no other part of the stack will tell you something is wrong, so the pre-flight check carries more weight here than it does in video.