Skip to main content

Overview

Rewarded ads are full-screen video ads that provide rewards such as in-game currency, lives, or hints when users watch the video to completion.

Key Features

  • Full-screen video ads
  • Rewards only provided when user completely watches the ad
  • User chooses to watch ad (e.g., “Watch video to get lives” button)
  • Configurable reward type and amount
Use test unit ID in development environment: PUBLIC_TEST_UNIT_ID_REWARDED

Implementation Steps

Implement rewarded ads in the following steps:
  1. Create AdropRewardedAd Instance - Create ad object with unit ID
  2. Set Delegate - Set delegate to handle ad events
  3. Load Ad - Request ad using load() method
  4. Show Ad - Display ad using show() method and handle rewards

Swift Example

Basic Implementation

import UIKit
import AdropAds

class RewardedViewController: UIViewController {
    private var rewardedAd: AdropRewardedAd?

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1. Create AdropRewardedAd instance
        rewardedAd = AdropRewardedAd(unitId: "YOUR_UNIT_ID")

        // 2. Set delegate
        rewardedAd?.delegate = self

        // 3. Load ad
        rewardedAd?.load()
    }

    @IBAction func showRewardedAdButtonTapped(_ sender: UIButton) {
        // Check if ad is loaded
        guard rewardedAd?.isLoaded == true else {
            print("Ad not loaded yet")
            return
        }

        // 4. Show ad and handle reward
        rewardedAd?.show(fromRootViewController: self) { [weak self] type, amount in
            // Grant reward
            print("Reward earned - Type: \(type), Amount: \(amount)")
            self?.grantReward(type: type, amount: amount)
        }
    }

    private func grantReward(type: Int, amount: Int) {
        // Grant reward to user
        // Example: Add game currency, restore lives, etc.

        // Important: It is recommended to verify rewards on your server
        // Processing rewards only on the client side allows cheating
    }
}

// MARK: - AdropRewardedAdDelegate
extension RewardedViewController: AdropRewardedAdDelegate {
    // Required: Ad received successfully
    func onAdReceived(_ ad: AdropRewardedAd) {
        print("Ad received")
        // Enable watch ad button, etc.
    }

    // Required: Ad receive failed
    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        print("Ad receive failed: \(errorCode)")
        // Keep watch ad button disabled, etc.
    }

    // Optional: Ad impression
    func onAdImpression(_ ad: AdropRewardedAd) {
        print("Ad impression")
    }

    // Optional: Ad clicked
    func onAdClicked(_ ad: AdropRewardedAd) {
        print("Ad clicked")
    }

    // Optional: Before showing full screen ad
    func onAdWillPresentFullScreen(_ ad: AdropRewardedAd) {
        print("About to show ad")
        // Pause background music, etc.
    }

    // Optional: After showing full screen ad
    func onAdDidPresentFullScreen(_ ad: AdropRewardedAd) {
        print("Ad shown")
    }

    // Optional: Before dismissing full screen ad
    func onAdWillDismissFullScreen(_ ad: AdropRewardedAd) {
        print("About to dismiss ad")
    }

    // Optional: After dismissing full screen ad
    func onAdDidDismissFullScreen(_ ad: AdropRewardedAd) {
        print("Ad dismissed")
        // Resume background music, etc.

        // Preload next ad
        rewardedAd?.load()
    }

    // Optional: Ad show failed
    func onAdFailedToShowFullScreen(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        print("Ad show failed: \(errorCode)")
    }
}

SwiftUI Example

import SwiftUI
import AdropAds

class RewardedAdViewModel: NSObject, ObservableObject, AdropRewardedAdDelegate {
    @Published var isAdReady = false
    @Published var showingAlert = false
    @Published var alertMessage = ""

    private var rewardedAd: AdropRewardedAd?

    override init() {
        super.init()
        loadAd()
    }

    func loadAd() {
        rewardedAd = AdropRewardedAd(unitId: "YOUR_UNIT_ID")
        rewardedAd?.delegate = self
        rewardedAd?.load()
    }

    func showAd() {
        guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
              let rootViewController = windowScene.windows.first?.rootViewController else {
            return
        }

        rewardedAd?.show(fromRootViewController: rootViewController) { [weak self] type, amount in
            self?.alertMessage = "Reward earned! Type: \(type), Amount: \(amount)"
            self?.showingAlert = true
            self?.grantReward(type: type, amount: amount)
        }
    }

    private func grantReward(type: Int, amount: Int) {
        // Grant reward
        print("Granting reward - Type: \(type), Amount: \(amount)")
    }

    // MARK: - AdropRewardedAdDelegate

    func onAdReceived(_ ad: AdropRewardedAd) {
        isAdReady = true
    }

    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        isAdReady = false
        alertMessage = "Ad load failed: \(errorCode)"
        showingAlert = true
    }

    func onAdDidDismissFullScreen(_ ad: AdropRewardedAd) {
        isAdReady = false
        // Preload next ad
        loadAd()
    }

    func onAdFailedToShowFullScreen(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        alertMessage = "Ad show failed: \(errorCode)"
        showingAlert = true
    }
}

struct RewardedAdView: View {
    @StateObject private var viewModel = RewardedAdViewModel()

    var body: some View {
        VStack(spacing: 20) {
            Text("Rewarded Ad Example")
                .font(.title)

            Button(action: {
                viewModel.showAd()
            }) {
                Text("Watch video to get reward")
                    .padding()
                    .background(viewModel.isAdReady ? Color.blue : Color.gray)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }
            .disabled(!viewModel.isAdReady)
        }
        .alert(isPresented: $viewModel.showingAlert) {
            Alert(
                title: Text("Notification"),
                message: Text(viewModel.alertMessage),
                dismissButton: .default(Text("OK"))
            )
        }
    }
}

Objective-C Example

@import AdropAds;

@interface RewardedViewController () <AdropRewardedAdDelegate>
@property (nonatomic, strong) AdropRewardedAd *rewardedAd;
@end

@implementation RewardedViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 1. Create AdropRewardedAd instance
    self.rewardedAd = [[AdropRewardedAd alloc] initWithUnitId:@"YOUR_UNIT_ID"];

    // 2. Set delegate
    self.rewardedAd.delegate = self;

    // 3. Load ad
    [self.rewardedAd load];
}

- (IBAction)showRewardedAdButtonTapped:(UIButton *)sender {
    // Check if ad is loaded
    if (!self.rewardedAd.isLoaded) {
        NSLog(@"Ad not loaded yet");
        return;
    }

    // 4. Show ad and handle reward
    __weak typeof(self) weakSelf = self;
    [self.rewardedAd showFromRootViewController:self
                        userDidEarnRewardHandler:^(NSInteger type, NSInteger amount) {
        NSLog(@"Reward earned - Type: %ld, Amount: %ld", (long)type, (long)amount);
        [weakSelf grantRewardWithType:type amount:amount];
    }];
}

- (void)grantRewardWithType:(NSInteger)type amount:(NSInteger)amount {
    // Grant reward to user
}

#pragma mark - AdropRewardedAdDelegate

// Required: Ad received successfully
- (void)onAdReceived:(AdropRewardedAd *)ad {
    NSLog(@"Ad received");
}

// Required: Ad receive failed
- (void)onAdFailedToReceive:(AdropRewardedAd *)ad :(AdropErrorCode)errorCode {
    NSLog(@"Ad receive failed: %ld", (long)errorCode);
}

// Optional: Ad impression
- (void)onAdImpression:(AdropRewardedAd *)ad {
    NSLog(@"Ad impression");
}

// Optional: Ad clicked
- (void)onAdClicked:(AdropRewardedAd *)ad {
    NSLog(@"Ad clicked");
}

// Optional: Before showing full screen ad
- (void)onAdWillPresentFullScreen:(AdropRewardedAd *)ad {
    NSLog(@"About to show ad");
}

// Optional: After showing full screen ad
- (void)onAdDidPresentFullScreen:(AdropRewardedAd *)ad {
    NSLog(@"Ad shown");
}

// Optional: Before dismissing full screen ad
- (void)onAdWillDismissFullScreen:(AdropRewardedAd *)ad {
    NSLog(@"About to dismiss ad");
}

// Optional: After dismissing full screen ad
- (void)onAdDidDismissFullScreen:(AdropRewardedAd *)ad {
    NSLog(@"Ad dismissed");

    // Preload next ad
    [self.rewardedAd load];
}

// Optional: Ad show failed
- (void)onAdFailedToShowFullScreen:(AdropRewardedAd *)ad :(AdropErrorCode)errorCode {
    NSLog(@"Ad show failed: %ld", (long)errorCode);
}

@end

Delegate Methods

Required Methods

onAdReceived(_:)
void
Called when ad is received successfully. You can show the ad using show() method from this point.
onAdFailedToReceive(_:_:)
void
Called when ad fails to load. You can check the cause of failure through the error code.

Optional Methods

onAdImpression(_:)
void
Called when ad impression is recorded and sent.
onAdClicked(_:)
void
Called when user clicks the ad.
onAdWillPresentFullScreen(_:)
void
Called just before the ad screen is displayed. You can pause background music, etc.
onAdDidPresentFullScreen(_:)
void
Called after the ad screen is fully displayed.
onAdWillDismissFullScreen(_:)
void
Called just before the ad screen is dismissed.
onAdDidDismissFullScreen(_:)
void
Called after the ad screen is fully dismissed. You can resume background music or preload the next ad.
onAdFailedToShowFullScreen(_:_:)
void
Called when ad fails to show. You can check the cause of failure through the error code.

Closure Callbacks

As an alternative to delegates, you can use closure-based callbacks.
let rewardedAd = AdropRewardedAd(unitId: "YOUR_UNIT_ID")

// Required
rewardedAd.onAdReceived = { ad in
    print("Ad received")
}
rewardedAd.onAdFailedToReceive = { ad, errorCode in
    print("Ad failed: \(errorCode)")
}

// Optional
rewardedAd.onAdImpression = { ad in print("Ad impression") }
rewardedAd.onAdClicked = { ad in print("Ad clicked") }
rewardedAd.onAdWillPresentFullScreen = { ad in print("Ad will present") }
rewardedAd.onAdDidPresentFullScreen = { ad in print("Ad did present") }
rewardedAd.onAdWillDismissFullScreen = { ad in print("Ad will dismiss") }
rewardedAd.onAdDidDismissFullScreen = { ad in print("Ad did dismiss") }
rewardedAd.onAdFailedToShowFullScreen = { ad, errorCode in print("Ad failed to show: \(errorCode)") }
If both a delegate and closures are set, both will be called.

Reward Handling

Reward Callback

Pass the reward callback through the userDidEarnRewardHandler parameter of the show() method.
rewardedAd?.show(fromRootViewController: self) { type, amount in
    // type: Reward type (Int)
    // amount: Reward amount (Int)
    print("Reward earned - Type: \(type), Amount: \(amount)")
}

Reward Type and Amount

  • type: Reward type set in Ad Control Console (integer value)
  • amount: Reward amount set in Ad Control Console (integer value)

Server-Side Verification

Server-side verification (SSV) allows you to verify reward grants on your server, preventing client-side manipulation. Use AdropServerSideVerificationOptions to pass user identification and custom data that will be included in the server-to-server callback.

Setting Up SSV

let rewardedAd = AdropRewardedAd(unitId: "YOUR_UNIT_ID")
rewardedAd.delegate = self

// Set server-side verification options before loading the ad
let ssvOptions = AdropServerSideVerificationOptions(
    userId: "user_12345",
    customData: "extra_info"
)
rewardedAd.serverSideVerificationOptions = ssvOptions

rewardedAd.load()

AdropServerSideVerificationOptions

PropertyTypeDescription
userIdString?User identifier for server-side verification
customDataString?Custom data string to include in the callback
// Initialize with parameters
let options = AdropServerSideVerificationOptions(
    userId: "user_12345",
    customData: "level_5_reward"
)

// Or set properties individually
let options = AdropServerSideVerificationOptions()
options.userId = "user_12345"
options.customData = "level_5_reward"

rewardedAd.serverSideVerificationOptions = options
Set serverSideVerificationOptions before calling load(). The userId and customData values are sent to your server callback URL when the user earns a reward.

Best Practices

1. Preload Ads

Preload ads for better user experience.
class GameViewController: UIViewController {
    private var rewardedAd: AdropRewardedAd?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Preload ad when entering screen
        loadRewardedAd()
    }

    private func loadRewardedAd() {
        rewardedAd = AdropRewardedAd(unitId: "YOUR_UNIT_ID")
        rewardedAd?.delegate = self
        rewardedAd?.load()
    }

    private func showRewardedAd() {
        rewardedAd?.show(fromRootViewController: self) { [weak self] type, amount in
            self?.grantReward(type: type, amount: amount)
        }
    }
}

extension GameViewController: AdropRewardedAdDelegate {
    func onAdReceived(_ ad: AdropRewardedAd) {
        print("Rewarded ad ready")
    }

    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        print("Ad load failed: \(errorCode)")
    }

    func onAdDidDismissFullScreen(_ ad: AdropRewardedAd) {
        // Preload next ad after ad is dismissed
        loadRewardedAd()
    }
}

2. Check Ad Ready State

Check if ad is loaded and update UI.
class GameViewController: UIViewController {
    @IBOutlet weak var watchAdButton: UIButton!
    private var rewardedAd: AdropRewardedAd?
    private var isAdReady = false

    private func updateButtonState() {
        watchAdButton.isEnabled = isAdReady
        watchAdButton.alpha = isAdReady ? 1.0 : 0.5
        watchAdButton.setTitle(
            isAdReady ? "Watch video to get lives" : "Loading ad...",
            for: .normal
        )
    }
}

extension GameViewController: AdropRewardedAdDelegate {
    func onAdReceived(_ ad: AdropRewardedAd) {
        isAdReady = true
        updateButtonState()
    }

    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        isAdReady = false
        updateButtonState()
    }

    func onAdDidDismissFullScreen(_ ad: AdropRewardedAd) {
        isAdReady = false
        updateButtonState()

        // Load next ad
        rewardedAd?.load()
    }
}

3. Background Music Handling

Control background music appropriately before and after showing ads.
extension GameViewController: AdropRewardedAdDelegate {
    func onAdReceived(_ ad: AdropRewardedAd) { }
    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) { }

    func onAdWillPresentFullScreen(_ ad: AdropRewardedAd) {
        // Pause background music before showing ad
        AudioManager.shared.pauseBackgroundMusic()
    }

    func onAdDidDismissFullScreen(_ ad: AdropRewardedAd) {
        // Resume background music after ad ends
        AudioManager.shared.resumeBackgroundMusic()
    }
}

4. Error Handling

Implement retry logic when ad loading fails.
extension GameViewController: AdropRewardedAdDelegate {
    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        print("Ad load failed: \(errorCode)")

        // Retry for network errors
        if errorCode == .ERROR_CODE_NETWORK {
            DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) { [weak self] in
                self?.rewardedAd?.load()
            }
        }
    }

    func onAdFailedToShowFullScreen(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        print("Ad show failed: \(errorCode)")

        // Notify user
        showAlert(message: "Unable to show ad. Please try again later.")
    }
}

5. Memory Management

Clean up ad object when ViewController is deallocated.
class GameViewController: UIViewController {
    private var rewardedAd: AdropRewardedAd?

    deinit {
        rewardedAd?.delegate = nil
        rewardedAd = nil
    }
}

Testing

Test Unit ID

Always use a test unit ID during development.
// Development environment
let rewardedAd = AdropRewardedAd(unitId: "PUBLIC_TEST_UNIT_ID_REWARDED")

// Production environment
let rewardedAd = AdropRewardedAd(unitId: "YOUR_PRODUCTION_UNIT_ID")
Testing with a real unit ID may be considered invalid traffic and could result in account suspension. Always use a test unit ID.

Managing Unit IDs by Environment

Automatically switch unit IDs based on build configuration.
enum AdUnitID {
    static var rewarded: String {
        #if DEBUG
        return "PUBLIC_TEST_UNIT_ID_REWARDED"
        #else
        return "YOUR_PRODUCTION_UNIT_ID"
        #endif
    }
}

// Usage
let rewardedAd = AdropRewardedAd(unitId: AdUnitID.rewarded)

Interstitial Ads

Interstitial ad implementation guide

Error Codes

AdropErrorCode reference

Example Project

View complete example code