A player finishes a run with 120 coins. The result screen offers another 120 for watching an ad. They tap. A spinner hangs without explanation, a video finally appears, and after they finish it the balance still reads 120.
At that point, the quality of the ad creative no longer matters. The game has broken a small but explicit contract.
Good rewarded video ad UX treats the experience as a state machine, not as a video slot. The player needs four things: an exact offer before opting in, a harmless way to decline, an honest explanation while the ad is being prepared, and visible proof that the promised reward was granted. The difficult moments are usually outside the video itself.
Google’s current rewarded-ad policy requires a clear disclosure of both the action and the reward before every offer, affirmative opt-in for standard rewarded ads, a non-punitive “no” path, and delivery of the promised reward after the required action. Unity’s rewarded inventory policy makes the publisher—not the ad network—responsible for fulfilling the offer. Google AdMob policy and Unity Rewarded Ad Inventory Policy.
This guide turns those obligations into screens, copy, system states, and test cases. It also includes an original working prototype and a static flow map for accept, cancel, playback error, early close, delayed verification, and successful reward delivery.
Original teaching example: The fictional game “Harbor Run,” its rewards, and the simulated advertiser inside the prototype were created for this article. The demo simulates app and SDK events; it does not load a live ad, reproduce a brand’s interface, or validate any revenue or retention effect.
Rewarded video is a contract with more than one state
The most useful mental model is not “show video, then give coins.” Google’s Rewarded Ads Playbook describes a funnel that moves through the prompt, the ad impression, the reward, and the moment the item is used. Mobile ad SDKs expose still more technical distinctions: loaded, failed to load, shown, failed to show, dismissed, and earned. Google AdMob Rewarded Ads Playbook and Google’s Android rewarded-ad guide.
That means your interface should answer a different player question in every state.
| State | What the player is wondering | What the interface should say or show | System evidence behind it |
|---|---|---|---|
| Offer available | “What do I give, and what do I get?” | “Watch one ad to add +120 coins. 120 → 240.” | A recent availability/readiness check |
| Preparing | “Did my tap work?” | “Preparing video…” with a way back until playback starts | Load or presentation request in progress |
| Playing | “What is happening now?” | The ad SDK’s full-screen experience and its own controls | Ad-start callback |
| Earned, not yet granted | “Did I qualify?” | “Video complete. Confirming your reward…” | Earned/completion signal received |
| Granted | “Did my balance actually change?” | “+120 coins added. New run total: 240.” | Idempotent reward transaction committed |
| Declined or closed early | “Did I lose what I already earned?” | “No bonus added. Your 120 coins are safe.” | No reward transaction created |
| Load or display failure | “Was this my fault?” | “Video unavailable. Your 120 coins are safe.” | Load/show error callback |
| Verification delayed | “Do I have to watch again?” | “Reward pending. We’ll add it when verification arrives.” | Durable pending record tied to this completion |
The player does not need to know your callback names. They do need the interface to tell the truth about which promise has and has not been fulfilled.
Design the offer so the choice is fully legible
A rewarded offer should communicate the action, the quantity, and the destination of the reward in one glance. “Free,” “Claim,” and “2x” can all be visually attractive while still leaving important questions unanswered.
For the Harbor Run result screen, compare these versions:
Weak: “Claim 2x!”
Better: “Watch one ad to add +120 coins. 120 → 240.”
The better version names the cost in time, states the incremental reward, and shows the final result. Its buttons can carry the contract one step further:
- Watch ad · get +120
- Keep 120
“Keep 120” is better than a vague “Cancel” because it explains the consequence of declining. It also prevents the common fear that closing the prompt will discard the base reward.
Google requires rewarded offers to disclose the required action and promised reward clearly and conspicuously before each presentation. Bundles must state the required count, such as three ads for one reward. The same policy says declining cannot interfere with normal app use and prohibits pressure copy such as asking players to watch in order to “support” the publisher. Policies for ad units that offer rewards.
That policy floor is also a useful UX floor. Avoid asymmetric buttons that turn a nominal choice into a trap: a bright, full-width “YES!” paired with a nearly invisible close icon; a decline label that insults the player; or a “not now” route that immediately opens the same offer again.
Treat random rewards as a separate product decision
A mystery chest is not equivalent to a fixed coin grant. Under Google’s policy, a random reward can be used only when the chance-based nature is disclosed before the ad and all possible outcomes—including the possibility of no reward—are easily accessible. Unity’s policy requires conspicuous probability disclosure. Roblox’s current rewarded-video documentation takes a stricter platform-specific position: its video rewards cannot be randomized. Google’s reward requirements, Unity’s inventory policy, and Roblox Creator Hub.
If one implementation must travel across several platforms or networks, a deterministic reward is operationally simpler. When a random reward is worth the added complexity, design and review it as its own offer rather than swapping a chest icon into a fixed-reward flow.
Put the offer at a decision point, not inside active danger
The right placement connects the reward to a goal the player already has. It also freezes or resolves the game state before a full-screen ad takes control.
Roblox’s platform guidance recommends natural breaks such as the end of a level, before a challenge, or after the player runs out of a resource. It also warns that a player’s character should not be harmed while the ad is playing, suggesting safe zones or pausing damage. That advice is platform-specific, but the design principle travels well: accepting an ad should not silently create a new gameplay loss. Roblox rewarded video ads documentation.
Here is a filled placement review for four common offers:
| Placement | Immediate player goal | Safe no-ad outcome | Clear offer | Main UX risk |
|---|---|---|---|---|
| End-of-run result | Bank more of what was just earned | Keep the base result | “Watch one ad to add +120 coins” | “2x” math that changes after caps or rounding |
| Revive after failure | Continue the same attempt | Restart or exit without losing already banked items | “Watch one ad to revive at Checkpoint 3” | A countdown or rare-item loss that makes the choice feel coerced |
| Energy gate | Start another activity now | Wait, use another mode, or leave | “Watch one ad for +10 energy” | The game becoming practically unusable without repeated ads |
| Optional chest | Obtain an extra item | Continue without the chest | Fixed item, or a fully disclosed random table | Odds, platform-policy differences, and reward disappointment |
A rewarded placement can be technically optional while feeling mandatory. A recent r/gamedesign discussion is not representative research, but it captures a useful qualitative warning: several commenters distinguished genuinely optional rewards from games whose progression feels deliberately crippled unless every offer is accepted. Treat that as a hypothesis to test with your own players, not as a population estimate. Reddit discussion, “What’s your opinion on rewarded ads in mobile games?”.
Reward size belongs in the game economy, not in a last-minute ad configuration screen. Unity’s 2021 placement guide recommends modeling the economy as though players claim all available rewarded-video earnings and tying reward value to the economy rather than to fluctuating eCPM. This is vendor guidance rather than independent causal evidence, but it is a sensible planning check: calculate what the reward does to progression, purchases, and scarcity before polishing the button. Unity, “The fundamentals of rewarded video ad placements”.
Design three different waits, not one generic spinner
“Waiting for the ad” can describe three technically and psychologically different moments:
- Preparing the ad: your app is checking availability, loading, or asking the SDK to present.
- Watching the ad: the ad network owns the full-screen experience and completion rules.
- Confirming the reward: your app has a completion signal but still needs to commit or verify the grant.
Use different copy and controls for each one.
1. Preparing: keep context and preserve an exit
Preload before the offer is likely to be accepted. Google’s Android guide explicitly supports caching preloaded ads and notes that its loaded ads expire after one hour; AppLovin exposes readiness, load-failure, and display-failure callbacks and recommends loading the next ad after the current one is hidden. Roblox recommends checking availability close to the intended show moment. These details differ by SDK, so follow the current documentation for each integration rather than inventing one universal cache rule. Google rewarded ads for Android, AppLovin MAX rewarded ads, and Roblox rewarded video ads.
When preparation is still necessary after the tap:
- Disable repeat taps immediately.
- Keep the reward and base result visible.
- Say “Preparing video…” rather than showing a fake playback countdown.
- Allow the player to go back until the full-screen ad starts.
- If the SDK reports no fill or a display failure, end the wait and show a recoverable error.
Do not promise a specific number of seconds unless your product actually controls and measures that interval. A network ad can fail, expire, or take longer on a weak connection. Honest indeterminate feedback is better than a countdown that reaches zero and keeps spinning.
2. Playing: do not compete with the SDK’s controls
Once playback starts, the ad SDK normally owns the close control, progress, audio state, and clickthrough. Avoid drawing a second game-owned close button, reward progress bar, or “almost there” message over the ad. Those layers can conflict with network UI and create the false impression that the player has completed your requirement when the SDK has not.
The game should instead freeze the offer context internally: placement ID, reward type and amount, balance before the offer, and a unique attempt identifier. When the player returns, the game can explain the outcome without reconstructing it from the screen that happened to be visible.
3. Confirming: make the post-video wait explicit
Completion and delivery are not the same event. Replace the generic spinner with copy that reflects the new contract state:
Video complete. Confirming +120 coins…
This tells the player that completion was recorded and another viewing is unnecessary. Persist the pending attempt so leaving the app does not discard it. It also gives your system a clean place to resolve client callbacks, server verification, and duplicate protection.
Do not equate “ad closed” with “reward earned”
A full-screen ad being dismissed only proves that control returned to the app. It does not, by itself, prove that the completion requirement was met.
Google’s Android SDK has separate callbacks for earned rewards and full-screen dismissal. For Google-served ads, the earned callback is called before dismissal, but with mediation the third-party source can determine callback order. AppLovin likewise separates onUserRewarded from onAdHidden. Build the reward flow around the earned event, not around the close event or a timer you started locally. Google rewarded callback ordering and AppLovin rewarded-ad callbacks.
A robust grant pipeline looks like this:
- Create an offer attempt with the promised reward and a unique local ID.
- Present the ad only once for that attempt.
- Mark the attempt eligible when the SDK reports the reward event.
- Grant the reward through one idempotent transaction.
- Store the completed transaction and update the visible balance.
- Ignore or reconcile duplicate callbacks instead of granting twice.
Server-side verification can add protection for valuable rewards. Google’s SSV callbacks include a unique transaction_id and signed parameters. Its documentation recommends a practical tradeoff: grant immediately from the client callback and validate when the server callback arrives for a smoother experience, or wait for verified server delivery when reward validity is critical and delay is acceptable. Google, “Validate server-side verification callbacks”.
AppLovin’s S2S documentation similarly warns that callbacks can be delayed by a few minutes and may be retried. That means a missing callback at the instant the video closes is not necessarily a final failure. AppLovin S2S Rewarded Callback API.
Choose the delivery model deliberately:
| Delivery model | Good fit | Player-facing state | Main operational requirement |
|---|---|---|---|
| Immediate client grant, later server validation | Ordinary soft currency or low-risk boosts | Reward appears immediately | Reconciliation and fraud monitoring |
| Wait for verified server grant | High-value or economy-sensitive rewards | “Reward pending” until confirmation | Durable pending records and delayed-delivery recovery |
| Client eligibility plus idempotent server commit | Most account-based games | Brief “confirming” state, then one grant | Unique transaction key and retry-safe API |
The third pattern is a useful default when you control an account backend. The SDK’s earned event establishes eligibility; your server applies the economic change once. If the app is killed between those steps, the pending attempt survives and can be resolved on the next launch.
Four original flows, with exact screen copy
The downloadable prototype implements the following paths. Each one begins with the same result: Harbor Run has already awarded 120 base coins. The rewarded offer can add another 120, but it cannot take the first 120 away.
Flow A: Accept and receive the reward
Results → Offer accepted → Preparing → Ad starts → Earned → Confirming → Granted
- Offer: “Watch one ad to add +120 coins. 120 → 240.”
- Preparing: “Preparing video… Your run result is saved.”
- Confirming: “Video complete. Confirming +120 coins…”
- Success: “+120 coins added. Run total: 240.”
The success screen shows both the increment and the final total. A balance animation is helpful only after the grant transaction succeeds; animating first and committing later creates a visible lie when the backend fails.
Flow B: Decline without penalty
Results → Keep 120 → Results restored
- Button: “Keep 120”
- Confirmation: “Offer skipped. 120 coins kept.”
No second confirmation dialog is needed. Declining is reversible only in the normal sense that the offer may appear again under your pacing rules; it should not immediately reopen or block the next action.
Flow C: The ad cannot start
Offer accepted → Preparing → Load/show error → Retry or keep base result
- Error title: “Video unavailable”
- Explanation: “The video didn’t start. Your 120 coins are safe.”
- Actions: “Try again” and “Keep 120”
Do not blame the connection unless you have actually diagnosed it. “Video unavailable” covers no fill, expiration, and presentation failure without inventing a cause. A retry should be explicit and bounded by the SDK’s current readiness—not an automatic loop that keeps the player trapped.
Flow D: The video completed, but verification is delayed
Ad earned → Pending record created → Confirmation delayed → Grant arrives once
- Pending title: “Reward pending”
- Explanation: “Your video was completed. We’ll add +120 coins when verification arrives.”
- Reference: “Reward check HR-2407”
- Resolution: “Verified: +120 coins added.”
In production, the reference must identify a durable attempt or transaction that support and reconciliation can retrieve. HR-2407 is the fictional example shown here; the browser prototype models the interaction, not a production support system. Most importantly, the pending screen never asks the player to watch the same ad again.
Open the interactive rewarded-video UX prototype to run the happy path, decline, unavailable-ad, early-close, and delayed-verification scenarios.
Replace vague copy with state-specific copy
| Vague or risky copy | Better copy | What it fixes |
|---|---|---|
| “Claim 2x!” | “Watch one ad to add +120 coins. 120 → 240.” | Names action, increment, and final result |
| “Continue” | “Watch an ad to revive at Checkpoint 3.” | Defines where the player will return |
| “Free chest” | “Watch one ad for one Bronze Chest.” | Removes ambiguity about price and quantity |
| “Loading…” | “Preparing video… You can go back until it starts.” | Explains the current state and available control |
| “Something went wrong” | “The video didn’t start. Your 120 coins are safe.” | States what failed and what was preserved |
| “Reward sent” | “+120 coins added. New balance: 2,480.” | Shows the actual economic result |
| “No reward” | “Ad closed before completion. No bonus was added; 120 coins kept.” | Separates the missing bonus from the base result |
| “Try again” after completion | “Reward pending. No need to watch again.” | Prevents duplicate effort and duplicate-grant risk |
Copy cannot repair a broken transaction model, but it can expose one. If your team cannot fill in the exact amount, condition, preserved base value, and final balance, the offer logic is not ready for production.
Measure the transitions, not just impressions and revenue
An impression tells you that an ad rendered. It does not tell you whether the offer was understood, the ad started promptly, a completion callback arrived, or the reward was delivered. Roblox’s documentation makes a similar denominator distinction by supporting “ad opportunity” tracking separately from completed views. Roblox ad opportunities.
Instrument the state machine with a compact event contract:
| Event | Why it exists | Essential properties |
|---|---|---|
rv_offer_view |
Counts real opportunities | placement, reward type/amount, base value, ad-ready flag |
rv_accept / rv_decline |
Measures the decision | offer ID, UI variant |
rv_load_start / rv_load_fail |
Isolates preparation reliability | network, error class, elapsed time |
rv_ad_start |
Confirms the accepted offer actually began | attempt ID, placement, ad source if available |
rv_ad_earned |
Marks SDK eligibility | attempt ID, callback source |
rv_ad_dismiss |
Records return to the game | earned-before-dismiss flag |
rv_reward_pending |
Exposes verification delay | transaction/reference ID |
rv_reward_granted |
Confirms the promise was fulfilled | amount, balance before/after, grant latency |
rv_reward_duplicate_blocked |
Verifies idempotency protection | transaction ID, duplicate source |
rv_flow_exit |
Shows where play resumed | exit reason and next game action |
From those events, calculate acceptance per offer view, ad-start success per acceptance, preparation latency at the median and tail, earned rate per ad start, reward-grant success per earned event, and earned-to-granted delay. Segment by placement, app version, SDK/mediation version, geography where permitted, and reward type.
Revenue, session length, retention, and purchase behavior belong in the experiment plan, but the prototype does not establish an effect on any of them. Test one meaningful change at a time, preserve an untreated comparison where feasible, and inspect economy outcomes alongside UX failures. A higher acceptance rate is not a win if the no-ad path became punitive or missing-reward reports increased.
Run the failure cases before testing button colors
A rewarded-video QA pass should force the transitions that normal happy-path testing avoids.
| Test | Expected visible result | Expected system result |
|---|---|---|
| Decline from the offer | Base reward remains; flow continues | No ad request and no reward transaction |
| Double-tap accept | One preparation state | One attempt and one show request |
| No ad available | Recoverable error, no blame | No grant; retry only after a new readiness check |
| Display failure after load | Same safe error path | Failed attempt logged; next ad may preload |
| Close before earned callback | “No bonus added; base kept” | No reward grant |
| Earned callback, then dismiss | Brief confirming state, then success | Exactly one grant |
| Dismiss callback before earned callback under mediation | UI waits for resolved outcome rather than assuming failure | State remains open for the valid earned callback/order |
| App backgrounded during playback | Returns to resolved or pending state | Attempt ID preserved |
| App killed after earned but before success screen | Pending or granted result appears on next launch | Durable transaction completes once |
| Delayed SSV callback | “Reward pending; no need to watch again” | Later callback resolves the same transaction |
| Duplicate callback | No second animation or balance increase | Duplicate transaction rejected |
| Localization or large numbers | Amount and final total remain legible | Reward arithmetic unchanged |
Use each network’s test mode or test ad units during development rather than clicking live inventory. Google’s Android guide explicitly warns that using live ads for testing can lead to account suspension. Google rewarded ads for Android.
Then test the interface with real players. Ask them what they expect before tapping, what they think is happening during preparation, whether they believe declining is safe, and how certain they are that the reward arrived. Those questions validate the contract more directly than asking whether the colors look appealing.
The part you control is everything around the video
The ad network controls most of the playback. The game controls the promise that precedes it, the transition into it, the interpretation of its callbacks, and the economic change afterward.
Make the offer precise. Keep “no” safe. Distinguish preparation from playback and verification. Treat earned, dismissed, pending, and granted as different states. Record one durable transaction and grant it once. When the player returns, show the exact result rather than a celebratory screen that may or may not match the ledger.
That is rewarded video UX: not persuading someone to tolerate an interruption, but keeping a clear value exchange trustworthy from the first button to the updated balance.
Sources
- “Policies for ad units that offer rewards” — Google AdMob Help. Accessed September 9, 2026.
- “Rewarded ads” (Android) — Google for Developers. Last updated September 3, 2026; accessed September 9, 2026.
- “Rewarded interstitial ads” (Android) — Google for Developers. Last updated September 3, 2026; accessed September 9, 2026.
- “Validate server-side verification (SSV) callbacks” — Google for Developers. Last updated September 3, 2026; accessed September 9, 2026.
- “Google AdMob Rewarded Ads Playbook” — Google AdMob. Accessed September 9, 2026.
- “Rewarded ads” (Android/Amazon) — AppLovin MAX Support Center. Accessed September 9, 2026.
- “S2S Rewarded Callback API” — AppLovin MAX Support Center. Accessed September 9, 2026.
- “Rewarded video ads” — Roblox Creator Hub. Accessed September 9, 2026.
- “Rewarded Ad Inventory Policy” — Unity. Last updated December 4, 2024; accessed September 9, 2026.
- “The fundamentals of rewarded video ad placements” — Unity. Published December 23, 2021; accessed September 9, 2026.
- “What’s your opinion on rewarded ads in mobile games?” — r/gamedesign on Reddit. Accessed September 9, 2026; used only as non-representative qualitative input.




