Overview
Rewarded ads are full-screen ads where users receive rewards after watching the entire ad. Use them to provide rewards such as in-game items, additional content, etc.Key Features
- Full-screen ads that cover the entire screen
- Video ad support
- Reward event callbacks
- Reward type and amount information
- Separate load and show for flexible timing control
Use the test unit ID in development:
PUBLIC_TEST_UNIT_ID_REWARDEDAdropRewardedAd
Constructor
AdropRewardedAd({
required String unitId,
AdropRewardedListener? listener,
})
| Parameter | Type | Required | Description |
|---|---|---|---|
unitId | String | Y | Unit ID created in the Ad Control Console |
listener | AdropRewardedListener | N | Ad event listener |
Properties
| Property | Type | Description |
|---|---|---|
isLoaded | bool | Whether the ad is loaded |
unitId | String | Ad unit ID |
creativeId | String | Creative ID |
txId | String | Transaction ID |
campaignId | String | Campaign ID |
destinationURL | String | Destination URL |
browserTarget | BrowserTarget? | Browser target (external or internal) |
serverSideVerificationOptions | ServerSideVerificationOptions? | Server-side verification options (userId, customData) |
Methods
| Method | Return Type | Description |
|---|---|---|
load() | Future<void> | Loads the ad |
show() | Future<void> | Shows the ad on screen |
dispose() | Future<void> | Releases resources |
Basic Usage
import 'package:flutter/material.dart';
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart';
class RewardedExample extends StatefulWidget {
const RewardedExample({super.key});
@override
State<RewardedExample> createState() => _RewardedExampleState();
}
class _RewardedExampleState extends State<RewardedExample> {
bool isLoaded = false;
AdropRewardedAd? rewardedAd;
@override
void initState() {
super.initState();
_createRewardedAd();
}
void _createRewardedAd() {
rewardedAd = AdropRewardedAd(
unitId: 'YOUR_UNIT_ID',
listener: AdropRewardedListener(
onAdReceived: (ad) {
debugPrint('Rewarded ad loaded: ${ad.creativeId}');
setState(() {
isLoaded = true;
});
},
onAdFailedToReceive: (ad, errorCode) {
debugPrint('Rewarded ad failed to load: $errorCode');
},
onAdClicked: (ad) {
debugPrint('Rewarded ad clicked');
},
onAdDidPresentFullScreen: (ad) {
debugPrint('Rewarded ad presented');
},
onAdDidDismissFullScreen: (ad) {
debugPrint('Rewarded ad dismissed');
},
onAdFailedToShowFullScreen: (ad, errorCode) {
debugPrint('Rewarded ad failed to show: $errorCode');
},
onAdEarnRewardHandler: (ad, type, amount) {
debugPrint('Reward earned: type=$type, amount=$amount');
_giveReward(type, amount);
},
),
);
}
void _giveReward(int type, int amount) {
// Implement reward logic
// e.g., coins, items, extra lives, etc.
}
void loadAd() {
rewardedAd?.load();
}
void showAd() {
if (isLoaded) {
rewardedAd?.show();
}
}
@override
void dispose() {
rewardedAd?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Rewarded Ad Example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: loadAd,
child: const Text('Load Ad'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: isLoaded ? showAd : null,
child: const Text('Watch Ad for Reward'),
),
],
),
),
);
}
}
AdropRewardedListener
A listener for handling rewarded ad events.Callbacks
AdropRewardedListener(
onAdReceived: (AdropAd ad) {
// Ad loaded successfully
},
onAdClicked: (AdropAd ad) {
// Ad clicked
},
onAdImpression: (AdropAd ad) {
// Ad impression
},
onAdWillPresentFullScreen: (AdropAd ad) {
// Ad about to be presented (iOS only)
},
onAdDidPresentFullScreen: (AdropAd ad) {
// Ad presented
},
onAdWillDismissFullScreen: (AdropAd ad) {
// Ad about to be dismissed (iOS only)
},
onAdDidDismissFullScreen: (AdropAd ad) {
// Ad dismissed
},
onAdFailedToReceive: (AdropAd ad, AdropErrorCode errorCode) {
// Ad failed to load
},
onAdFailedToShowFullScreen: (AdropAd ad, AdropErrorCode errorCode) {
// Ad failed to show
},
onAdEarnRewardHandler: (AdropAd ad, int type, int amount) {
// Reward earned
},
)
Callback Descriptions
| Callback | Description |
|---|---|
onAdReceived | Called when ad loads successfully |
onAdClicked | Called when ad is clicked |
onAdImpression | Called when ad is displayed |
onAdWillPresentFullScreen | Called before ad is presented (iOS only) |
onAdDidPresentFullScreen | Called after ad is presented |
onAdWillDismissFullScreen | Called before ad is dismissed (iOS only) |
onAdDidDismissFullScreen | Called after ad is dismissed |
onAdFailedToReceive | Called when ad fails to load |
onAdFailedToShowFullScreen | Called when ad fails to show |
onAdEarnRewardHandler | Called when reward is earned |
Reward Handling
Reward Callback
Process reward information in theonAdEarnRewardHandler callback.
onAdEarnRewardHandler: (ad, type, amount) {
debugPrint('Reward earned: type=$type, amount=$amount');
// Handle based on reward type
switch (type) {
case 1:
// Coin reward
_addCoins(amount);
break;
case 2:
// Item reward
_addItem(amount);
break;
default:
// Default reward
_giveDefaultReward(amount);
}
}
Reward Timing
Rewards must be granted in the
onAdEarnRewardHandler callback. This callback is not called if the ad is dismissed before being fully watched.class RewardManager {
bool _rewardEarned = false;
void setupRewardedAd() {
rewardedAd = AdropRewardedAd(
unitId: 'YOUR_UNIT_ID',
listener: AdropRewardedListener(
onAdEarnRewardHandler: (ad, type, amount) {
// Set reward flag
_rewardEarned = true;
},
onAdDidDismissFullScreen: (ad) {
// Check reward after ad is dismissed
if (_rewardEarned) {
_giveReward();
_rewardEarned = false;
}
},
),
);
}
}
Ad Recreation
Rewarded ads are one-time use. Once shown, an ad cannot be displayed again, so you must recreate the instance to load a new ad.class _RewardedState extends State<RewardedWidget> {
bool isLoaded = false;
bool isShown = false;
AdropRewardedAd? rewardedAd;
@override
void initState() {
super.initState();
_createRewardedAd();
}
void _createRewardedAd() {
rewardedAd?.dispose();
rewardedAd = AdropRewardedAd(
unitId: 'YOUR_UNIT_ID',
listener: AdropRewardedListener(
onAdReceived: (ad) {
setState(() {
isLoaded = true;
});
},
onAdDidPresentFullScreen: (ad) {
setState(() {
isShown = true;
});
},
onAdEarnRewardHandler: (ad, type, amount) {
_giveReward(type, amount);
},
onAdDidDismissFullScreen: (ad) {
// Prepare new ad after dismissal
_createRewardedAd();
rewardedAd?.load();
},
),
);
setState(() {
isLoaded = false;
isShown = false;
});
}
@override
void dispose() {
rewardedAd?.dispose();
super.dispose();
}
}
Error Handling
class _RewardedState extends State<RewardedWidget> {
bool isLoaded = false;
AdropErrorCode? errorCode;
AdropRewardedAd? rewardedAd;
void _createRewardedAd() {
rewardedAd = AdropRewardedAd(
unitId: 'YOUR_UNIT_ID',
listener: AdropRewardedListener(
onAdReceived: (ad) {
setState(() {
isLoaded = true;
errorCode = null;
});
},
onAdFailedToReceive: (ad, error) {
setState(() {
isLoaded = false;
errorCode = error;
});
_handleError(error);
},
onAdFailedToShowFullScreen: (ad, error) {
setState(() {
errorCode = error;
});
_handleError(error);
},
),
);
}
void _handleError(AdropErrorCode error) {
switch (error) {
case AdropErrorCode.network:
debugPrint('Network error occurred.');
break;
case AdropErrorCode.adNoFill:
debugPrint('No ads available.');
break;
case AdropErrorCode.adShown:
debugPrint('Ad already shown.');
break;
default:
debugPrint('Error: ${error.code}');
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: rewardedAd?.load,
child: const Text('Load Ad'),
),
ElevatedButton(
onPressed: isLoaded ? rewardedAd?.show : null,
child: const Text('Watch Ad for Reward'),
),
if (errorCode != null)
Text(
'Error: ${errorCode?.code}',
style: const TextStyle(color: Colors.red),
),
],
);
}
}
Best Practices
1. Preload Ads
Preload ads so they can be shown immediately when users request rewards.class GameScreen extends StatefulWidget {
@override
State<GameScreen> createState() => _GameScreenState();
}
class _GameScreenState extends State<GameScreen> {
AdropRewardedAd? rewardedAd;
bool isAdReady = false;
@override
void initState() {
super.initState();
_preloadAd();
}
void _preloadAd() {
rewardedAd = AdropRewardedAd(
unitId: 'YOUR_UNIT_ID',
listener: AdropRewardedListener(
onAdReceived: (ad) {
setState(() {
isAdReady = true;
});
},
onAdEarnRewardHandler: (ad, type, amount) {
_giveReward(type, amount);
},
onAdDidDismissFullScreen: (ad) {
// Preload next ad
_preloadAd();
},
),
);
rewardedAd?.load();
}
void showRewardedAd() {
if (isAdReady) {
rewardedAd?.show();
setState(() {
isAdReady = false;
});
}
}
@override
void dispose() {
rewardedAd?.dispose();
super.dispose();
}
}
2. Inform Users About Rewards
Clearly communicate the rewards users can receive before watching the ad.void showRewardDialog() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Get Reward'),
content: const Text('Watch an ad to receive 100 coins!'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
showRewardedAd();
},
child: const Text('Watch Ad'),
),
],
),
);
}
3. Show Ad Availability
Only enable the reward button when an ad is ready.Widget buildRewardButton() {
return ElevatedButton.icon(
onPressed: isAdReady ? showRewardedAd : null,
icon: const Icon(Icons.play_circle_outline),
label: Text(isAdReady ? 'Watch Ad for Reward' : 'Loading Ad...'),
style: ElevatedButton.styleFrom(
backgroundColor: isAdReady ? Colors.green : Colors.grey,
),
);
}
4. Reward Reliability
It’s recommended to verify rewards on the server.onAdEarnRewardHandler: (ad, type, amount) async {
try {
// Request reward from server
await _api.grantReward(
userId: currentUserId,
transactionId: ad.txId,
rewardType: type,
amount: amount,
);
// Update local state
_updateLocalBalance(amount);
} catch (e) {
debugPrint('Failed to grant reward: $e');
// Retry or handle error
}
}
5. Resource Management
Always dispose unused ad instances.@override
void dispose() {
rewardedAd?.dispose();
super.dispose();
}
Complete Example
import 'package:flutter/material.dart';
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart';
class RewardedAdPage extends StatefulWidget {
const RewardedAdPage({super.key});
@override
State<RewardedAdPage> createState() => _RewardedAdPageState();
}
class _RewardedAdPageState extends State<RewardedAdPage> {
bool isLoaded = false;
bool isLoading = false;
bool isShown = false;
int coins = 0;
AdropErrorCode? errorCode;
AdropRewardedAd? rewardedAd;
@override
void initState() {
super.initState();
_createRewardedAd();
}
void _createRewardedAd() {
rewardedAd?.dispose();
rewardedAd = AdropRewardedAd(
unitId: 'PUBLIC_TEST_UNIT_ID_REWARDED', // Test unit ID
listener: AdropRewardedListener(
onAdReceived: (ad) {
debugPrint('Ad loaded');
debugPrint('Creative ID: ${ad.creativeId}');
debugPrint('Campaign ID: ${ad.campaignId}');
setState(() {
isLoaded = true;
isLoading = false;
errorCode = null;
});
},
onAdClicked: (ad) {
debugPrint('Ad clicked: ${ad.destinationURL}');
},
onAdImpression: (ad) {
debugPrint('Ad impression: ${ad.creativeId}');
},
onAdWillPresentFullScreen: (ad) {
debugPrint('Ad will present');
},
onAdDidPresentFullScreen: (ad) {
debugPrint('Ad presented');
setState(() {
isShown = true;
});
},
onAdWillDismissFullScreen: (ad) {
debugPrint('Ad will dismiss');
},
onAdDidDismissFullScreen: (ad) {
debugPrint('Ad dismissed');
// Prepare new ad
_createRewardedAd();
},
onAdFailedToReceive: (ad, error) {
debugPrint('Ad failed to load: $error');
setState(() {
isLoaded = false;
isLoading = false;
errorCode = error;
});
},
onAdFailedToShowFullScreen: (ad, error) {
debugPrint('Ad failed to show: $error');
setState(() {
errorCode = error;
});
},
onAdEarnRewardHandler: (ad, type, amount) {
debugPrint('Reward earned: type=$type, amount=$amount');
setState(() {
coins += amount;
});
_showRewardNotification(amount);
},
),
);
setState(() {
isLoaded = false;
isShown = false;
errorCode = null;
});
}
void loadAd() {
setState(() {
isLoading = true;
errorCode = null;
});
rewardedAd?.load();
}
void showAd() {
if (isLoaded) {
rewardedAd?.show();
}
}
void _showRewardNotification(int amount) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('You earned $amount coins!'),
backgroundColor: Colors.green,
duration: const Duration(seconds: 2),
),
);
}
@override
void dispose() {
rewardedAd?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Rewarded Ad Example'),
),
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Coin display
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.amber.shade100,
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.monetization_on, color: Colors.amber),
const SizedBox(width: 8),
Text(
'$coins Coins',
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
],
),
),
const SizedBox(height: 32),
// Load button
ElevatedButton(
onPressed: isLoading ? null : loadAd,
child: Text(isLoading ? 'Loading...' : 'Load Ad'),
),
const SizedBox(height: 16),
// Show button
ElevatedButton.icon(
onPressed: isLoaded ? showAd : null,
icon: const Icon(Icons.play_circle_outline),
label: const Text('Watch Ad for Reward'),
style: ElevatedButton.styleFrom(
backgroundColor: isLoaded ? Colors.green : Colors.grey,
),
),
const SizedBox(height: 16),
// Reset button
TextButton(
onPressed: (isShown || errorCode != null)
? () => _createRewardedAd()
: null,
child: const Text('Reset'),
),
const SizedBox(height: 24),
// Status display
Text('Loaded: ${isLoaded ? "Yes" : "No"}'),
Text('Shown: ${isShown ? "Yes" : "No"}'),
// Error display
if (errorCode != null) ...[
const SizedBox(height: 16),
Text(
'Error: ${errorCode?.code}',
style: const TextStyle(color: Colors.red),
),
],
],
),
),
),
);
}
}
Server-Side Verification (SSV)
Server-side verification allows you to securely verify reward grants on your server. SetServerSideVerificationOptions to include userId and customData in the server-to-server callback when the ad is loaded.
To receive SSV callbacks on your server, register a callback URL in the console: [Management] > [Integrations] > Reward Ad SSV. The
userId and customData set here are included in the encrypted payload sent to that URL. See the Reward Ad SSV guide for payload decryption and setup.Setup
SetserverSideVerificationOptions before calling load().
final rewardedAd = AdropRewardedAd(
unitId: 'YOUR_UNIT_ID',
listener: AdropRewardedListener(
onAdReceived: (ad) {
setState(() {
isLoaded = true;
});
},
onAdEarnRewardHandler: (ad, type, amount) {
debugPrint('Reward earned: type=$type, amount=$amount');
// Verify reward on server
},
),
);
// Set SSV options before calling load()
rewardedAd.serverSideVerificationOptions = ServerSideVerificationOptions(
userId: 'user_123',
customData: 'level_5_reward',
);
await rewardedAd.load();
ServerSideVerificationOptions
| Property | Type | Description |
|---|---|---|
userId | String? | User identifier for server-side verification |
customData | String? | Custom data string to include in the server callback |
Full Example
class _RewardedSSVState extends State<RewardedSSVWidget> {
bool isLoaded = false;
AdropRewardedAd? rewardedAd;
void _createRewardedAd() {
rewardedAd?.dispose();
rewardedAd = AdropRewardedAd(
unitId: 'YOUR_UNIT_ID',
listener: AdropRewardedListener(
onAdReceived: (ad) {
setState(() {
isLoaded = true;
});
},
onAdEarnRewardHandler: (ad, type, amount) {
// Verify reward on server
_verifyRewardOnServer(
transactionId: ad.txId,
rewardType: type,
amount: amount,
);
},
onAdDidDismissFullScreen: (ad) {
// Prepare next ad
_createRewardedAd();
rewardedAd?.load();
},
),
);
// Set SSV options
rewardedAd!.serverSideVerificationOptions = ServerSideVerificationOptions(
userId: currentUserId,
customData: 'reward_context_data',
);
}
Future<void> _verifyRewardOnServer({
required String transactionId,
required int rewardType,
required int amount,
}) async {
// Send reward verification request to server
try {
await api.verifyReward(
transactionId: transactionId,
rewardType: rewardType,
amount: amount,
);
_updateLocalBalance(amount);
} catch (e) {
debugPrint('Reward verification failed: $e');
}
}
@override
void dispose() {
rewardedAd?.dispose();
super.dispose();
}
}
serverSideVerificationOptions must be set before calling load(). Options set after load() will not be applied to that ad request.Backfill Ads
When backfill ads are enabled, backfill ads are automatically loaded when direct ads are unavailable. You can handle backfill-related errors using the error code.rewardedAd = AdropRewardedAd(
unitId: 'YOUR_UNIT_ID',
listener: AdropRewardedListener(
onAdReceived: (ad) {
debugPrint('Ad loaded: ${ad.creativeId}');
},
onAdFailedToReceive: (ad, errorCode) {
switch (errorCode) {
case AdropErrorCode.adNoFill:
debugPrint('No direct ad available');
break;
case AdropErrorCode.backfillNoFill:
debugPrint('No backfill ad available either');
break;
default:
debugPrint('Ad load failed: ${errorCode.code}');
}
},
),
);
To use backfill ads, add the backfill dependency to native platforms. See Getting Started.
Next Steps
Popup Ads
Implement popup-style ads
Targeting
Set up targeting for personalized ads
Reference
Check types, methods, and error codes