vastlint

VAST wrapper chains

A VAST wrapper is a VAST response that redirects to another VAST URL instead of containing an inline ad directly. Wrappers are used throughout the programmatic ad ecosystem for ad serving, third-party measurement, demand aggregation, and SSP/DSP integrations. A wrapper chain is a sequence of wrapper responses that must all resolve before the player reaches the inline ad with the actual video.

Wrapper chains are one of the most common sources of ad delivery failures. Each hop adds latency, and every platform enforces a maximum chain depth. Exceed it, and the slot goes unfilled with no error surfaced to the user.

Platform chain depth limits

PlatformMax hops
Google IMA SDK4
Roku RAF4
Amazon Fire TV4
Apple tvOS (IMA)4
Samsung Tizen (IMA)4
LG webOS (IMA)4
JW Player5

Wrapper element structure

A wrapper VAST response contains a <Wrapper> element instead of <InLine>. The <VASTAdTagURI> child element contains the URL of the next VAST tag in the chain.

<!-- Hop 1: Your SSP tag (wrapper) -->
<VAST version="4.2">
  <Ad id="wrapper1">
    <Wrapper allowMultipleAds="true" followAdditionalWrappers="true">
      <AdSystem>My SSP</AdSystem>
      <!-- URL of the next tag in the chain -->
      <VASTAdTagURI>
        <![CDATA[https://dsp.example.com/vast-tag?params=...]]>
      </VASTAdTagURI>
      <!-- Wrapper-level impression fires in addition to inline impression -->
      <Impression id="ssp-imp"><![CDATA[https://track.ssp.com/impression]]></Impression>
      <Error><![CDATA[https://track.ssp.com/error?code=[ERRORCODE]]]></Error>
    </Wrapper>
  </Ad>
</VAST>

<!-- Hop 2: DSP tag (another wrapper) -->
<VAST version="4.2">
  <Ad id="wrapper2">
    <Wrapper followAdditionalWrappers="true">
      <AdSystem>DSP</AdSystem>
      <VASTAdTagURI>
        <![CDATA[https://adserver.dsp.com/inline-vast]]>
      </VASTAdTagURI>
      <Impression><![CDATA[https://track.dsp.com/impression]]></Impression>
    </Wrapper>
  </Ad>
</VAST>

<!-- Hop 3: Inline ad (resolves the chain) -->
<VAST version="4.2">
  <Ad id="inline1">
    <InLine>
      <AdSystem>Ad Server</AdSystem>
      <AdTitle>My Video Ad</AdTitle>
      <Impression><![CDATA[https://track.adserver.com/impression]]></Impression>
      <Creatives>
        <Creative sequence="1">
          <Linear>
            <Duration>00:00:30</Duration>
            <MediaFiles>...</MediaFiles>
          </Linear>
        </Creative>
      </Creatives>
    </InLine>
  </Ad>
</VAST>

followAdditionalWrappers and allowMultipleAds

Two boolean attributes on <Wrapper> control chain resolution behaviour:

AttributeDefaultBehaviour when false
followAdditionalWrapperstruePlayer stops following wrapper chain at this hop. If the next tag is another wrapper, it is abandoned and the ad fails.
allowMultipleAdsfalsePlayer uses only the first <Ad> in the resolved response. Ad pods (multiple sequenced ads) are truncated to one ad.

For normal single-ad delivery, set followAdditionalWrappers="true". For ad pods passing through wrappers, set both attributes to true.

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

Tracking across wrapper chains

Each wrapper in the chain can declare its own <Impression>, <Error>, and <TrackingEvents> URLs. When the inline ad resolves, the player fires all accumulated tracking URLs from every wrapper in the chain plus the inline ad — in order from outermost wrapper to inline.

This means a 3-hop chain with an impression URL at each level will fire 4 impression URLs total (3 wrappers + 1 inline). This is expected behaviour and how each party in the programmatic chain records the impression.

Error tracking in wrapper chains

Each wrapper should include an <Error> URL with the [ERRORCODE] macro. When the chain fails to resolve (timeout, HTTP error, depth exceeded), the player fires the error URL at the outermost wrapper that has one. Without error tracking, you will have no signal when chains fail.

<Wrapper>
  <AdSystem>My SSP</AdSystem>
  <VASTAdTagURI><![CDATA[https://dsp.example.com/vast]]></VASTAdTagURI>
  <Impression><![CDATA[https://track.ssp.com/impression]]></Impression>
  <!-- [ERRORCODE] is replaced with the IAB VAST error code -->
  <Error><![CDATA[https://track.ssp.com/error?code=[ERRORCODE]]]></Error>
</Wrapper>

Latency impact

Each wrapper hop requires a network round-trip. At 100ms per hop (optimistic), a 4-hop chain adds 400ms before the player can start buffering video. On CTV networks, each hop may take 200–500ms, making a 4-hop chain add 800ms–2s of latency before the ad can even start downloading.

Most CTV platforms have ad request timeout budgets of 3–5 seconds. A chain that takes 2s to resolve leaves very little time for video buffering. The practical recommendation is to keep chains to 2 hops or fewer for reliable CTV delivery.

Debugging wrapper chains

Use the VAST validator to follow and inspect your wrapper chain. It resolves each hop and reports chain depth, per-hop latency, and any validation errors at each level. The VAST tag testing guide covers additional debugging techniques.

Common mistakes checklist

  • Chain exceeds platform limit — the most common cause of unfilled slots in programmatic video. Keep chains to 3 hops or fewer. Monitor chain depth with wrapper error tracking.
  • No error tracking on wrappers — without <Error>URLs on wrappers, chain failures are invisible. You will see low fill rates in reporting with no corresponding errors.
  • followAdditionalWrappers=false on a SSP wrapper — this silently stops chain resolution at that hop. Any downstream wrapper is abandoned. Usually a misconfiguration.
  • allowMultipleAds=false (default) when serving pods — pod ads are silently truncated to one ad. Set allowMultipleAds="true" on all wrappers in a pod chain.
  • HTTP wrapper URLs in an HTTPS chain — browsers and CTV platforms block mixed-content requests. All <VASTAdTagURI> values must be HTTPS.
  • Circular wrapper chains — a wrapper that eventually points back to itself will loop until the chain depth limit is hit and the ad fails. This is almost always a misconfiguration in the ad server.