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
| Initiation | User opt-in (tap "Watch ad for reward") |
| Skip | None — omit skipoffset |
| Key tracking event | complete — triggers reward delivery |
| Typical duration | 15–30s (some platforms allow up to 60s) |
| Common environments | Mobile 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:
- User taps "Watch ad for reward"
- App requests a rewarded VAST tag from your ad server
- SDK loads and plays the video to 100%
completetracking URL fires to your server- App SDK fires
onRewardEarnedcallback to your app - 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.