A player just lost on level 10 — spent 15 minutes, frustration, and the urge to quit. Properly placed Rewarded Ads turn that frustration into revenue without loyalty loss. But incorrect integration breaks game economy and reduces retention. We have been doing rewarded integrations for 5+ years, delivered 30+ projects for iOS and Android — from hyper-casual to RPG. One case: after configuring continue-after-fail, retention grew by 12%, and eCPM increased by 25%. Average eCPM growth after our tuning is 25-40% (e.g., from $6 to $9 for one project). Let's break down the technical nuances and pitfalls.
How to choose placements for Rewarded Ads?
Placement is a point in the game loop where the player has a need they are willing to "pay" for with an ad view. The most effective:
-
Continue after fail — 30–50% conversion provided the player hasn't seen an ad on that screen before. Show after
onGameOver, before the results screen. Limit: 1–2 per attempt. - Daily bonus multiplier — "watch ad — get x3 daily reward". Doesn't break balance, conversion is consistently high.
- Extra currency / chest unlock — a specific offer: "+50 gems" instead of "bonus". Works in the main menu or after a level.
| Placement | Conversion | Impact on Retention | Recommended Limit |
|---|---|---|---|
| Continue after fail | 30–50% | Neutral (with limit) | 1–2 per attempt |
| Daily bonus multiplier | 20–35% | Positive | 1 per day |
| Extra currency | 15–25% | Neutral | 3–5 per day |
How to technically integrate rewarded on Unity?
We use AdMob (Google Mobile Ads) or IronSource (LevelPlay) SDK. For AdMob initialization:
private RewardedAd rewardedAd; public void LoadRewardedAd() { var adUnitId = Application.platform == RuntimePlatform.Android ? "ca-app-pub-xxx/yyy" : "ca-app-pub-xxx/zzz"; RewardedAd.Load(adUnitId, new AdRequest(), (ad, error) => { if (error != null) { Debug.LogWarning($"Rewarded load failed: {error}"); return; } rewardedAd = ad; RegisterRewardedAdEvents(rewardedAd); }); } private void RegisterRewardedAdEvents(RewardedAd ad) { ad.OnAdFullScreenContentClosed += () => { LoadRewardedAd(); }; } public void ShowRewardedAd(System.Action<int> onRewarded) { if (rewardedAd == null || !rewardedAd.CanShowAd()) { Debug.Log("Rewarded not ready"); return; } rewardedAd.Show(reward => { onRewarded?.Invoke(reward.Amount); }); } IronSource (LevelPlay) requires calling IronSource.Agent.loadRewardedVideo() beforehand, and show the button only when IronSource.Agent.isRewardedVideoAvailable() == true.
void Start() { IronSource.Agent.loadRewardedVideo(); } public void OnShowRewardedClicked() { if (IronSource.Agent.isRewardedVideoAvailable()) { IronSource.Agent.showRewardedVideo(); } } private void OnRewardedVideoAdRewarded(IronSourcePlacement placement) { int rewardAmount = placement.getRewardAmount(); // grant reward } | SDK | SSV Support | Integration Ease | eCPM (avg) |
|---|---|---|---|
| AdMob | + (ECDSA) | Medium | $8-12 |
| Unity Ads | + | Easy | $6-10 |
| IronSource | + (LevelPlay) | Hard (waterfall config needed) | $10-15 |
Why is server-side verification (SSV) mandatory?
If rewarded gives hard currency (gems, crystals) — without SSV, rewards are cheated with tools like Frida in minutes. AdMob SSV processes callback faster than IronSource, reducing grant delay by 200 ms. Scheme:
- Client passes
userIdand a uniquenonceincustomDatawhen requesting an ad. - AdMob/IronSource include them in the SSV callback to your backend with ECDSA signature.
- Server verifies signature, nonce uniqueness (so one callback cannot pass twice), and grants currency.
Client implementation — 0.5 day, server part — 1 day with testing.
Example SSV callback handler in Python
from flask import Flask, request from ecdsa import VerifyingKey import json app = Flask(__name__) @app.route('/ssv_callback', methods=['POST']) def ssv_callback(): data = request.json signature = data['signature'] payload = data['payload'] vk = VerifyingKey.from_pem(open('public_key.pem').read()) if vk.verify(signature, payload.encode()): # Check nonce in Redis return 'OK', 200 return 'Invalid signature', 400 What impression limits to set?
Limits must be on the server, not just on the client (PlayerPrefs resets). In an MMO project, we set limits via Redis to guarantee nonce uniqueness even at high RPS. Typical: 5-10 rewarded/day for currency, 1-2/day for continue. A hard limit kills revenue, a soft limit destroys economy. We recommend starting with 8 rewarded/day and A/B test steps of ±2. A/B testing helps balance revenue and economy without risk.
How we integrate rewarded ads: step-by-step process
- Audit current integration (if any) and recommendations to increase eCPM.
- Select placements for your game economy.
- Implementation on Unity (AdMob, IronSource) or native SDKs (iOS/Android).
- Set up SSV backend (any stack: Node.js, Python, Go).
- A/B test placements and limits.
- Documentation and 1 month support.
What you get as a result
After completion, you receive:
- Working rewarded placements with optimized show timing.
- Server-side SSV verification with cheat protection.
- Documentation for key scripts and configs.
- Access to backend code for self-modification.
- 1 month of technical support and consultation.
Estimated timelines
Basic integration with 2-3 placements and limits — from 2 days. With SSV and server-side reward logic — from 3 days. Cost is calculated individually.
Order a free audit of your current integration — we will assess your project. Contact us for a consultation.







