vastlint

Rewarded video VAST ads

A rewarded video ad is a user-initiated linear ad that a viewer opts into in exchange for an in-app or in-game reward (extra lives, coins, premium content, etc.). Because the viewer actively chooses to watch, rewarded ads must play to completion — no skip button is shown. Completion rates are typically 90–95%.

In VAST XML, a rewarded ad is a non-skippable linear creative with specific tracking requirements. The rewarded consent and reward delivery logic live in the app or SDK, not in the VAST tag itself.

Quick reference

InitiationUser opt-in (tap "Watch ad for reward")
SkipNone — omit skipoffset
Key tracking eventcomplete — triggers reward delivery
Typical duration15–30s (some platforms allow up to 60s)
Common environmentsMobile apps, games, OTT/CTV apps

VAST structure for rewarded video

A rewarded ad is structurally identical to a standard non-skippable linear. The critical differences are in how the app or SDK uses it: the SDK fires the reward callback on the complete tracking event, and the app does not show a close or skip button until completion (or until a timeout configured by the publisher).

<VAST version="4.2">
  <Ad id="1">
    <InLine>
      <AdSystem>My Ad Server</AdSystem>
      <AdTitle>Rewarded Video Ad</AdTitle>
      <Impression id="imp1"><![CDATA[https://track.example.com/impression]]></Impression>
      <UniversalAdId idRegistry="Ad-ID">RWRD5678</UniversalAdId>
      <Creatives>
        <Creative id="creative1" sequence="1">
          <Linear>
            <!-- No skipoffset — user must watch to completion -->
            <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>
              <!-- complete fires when reward is earned -->
              <Tracking event="complete"><![CDATA[https://track.example.com/complete]]></Tracking>
            </TrackingEvents>
            <VideoClicks>
              <ClickThrough><![CDATA[https://example.com/landing]]></ClickThrough>
              <ClickTracking><![CDATA[https://track.example.com/click]]></ClickTracking>
            </VideoClicks>
            <MediaFiles>
              <MediaFile delivery="progressive" type="video/mp4"
                width="1920" height="1080" bitrate="2500">
                <![CDATA[https://cdn.example.com/rewarded-1080p.mp4]]>
              </MediaFile>
              <MediaFile delivery="progressive" type="video/mp4"
                width="1280" height="720" bitrate="1500">
                <![CDATA[https://cdn.example.com/rewarded-720p.mp4]]>
              </MediaFile>
              <MediaFile delivery="progressive" type="video/mp4"
                width="854" height="480" bitrate="800">
                <![CDATA[https://cdn.example.com/rewarded-480p.mp4]]>
              </MediaFile>
            </MediaFiles>
          </Linear>
        </Creative>
      </Creatives>
    </InLine>
  </Ad>
</VAST>

The complete event and reward delivery

The complete tracking event is the signal that the viewer watched the full ad. In a rewarded implementation, the app SDK listens for this event and triggers the reward callback. The sequence is:

  1. User taps "Watch ad for reward"
  2. App requests a rewarded VAST tag from your ad server
  3. SDK loads and plays the video to 100%
  4. complete tracking URL fires to your server
  5. App SDK fires onRewardEarned callback to your app
  6. App grants the reward

If the complete URL is missing or returns an error, most SDKs will still fire the callback (the complete event is best-effort). But buyers tracking completion-based billing will not count the impression. Always include complete.

AdServingId for deduplication

In rewarded environments, the same user may be served the same ad multiple times within a session. Use <AdServingId> (VAST 4.1+) to provide a unique per-impression identifier that the SDK can use for server-side deduplication and frequency capping.

<InLine>
  <AdSystem>My Ad Server</AdSystem>
  <AdTitle>Rewarded Video Ad</AdTitle>
  <!-- Unique per-impression ID for deduplication -->
  <AdServingId>ad-impression-uuid-here</AdServingId>
  <Impression>...</Impression>
  ...
</InLine>

Orientation and aspect ratio

Mobile rewarded ads are often served in a fullscreen interstitial context. Provide both landscape (16:9) and portrait (9:16) MediaFile renditions if your creative supports it, or ensure your 16:9 creative is set to maintainAspectRatio="true" and scalable="true" so the player can letterbox it correctly.

<!-- 16:9 landscape — will be letterboxed in portrait if scalable -->
<MediaFile delivery="progressive" type="video/mp4"
  width="1920" height="1080" bitrate="2500"
  scalable="true" maintainAspectRatio="true">
  <![CDATA[https://cdn.example.com/rewarded-landscape.mp4]]>
</MediaFile>

Google IMA SDK rewarded behaviour

When using Google IMA SDK for rewarded ads, the SDK exposes a RewardedAd class and fires a REWARDED event (separate from the VAST complete pixel). The VAST tag structure is the same as any non-skippable linear — IMA SDK handles the reward callback logic, not VAST. Ensure your VAST tag has a valid complete tracking URL so your ad server can measure completions server-side.

Common mistakes checklist

  • Missing complete tracking event — this is the most critical event for rewarded ads. Without it, your ad server cannot verify completions.
  • skipoffset accidentally set — a rewarded ad with a skip button defeats the format entirely and will be rejected by most rewarded SDKs.
  • Duration too long for platform — most rewarded SDKs enforce a maximum (commonly 30s or 60s). Exceeding it causes the ad to be skipped or cut off early.
  • Only one MediaFile rendition — on mobile, bandwidth varies significantly. Provide 480p, 720p, and 1080p renditions for adaptive selection.
  • Using VPAID for rewarded — VPAID is blocked in all mobile and CTV environments. Use native VAST linear for rewarded.