vastlint

VAST ad pods & sequencing

An ad pod is a group of video ads played back-to-back in a single ad break — similar to a commercial break on TV. A pod might contain a 6s bumper, a 30s main ad, and another 6s bumper, all playing sequentially before content resumes.

In VAST XML, ad pods are represented by multiple <Ad> elements in a single <VAST> response, each with a sequence attribute that defines play order. VAST 4.x introduced the <AdPod> type and dedicated pod metadata elements.

Quick reference

Sequencingsequence attribute on each <Ad> element
Play orderAscending numeric order of sequence values
allowMultipleAdsMust be true on wrapper tags for pods to pass through
VAST 4.x AdPod<AdPod> with maxAds and maxDuration
CTV supportWidely supported on Roku, Fire TV, Apple tvOS, Samsung, LG

The sequence attribute

The sequence attribute on <Ad> is a positive integer that defines the ad's position in the pod. Ads play in ascending order of their sequence value. Gaps in sequence numbers are allowed — the player fills them in order.

An <Ad> without a sequence attribute is treated as a standalone ad, not part of a pod. Players that receive a mixed response (some with sequence, some without) should play sequenced ads in pod order and ignore unsequenced ads or treat them as separate requests.

<VAST version="4.2">
  <!-- Ad 1: Opening bumper (sequence=1) -->
  <Ad id="bumper-1" sequence="1">
    <InLine>
      <AdSystem>My Ad Server</AdSystem>
      <AdTitle>Opening Bumper</AdTitle>
      <Impression><![CDATA[https://track.example.com/bumper1-imp]]></Impression>
      <Creatives>
        <Creative sequence="1">
          <Linear>
            <Duration>00:00:06</Duration>
            <MediaFiles>
              <MediaFile delivery="progressive" type="video/mp4"
                width="1920" height="1080" bitrate="2000">
                <![CDATA[https://cdn.example.com/bumper-open.mp4]]>
              </MediaFile>
            </MediaFiles>
          </Linear>
        </Creative>
      </Creatives>
    </InLine>
  </Ad>

  <!-- Ad 2: Main 30s ad (sequence=2) -->
  <Ad id="main-1" sequence="2">
    <InLine>
      <AdSystem>My Ad Server</AdSystem>
      <AdTitle>Main Ad</AdTitle>
      <Impression><![CDATA[https://track.example.com/main-imp]]></Impression>
      <Creatives>
        <Creative sequence="1">
          <Linear>
            <Duration>00:00:30</Duration>
            <TrackingEvents>
              <Tracking event="start"><![CDATA[https://track.example.com/main-start]]></Tracking>
              <Tracking event="complete"><![CDATA[https://track.example.com/main-complete]]></Tracking>
            </TrackingEvents>
            <MediaFiles>
              <MediaFile delivery="progressive" type="video/mp4"
                width="1920" height="1080" bitrate="2500">
                <![CDATA[https://cdn.example.com/main-ad.mp4]]>
              </MediaFile>
            </MediaFiles>
          </Linear>
        </Creative>
      </Creatives>
    </InLine>
  </Ad>

  <!-- Ad 3: Closing bumper (sequence=3) -->
  <Ad id="bumper-2" sequence="3">
    <InLine>
      <AdSystem>My Ad Server</AdSystem>
      <AdTitle>Closing Bumper</AdTitle>
      <Impression><![CDATA[https://track.example.com/bumper2-imp]]></Impression>
      <Creatives>
        <Creative sequence="1">
          <Linear>
            <Duration>00:00:06</Duration>
            <MediaFiles>
              <MediaFile delivery="progressive" type="video/mp4"
                width="1920" height="1080" bitrate="2000">
                <![CDATA[https://cdn.example.com/bumper-close.mp4]]>
              </MediaFile>
            </MediaFiles>
          </Linear>
        </Creative>
      </Creatives>
    </InLine>
  </Ad>
</VAST>

allowMultipleAds on wrapper tags

If your ad pod response passes through one or more VAST wrapper tags, each wrapper must set allowMultipleAds="true". If any wrapper in the chain sets allowMultipleAds="false" (the default), the player will discard all but the first ad in the pod.

<!-- Wrapper must allow multiple ads for pods to pass through -->
<VAST version="4.2">
  <Ad id="wrapper1">
    <Wrapper allowMultipleAds="true" followAdditionalWrappers="true">
      <AdSystem>SSP</AdSystem>
      <VASTAdTagURI><![CDATA[https://adserver.example.com/pod-vast]]></VASTAdTagURI>
      <Impression><![CDATA[https://track.ssp.com/impression]]></Impression>
    </Wrapper>
  </Ad>
</VAST>

→ vastlint rule: VAST-3.0-allow-multiple-ads

VAST 4.x AdPod type

VAST 4.0 introduced a dedicated <AdPod> element that can declare pod-level constraints: maximum number of ads (maxAds) and maximum total duration (maxDuration). This lets ad servers and players negotiate pod composition without relying on the actual ad content.

<VAST version="4.2">
  <Ad id="pod-request">
    <AdPod>
      <AdSystem>My Ad Server</AdSystem>
      <!-- Pod can contain at most 3 ads -->
      <maxAds>3</maxAds>
      <!-- Pod total duration cannot exceed 90 seconds -->
      <maxDuration>00:01:30</maxDuration>
      <!-- Pod-level impression tracking -->
      <Impression><![CDATA[https://track.example.com/pod-imp]]></Impression>
    </AdPod>
  </Ad>
</VAST>

Note: <AdPod> is used differently from a sequenced inline pod — it is primarily a mechanism for server-side pod assembly and is supported by a smaller number of players. Check your platform's documentation before using it.

Each ad in a pod fires its own Impression

Every <Ad> in a pod has its own <Impression> URL that fires independently when that ad plays. There is no single pod-level impression event in classic VAST sequencing. This means a 3-ad pod will fire 3 separate impression URLs, one per ad, as each ad plays.

Common mistakes checklist

  • Duplicate or missing sequence values — two ads with the same sequence number cause undefined play order. Always use unique, consecutive integers starting from 1.
  • allowMultipleAds not set on wrappers — the most common reason pods are truncated to a single ad in production. Every wrapper in the chain must haveallowMultipleAds="true".
  • Mixing sequenced and unsequenced ads — all ads in a pod should have explicit sequence attributes. Mixing sequenced and unsequenced ads in one VAST response leads to inconsistent player behaviour.
  • Pod total duration exceeds break length — the publisher defines the break length. If the pod's total declared duration exceeds it, the player may truncate the pod mid-break. Always confirm maximum break duration with the publisher.
  • Expecting a single pod-level impression — pods fire one impression per ad. Ad server reporting will show N impressions for an N-ad pod, not 1. Adjust your reporting expectations accordingly.