メインコンテンツへスキップ

概要

リワード広告は、ユーザーが動画広告を最後まで視聴すると、ゲーム内通貨、ライフ、ヒントなどの報酬を提供するフルスクリーン動画広告です。

主な特徴

  • フルスクリーンで表示される動画広告
  • ユーザーが広告を完全に視聴した場合にのみ報酬を提供
  • ユーザーが自ら広告視聴を選択 (例: 「動画を見てライフを獲得」ボタン)
  • 報酬タイプと数量を設定可能
開発環境ではテストユニットIDを使用してください: PUBLIC_TEST_UNIT_ID_REWARDED

実装方法

リワード広告は次の手順で実装します:
  1. AdropRewardedAdインスタンスの生成 - ユニットIDで広告オブジェクトを生成
  2. デリゲートの設定 - 広告イベント処理のためのdelegateを指定
  3. 広告の読み込み - load()メソッドで広告をリクエスト
  4. 広告の表示 - show()メソッドで広告を表示し、報酬を処理

Swift例

基本実装

import UIKit
import AdropAds

class RewardedViewController: UIViewController {
    private var rewardedAd: AdropRewardedAd?

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1. AdropRewardedAdインスタンスの生成
        rewardedAd = AdropRewardedAd(unitId: "YOUR_UNIT_ID")

        // 2. デリゲートの設定
        rewardedAd?.delegate = self

        // 3. 広告の読み込み
        rewardedAd?.load()
    }

    @IBAction func showRewardedAdButtonTapped(_ sender: UIButton) {
        // 広告が読み込まれたか確認
        guard rewardedAd?.isLoaded == true else {
            print("広告がまだ読み込まれていません")
            return
        }

        // 4. 広告の表示と報酬処理
        rewardedAd?.show(fromRootViewController: self) { [weak self] type, amount in
            // 報酬付与処理
            print("報酬獲得 - タイプ: \(type), 数量: \(amount)")
            self?.grantReward(type: type, amount: amount)
        }
    }

    private func grantReward(type: Int, amount: Int) {
        // ユーザーに報酬を付与
        // 例: ゲーム通貨の追加、ライフの回復など

        // ⚠️ 重要: サーバーで報酬を検証することを推奨
        // クライアントのみで報酬を処理すると不正行為が可能
    }
}

// MARK: - AdropRewardedAdDelegate
extension RewardedViewController: AdropRewardedAdDelegate {
    // 必須: 広告受信成功
    func onAdReceived(_ ad: AdropRewardedAd) {
        print("広告受信完了")
        // 広告視聴ボタンを有効化するなど
    }

    // 必須: 広告受信失敗
    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        print("広告受信失敗: \(errorCode)")
        // 広告視聴ボタンを無効状態に維持するなど
    }

    // オプション: 広告表示
    func onAdImpression(_ ad: AdropRewardedAd) {
        print("広告表示")
    }

    // オプション: 広告クリック
    func onAdClicked(_ ad: AdropRewardedAd) {
        print("広告クリック")
    }

    // オプション: フルスクリーン広告表示直前
    func onAdWillPresentFullScreen(_ ad: AdropRewardedAd) {
        print("広告表示予定")
        // BGMの一時停止など
    }

    // オプション: フルスクリーン広告表示完了
    func onAdDidPresentFullScreen(_ ad: AdropRewardedAd) {
        print("広告表示完了")
    }

    // オプション: フルスクリーン広告閉じる直前
    func onAdWillDismissFullScreen(_ ad: AdropRewardedAd) {
        print("広告閉じる予定")
    }

    // オプション: フルスクリーン広告閉じた後
    func onAdDidDismissFullScreen(_ ad: AdropRewardedAd) {
        print("広告画面を閉じた")
        // BGMの再開など

        // 次の広告を事前読み込み
        rewardedAd?.load()
    }

    // オプション: 広告表示失敗
    func onAdFailedToShowFullScreen(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        print("広告表示失敗: \(errorCode)")
    }
}

SwiftUI例

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 = "報酬獲得! タイプ: \(type), 数量: \(amount)"
            self?.showingAlert = true
            self?.grantReward(type: type, amount: amount)
        }
    }

    private func grantReward(type: Int, amount: Int) {
        // 報酬付与処理
        print("報酬付与 - タイプ: \(type), 数量: \(amount)")
    }

    // MARK: - AdropRewardedAdDelegate

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

    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        isAdReady = false
        alertMessage = "広告読み込み失敗: \(errorCode)"
        showingAlert = true
    }

    func onAdDidDismissFullScreen(_ ad: AdropRewardedAd) {
        isAdReady = false
        // 次の広告を事前読み込み
        loadAd()
    }

    func onAdFailedToShowFullScreen(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        alertMessage = "広告表示失敗: \(errorCode)"
        showingAlert = true
    }
}

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

    var body: some View {
        VStack(spacing: 20) {
            Text("リワード広告サンプル")
                .font(.title)

            Button(action: {
                viewModel.showAd()
            }) {
                Text("動画を見て報酬を獲得")
                    .padding()
                    .background(viewModel.isAdReady ? Color.blue : Color.gray)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }
            .disabled(!viewModel.isAdReady)
        }
        .alert(isPresented: $viewModel.showingAlert) {
            Alert(
                title: Text("通知"),
                message: Text(viewModel.alertMessage),
                dismissButton: .default(Text("確認"))
            )
        }
    }
}

Objective-C例

@import AdropAds;

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

@implementation RewardedViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 1. AdropRewardedAdインスタンスの生成
    self.rewardedAd = [[AdropRewardedAd alloc] initWithUnitId:@"YOUR_UNIT_ID"];

    // 2. デリゲートの設定
    self.rewardedAd.delegate = self;

    // 3. 広告の読み込み
    [self.rewardedAd load];
}

- (IBAction)showRewardedAdButtonTapped:(UIButton *)sender {
    // 広告が読み込まれたか確認
    if (!self.rewardedAd.isLoaded) {
        NSLog(@"広告がまだ読み込まれていません");
        return;
    }

    // 4. 広告の表示と報酬処理
    __weak typeof(self) weakSelf = self;
    [self.rewardedAd showFromRootViewController:self
                        userDidEarnRewardHandler:^(NSInteger type, NSInteger amount) {
        NSLog(@"報酬獲得 - タイプ: %ld, 数量: %ld", (long)type, (long)amount);
        [weakSelf grantRewardWithType:type amount:amount];
    }];
}

- (void)grantRewardWithType:(NSInteger)type amount:(NSInteger)amount {
    // ユーザーに報酬を付与
}

#pragma mark - AdropRewardedAdDelegate

// 必須: 広告受信成功
- (void)onAdReceived:(AdropRewardedAd *)ad {
    NSLog(@"広告受信完了");
}

// 必須: 広告受信失敗
- (void)onAdFailedToReceive:(AdropRewardedAd *)ad :(AdropErrorCode)errorCode {
    NSLog(@"広告受信失敗: %ld", (long)errorCode);
}

// オプション: 広告表示
- (void)onAdImpression:(AdropRewardedAd *)ad {
    NSLog(@"広告表示");
}

// オプション: 広告クリック
- (void)onAdClicked:(AdropRewardedAd *)ad {
    NSLog(@"広告クリック");
}

// オプション: フルスクリーン広告表示直前
- (void)onAdWillPresentFullScreen:(AdropRewardedAd *)ad {
    NSLog(@"広告表示予定");
}

// オプション: フルスクリーン広告表示完了
- (void)onAdDidPresentFullScreen:(AdropRewardedAd *)ad {
    NSLog(@"広告表示完了");
}

// オプション: フルスクリーン広告閉じる直前
- (void)onAdWillDismissFullScreen:(AdropRewardedAd *)ad {
    NSLog(@"広告閉じる予定");
}

// オプション: フルスクリーン広告閉じた後
- (void)onAdDidDismissFullScreen:(AdropRewardedAd *)ad {
    NSLog(@"広告画面を閉じた");

    // 次の広告を事前読み込み
    [self.rewardedAd load];
}

// オプション: 広告表示失敗
- (void)onAdFailedToShowFullScreen:(AdropRewardedAd *)ad :(AdropErrorCode)errorCode {
    NSLog(@"広告表示失敗: %ld", (long)errorCode);
}

@end

デリゲートメソッド

必須メソッド

onAdReceived(_:)
void
広告の受信に成功したときに呼び出されます。この時点からshow()メソッドで広告を表示できます。
onAdFailedToReceive(_:_:)
void
広告の受信に失敗したときに呼び出されます。エラーコードで失敗原因を確認できます。

オプションメソッド

onAdImpression(_:)
void
広告が表示され、表示記録が送信されたときに呼び出されます。
onAdClicked(_:)
void
ユーザーが広告をクリックしたときに呼び出されます。
onAdWillPresentFullScreen(_:)
void
広告画面が表示される直前に呼び出されます。BGMの一時停止などの処理ができます。
onAdDidPresentFullScreen(_:)
void
広告画面が完全に表示された後に呼び出されます。
onAdWillDismissFullScreen(_:)
void
広告画面が閉じる直前に呼び出されます。
onAdDidDismissFullScreen(_:)
void
広告画面が完全に閉じた後に呼び出されます。BGMの再開や次の広告の事前読み込みができます。
onAdFailedToShowFullScreen(_:_:)
void
広告の表示に失敗したときに呼び出されます。エラーコードで失敗原因を確認できます。

クロージャコールバック

デリゲートの代わりにクロージャベースのコールバックを使用できます。
let rewardedAd = AdropRewardedAd(unitId: "YOUR_UNIT_ID")

// 必須
rewardedAd.onAdReceived = { ad in
    print("広告受信成功")
}
rewardedAd.onAdFailedToReceive = { ad, errorCode in
    print("広告受信失敗: \(errorCode)")
}

// オプション
rewardedAd.onAdImpression = { ad in print("広告表示") }
rewardedAd.onAdClicked = { ad in print("広告クリック") }
rewardedAd.onAdWillPresentFullScreen = { ad in print("広告表示直前") }
rewardedAd.onAdDidPresentFullScreen = { ad in print("広告表示完了") }
rewardedAd.onAdWillDismissFullScreen = { ad in print("広告閉じる直前") }
rewardedAd.onAdDidDismissFullScreen = { ad in print("広告閉じた") }
rewardedAd.onAdFailedToShowFullScreen = { ad, errorCode in print("広告表示失敗: \(errorCode)") }
デリゲートとクロージャの両方を設定すると、両方が呼び出されます。

報酬処理

報酬コールバック

show()メソッドのuserDidEarnRewardHandlerパラメータで報酬コールバックを渡します。
rewardedAd?.show(fromRootViewController: self) { type, amount in
    // type: 報酬タイプ (Int)
    // amount: 報酬数量 (Int)
    print("報酬獲得 - タイプ: \(type), 数量: \(amount)")
}

報酬タイプと数量

  • type: Adropコンソールで設定した報酬タイプ (整数値)
  • amount: Adropコンソールで設定した報酬数量 (整数値)

サーバーサイド検証

サーバーサイド検証(SSV)を使用すると、サーバーで報酬付与を検証でき、クライアント側の改ざんを防止できます。AdropServerSideVerificationOptionsを使用して、サーバー間コールバックに含まれるユーザー識別情報とカスタムデータを渡します。

SSVの設定

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

// 広告の読み込み前にサーバーサイド検証オプションを設定
let ssvOptions = AdropServerSideVerificationOptions(
    userId: "user_12345",
    customData: "extra_info"
)
rewardedAd.serverSideVerificationOptions = ssvOptions

rewardedAd.load()

AdropServerSideVerificationOptions

プロパティ説明
userIdString?サーバーサイド検証用のユーザー識別子
customDataString?コールバックに含めるカスタムデータ文字列
// パラメータで初期化
let options = AdropServerSideVerificationOptions(
    userId: "user_12345",
    customData: "level_5_reward"
)

// または個別にプロパティを設定
let options = AdropServerSideVerificationOptions()
options.userId = "user_12345"
options.customData = "level_5_reward"

rewardedAd.serverSideVerificationOptions = options
load()を呼び出す前にserverSideVerificationOptionsを設定してください。userIdcustomDataの値は、ユーザーが報酬を獲得したときにサーバーコールバックURLに送信されます。

ベストプラクティス

1. 広告の事前読み込み

ユーザー体験のために広告を事前に読み込んでおくことをお勧めします。
class GameViewController: UIViewController {
    private var rewardedAd: AdropRewardedAd?

    override func viewDidLoad() {
        super.viewDidLoad()

        // 画面進入時に広告を事前読み込み
        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("リワード広告準備完了")
    }

    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        print("広告読み込み失敗: \(errorCode)")
    }

    func onAdDidDismissFullScreen(_ ad: AdropRewardedAd) {
        // 広告が閉じた後、次の広告を事前読み込み
        loadRewardedAd()
    }
}

2. 広告準備状態の確認

広告が読み込まれたかを確認し、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 ? "動画を見てライフを獲得" : "広告読み込み中...",
            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()

        // 次の広告を読み込み
        rewardedAd?.load()
    }
}

3. BGM処理

広告表示前後でBGMを適切に制御します。
extension GameViewController: AdropRewardedAdDelegate {
    func onAdReceived(_ ad: AdropRewardedAd) { }
    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) { }

    func onAdWillPresentFullScreen(_ ad: AdropRewardedAd) {
        // 広告表示直前にBGMを一時停止
        AudioManager.shared.pauseBackgroundMusic()
    }

    func onAdDidDismissFullScreen(_ ad: AdropRewardedAd) {
        // 広告終了後にBGMを再開
        AudioManager.shared.resumeBackgroundMusic()
    }
}

4. エラー処理

広告読み込み失敗時のリトライロジックを実装します。
extension GameViewController: AdropRewardedAdDelegate {
    func onAdFailedToReceive(_ ad: AdropRewardedAd, _ errorCode: AdropErrorCode) {
        print("広告読み込み失敗: \(errorCode)")

        // ネットワークエラーの場合リトライ
        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("広告表示失敗: \(errorCode)")

        // ユーザーに通知
        showAlert(message: "広告を表示できません。後でもう一度お試しください。")
    }
}

5. メモリ管理

ViewControllerが解放されるとき、広告オブジェクトもクリーンアップします。
class GameViewController: UIViewController {
    private var rewardedAd: AdropRewardedAd?

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

テスト

テストユニットID

開発中は必ずテストユニットIDを使用してください。
// 開発環境
let rewardedAd = AdropRewardedAd(unitId: "PUBLIC_TEST_UNIT_ID_REWARDED")

// 本番環境
let rewardedAd = AdropRewardedAd(unitId: "YOUR_PRODUCTION_UNIT_ID")
実際のユニットIDでテストすると、無効なトラフィックと見なされ、アカウントが停止される可能性があります。必ずテストユニットIDを使用してください。

環境別ユニットID管理

ビルド設定に応じてユニットIDを自動的に切り替える方法です。
enum AdUnitID {
    static var rewarded: String {
        #if DEBUG
        return "PUBLIC_TEST_UNIT_ID_REWARDED"
        #else
        return "YOUR_PRODUCTION_UNIT_ID"
        #endif
    }
}

// 使用方法
let rewardedAd = AdropRewardedAd(unitId: AdUnitID.rewarded)

関連ドキュメント

インタースティシャル広告

インタースティシャル広告実装ガイド

エラーコード

AdropErrorCodeリファレンス

サンプルプロジェクト

全体のサンプルコードを見る