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

概要

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

主な特徴

  • 全画面を占める動画広告
  • ユーザーが広告を完全に視聴した場合のみ報酬を提供
  • ユーザーが直接広告視聴を選択(例:「動画を見てライフをもらう」ボタン)
  • 報酬タイプと数量を設定可能
開発環境ではテストユニットIDを使用してください。

実装方法

リワード広告は2つの方式で実装できます:
  1. クラス方式 - AdropRewardedAdクラスを直接使用
  2. Hook方式 - useAdropRewardedAd Hookを使用(推奨)

Hook方式実装(推奨)

React Hookを使用してより簡潔でReactらしい方式で実装できます。

基本例

import React, { useCallback } from 'react';
import { Button, View, Text, StyleSheet } from 'react-native';
import { useAdropRewardedAd } from 'adrop-ads-react-native';

const RewardedAdScreen = () => {
  const unitId = 'YOUR_UNIT_ID'; // またはテストユニットID

  const {
    load,
    show,
    reset,
    isLoaded,
    isOpened,
    isClosed,
    isEarnRewarded,
    reward,
    errorCode,
    isReady
  } = useAdropRewardedAd(unitId);

  // コンポーネントマウント時に広告ロード
  React.useEffect(() => {
    if (isReady) {
      load();
    }
  }, [isReady, load]);

  // 広告が閉じた後に次の広告をロード
  React.useEffect(() => {
    if (isClosed) {
      console.log('広告が閉じました');
      // 次の広告を事前ロード
      reset();
      load();
    }
  }, [isClosed, reset, load]);

  // 報酬処理
  React.useEffect(() => {
    if (isEarnRewarded && reward) {
      console.log(`報酬獲得 - タイプ: ${reward.type}, 数量: ${reward.amount}`);
      grantReward(reward.type, reward.amount);
    }
  }, [isEarnRewarded, reward]);

  const handleShowAd = useCallback(() => {
    if (isLoaded) {
      show();
    } else {
      console.log('広告がまだロードされていません');
    }
  }, [isLoaded, show]);

  const grantReward = (type: number, amount: number) => {
    // ユーザーに報酬を支給
    console.log(`報酬支給: タイプ=${type}, 数量=${amount}`);
    // 実際の報酬支給ロジックを実装
  };

  return (
    <View style={styles.container}>
      <Button
        title="広告ロード"
        onPress={load}
        disabled={!isReady}
      />
      <Button
        title="広告を見る"
        onPress={handleShowAd}
        disabled={!isLoaded}
      />
      {errorCode && (
        <Text style={styles.error}>エラー: {errorCode}</Text>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    gap: 16,
  },
  error: {
    color: 'red',
  },
});

export default RewardedAdScreen;

useAdropRewardedAd Hook

Hookを使用すると広告状態を自動的に管理できます。

パラメータ

unitId
string | null
広告コントロールコンソールで発行された広告ユニットID。nullを渡すと広告インスタンスが生成されません。

戻り値

load
() => void
広告をリクエストします。
show
() => void
広告を表示します。
reset
() => void
広告状態を初期化して新しい広告インスタンスを生成します。
isLoaded
boolean
広告がロードされて表示可能な状態かどうか
isOpened
boolean
広告が画面に表示されたかどうか
isClosed
boolean
広告が閉じられたかどうか
isEarnRewarded
boolean
ユーザーが報酬を獲得したかどうか
reward
{ type: number, amount: number } | undefined
報酬情報(タイプと数量)
errorCode
string | undefined
エラーコード(エラー発生時のみ値あり)
isReady
boolean
広告インスタンスが準備され使用可能な状態かどうか
isClicked
boolean
広告がクリックされたかどうか
isBackPressed
boolean
広告表示中に戻るボタンが押されたかどうか。Androidのみ。
browserTarget
BrowserTarget | undefined
ロードされた広告のブラウザターゲット設定(BrowserTarget.EXTERNALまたはBrowserTarget.INTERNAL

クラス方式実装

AdropRewardedAdクラスを直接使用して広告を実装できます。

基本例

import React, { useEffect, useState, useCallback } from 'react';
import { Button, View, Text, StyleSheet } from 'react-native';
import { AdropRewardedAd, AdropListener } from 'adrop-ads-react-native';

const RewardedAdScreen = () => {
  const [rewardedAd, setRewardedAd] = useState<AdropRewardedAd | null>(null);
  const [isLoaded, setIsLoaded] = useState(false);

  useEffect(() => {
    // 1. AdropRewardedAdインスタンス生成
    const ad = new AdropRewardedAd('YOUR_UNIT_ID');

    // 2. Listener設定
    const listener: AdropListener = {
      onAdReceived: (ad) => {
        console.log('広告受信完了:', ad.unitId);
        setIsLoaded(true);
      },
      onAdFailedToReceive: (ad, errorCode) => {
        console.log('広告受信失敗:', errorCode);
        setIsLoaded(false);
      },
      onAdDidPresentFullScreen: (ad) => {
        console.log('広告画面表示:', ad.unitId);
      },
      onAdDidDismissFullScreen: (ad) => {
        console.log('広告画面閉じる:', ad.unitId);
        setIsLoaded(false);
        // 次の広告を事前ロード
        ad.load();
      },
      onAdEarnRewardHandler: (ad, type, amount) => {
        console.log(`報酬獲得 - タイプ: ${type}, 数量: ${amount}`);
        grantReward(type, amount);
      },
      onAdClicked: (ad) => {
        console.log('広告クリック:', ad.unitId);
      },
      onAdImpression: (ad) => {
        console.log('広告表示:', ad.unitId);
      },
      onAdFailedToShowFullScreen: (ad, errorCode) => {
        console.log('広告表示失敗:', errorCode);
      },
    };

    ad.listener = listener;
    setRewardedAd(ad);

    // 3. 広告ロード
    ad.load();

    // コンポーネントアンマウント時にクリーンアップ
    return () => {
      ad.destroy();
    };
  }, []);

  const handleShowAd = useCallback(() => {
    if (rewardedAd && isLoaded) {
      rewardedAd.show();
    } else {
      console.log('広告がまだロードされていません');
    }
  }, [rewardedAd, isLoaded]);

  const grantReward = (type: number, amount: number) => {
    // ユーザーに報酬を支給
    console.log(`報酬支給: タイプ=${type}, 数量=${amount}`);
    // 実際の報酬支給ロジックを実装
  };

  return (
    <View style={styles.container}>
      <Button
        title="広告ロード"
        onPress={() => rewardedAd?.load()}
      />
      <Button
        title="広告を見る"
        onPress={handleShowAd}
        disabled={!isLoaded}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    gap: 16,
  },
});

export default RewardedAdScreen;

AdropRewardedAdクラス

コンストラクタ

new AdropRewardedAd(unitId: string)
unitId
string
広告コントロールコンソールで発行された広告ユニットID

プロパティ

unitId
string
広告ユニットID(読み取り専用)
isLoaded
boolean
広告がロードされて表示可能な状態かどうか(読み取り専用)
creativeId
string
ロードされた広告のクリエイティブID(読み取り専用)
txId
string
トランザクションID(読み取り専用)
campaignId
string
ロードされた広告のキャンペーンID(読み取り専用)
destinationURL
string
ロードされた広告のランディングURL(読み取り専用)
browserTarget
BrowserTarget
ロードされた広告のブラウザターゲット設定(BrowserTarget.EXTERNALまたはBrowserTarget.INTERNAL)(読み取り専用)
listener
AdropListener | undefined
広告イベントを受信するリスナー

メソッド

load()
void
広告をリクエストします。結果はリスナーのonAdReceivedまたはonAdFailedToReceiveで通知されます。
show()
void
広告を表示します。
destroy()
void
広告リソースを解放します。コンポーネントアンマウント時に呼び出す必要があります。

AdropListenerインターフェース

すべてのコールバックはオプションです。必要なコールバックのみ設定してください。

コールバック

onAdReceived(ad: AdropAd)
void
広告受信に成功したときに呼び出されます。この時点からshow()メソッドで広告を表示できます。
onAdFailedToReceive(ad: AdropAd, errorCode?: any)
void
広告受信に失敗したときに呼び出されます。エラーコードで失敗原因を確認できます。
onAdImpression(ad: AdropAd)
void
広告が表示され、インプレッション記録が送信されたときに呼び出されます。
onAdClicked(ad: AdropAd)
void
ユーザーが広告をクリックしたときに呼び出されます。
onAdWillPresentFullScreen(ad: AdropAd)
void
広告画面が表示される直前に呼び出されます。
onAdDidPresentFullScreen(ad: AdropAd)
void
広告画面が完全に表示された後に呼び出されます。
onAdWillDismissFullScreen(ad: AdropAd)
void
広告画面が閉じられる直前に呼び出されます。
onAdDidDismissFullScreen(ad: AdropAd)
void
広告画面が完全に閉じられた後に呼び出されます。次の広告を事前ロードするのに適したタイミングです。
onAdFailedToShowFullScreen(ad: AdropAd, errorCode?: any)
void
広告表示に失敗したときに呼び出されます。エラーコードで失敗原因を確認できます。
onAdBackButtonPressed(ad: AdropAd)
void
広告表示中にユーザーが戻るボタンを押したときに呼び出されます。Androidのみ。

リワード専用コールバック

onAdEarnRewardHandler(ad: AdropAd, type: number, amount: number)
void
ユーザーが広告を最後まで視聴し、報酬を獲得したときに呼び出されます。
  • type: 広告コントロールコンソールで設定した報酬タイプ(整数値)
  • amount: 広告コントロールコンソールで設定した報酬数量(整数値)

報酬処理

Hook方式での報酬処理

const RewardedAdScreen = () => {
  const { isEarnRewarded, reward } = useAdropRewardedAd('YOUR_UNIT_ID');

  useEffect(() => {
    if (isEarnRewarded && reward) {
      // 報酬支給処理
      console.log(`報酬獲得 - タイプ: ${reward.type}, 数量: ${reward.amount}`);
      grantReward(reward.type, reward.amount);
    }
  }, [isEarnRewarded, reward]);

  const grantReward = (type: number, amount: number) => {
    // ユーザーに報酬を支給
    // 例:ゲーム通貨追加、ライフ回復など
  };

  // ...
};

クラス方式での報酬処理

const listener: AdropListener = {
  onAdEarnRewardHandler: (ad, type, amount) => {
    console.log(`報酬獲得 - タイプ: ${type}, 数量: ${amount}`);
    grantReward(type, amount);
  },
  // その他のコールバック...
};

const grantReward = (type: number, amount: number) => {
  // ユーザーに報酬を支給
  // 例:ゲーム通貨追加、ライフ回復など
};

サーバーサイド検証

サーバーで報酬の付与を検証することで、不正行為を防止できます。setServerSideVerificationOptions()を使用して、サーバーサイド検証コールバックに含めるユーザーおよびカスタムデータを渡します。

セットアップ

import { AdropRewardedAd } from 'adrop-ads-react-native'

const rewardedAd = new AdropRewardedAd('YOUR_UNIT_ID')

// 広告を表示する前にサーバーサイド検証オプションを設定
rewardedAd.setServerSideVerificationOptions({
  userId: 'user_12345',
  customData: 'extra_info',
})

rewardedAd.listener = {
  onAdReceived: (ad) => {
    ad.show()
  },
  onAdEarnRewardHandler: (ad, type, amount) => {
    // クライアント側コールバック(オプション)
    // サーバーサイド検証コールバックも送信されます
    console.log(`報酬獲得: type=${type}, amount=${amount}`)
  },
}

rewardedAd.load()

ServerSideVerificationOptions

type ServerSideVerificationOptions = {
  userId?: string
  customData?: string
}
プロパティ:
  • userId (string, optional): サーバーコールバックに送信されるユーザー識別子
  • customData (string, optional): サーバーコールバックに送信されるカスタムデータ
setServerSideVerificationOptions()load()の前に呼び出す必要があります。オプションはユーザーがリワードを獲得した際にサーバーに送信されます。

テスト

テストユニットID

開発中は常にテストユニットIDを使用してください。実際のユニットIDでテストすると無効なトラフィックと見なされアカウントが停止される可能性があります。
// Hook方式
const unitId = __DEV__ ? 'PUBLIC_TEST_UNIT_ID_REWARDED' : 'YOUR_PRODUCTION_UNIT_ID';
const rewardedAd = useAdropRewardedAd(unitId);

// クラス方式
const unitId = __DEV__ ? 'PUBLIC_TEST_UNIT_ID_REWARDED' : 'YOUR_PRODUCTION_UNIT_ID';
const ad = new AdropRewardedAd(unitId);

エラー処理

Hook方式でのエラー処理

const RewardedAdScreen = () => {
  const { load, errorCode, reset } = useAdropRewardedAd('YOUR_UNIT_ID');

  useEffect(() => {
    if (errorCode) {
      console.log('広告エラー:', errorCode);
      // エラータイプに応じた処理
      if (errorCode === AdropErrorCode.network) {
        // ネットワークエラー:リトライ
        setTimeout(() => {
          reset();
          load();
        }, 3000);
      }
    }
  }, [errorCode, reset, load]);

  // ...
};

クラス方式でのエラー処理

const listener: AdropListener = {
  onAdFailedToReceive: (ad, errorCode) => {
    console.log('広告受信失敗:', errorCode);
    if (errorCode === AdropErrorCode.network) {
      // ネットワークエラー:3秒後にリトライ
      setTimeout(() => {
        ad.load();
      }, 3000);
    }
  },
  onAdFailedToShowFullScreen: (ad, errorCode) => {
    console.log('広告表示失敗:', errorCode);
    Alert.alert('お知らせ', '広告を表示できません。後でもう一度お試しください。');
  },
  // その他のコールバック...
};

ベストプラクティス

1. 広告を事前ロード

ユーザー体験のために広告を事前にロードしておくことをお勧めします。
// Hook方式
const RewardedAdScreen = () => {
  const { load, isClosed, reset, isReady } = useAdropRewardedAd('YOUR_UNIT_ID');

  // コンポーネントマウント時に広告ロード
  useEffect(() => {
    if (isReady) {
      load();
    }
  }, [isReady, load]);

  // 広告が閉じた後に次の広告を事前ロード
  useEffect(() => {
    if (isClosed) {
      reset();
      load();
    }
  }, [isClosed, reset, load]);

  // ...
};

2. 広告準備状態確認

広告がロードされているか確認してUIを更新します。
const RewardedAdScreen = () => {
  const { isLoaded, show } = useAdropRewardedAd('YOUR_UNIT_ID');

  return (
    <View>
      <Button
        title={isLoaded ? "動画を見てライフをもらう" : "広告ロード中..."}
        onPress={show}
        disabled={!isLoaded}
      />
    </View>
  );
};

3. メモリ管理

コンポーネントアンマウント時に広告リソースをクリーンアップします。
// Hook方式は自動的にクリーンアップ
const { ... } = useAdropRewardedAd('YOUR_UNIT_ID');

// クラス方式は手動でクリーンアップが必要
useEffect(() => {
  const ad = new AdropRewardedAd('YOUR_UNIT_ID');
  // ...

  return () => {
    ad.destroy();
  };
}, []);

4. エラーハンドリング

適切なエラー処理でユーザー体験を改善します。
const RewardedAdScreen = () => {
  const { errorCode, reset, load } = useAdropRewardedAd('YOUR_UNIT_ID');

  useEffect(() => {
    if (errorCode) {
      // ユーザーにエラーを通知
      Alert.alert('お知らせ', '広告を読み込めません。');

      // ネットワークエラーの場合はリトライ
      if (errorCode === AdropErrorCode.network) {
        setTimeout(() => {
          reset();
          load();
        }, 3000);
      }
    }
  }, [errorCode, reset, load]);

  // ...
};

完全な例

Hook方式の完全な例

import React, { useEffect, useCallback } from 'react';
import {
  Button,
  View,
  Text,
  StyleSheet,
  Alert,
  ActivityIndicator
} from 'react-native';
import { useAdropRewardedAd } from 'adrop-ads-react-native';

const RewardedAdScreen = () => {
  const unitId = __DEV__ ? 'PUBLIC_TEST_UNIT_ID_REWARDED' : 'YOUR_PRODUCTION_UNIT_ID';

  const {
    load,
    show,
    reset,
    isLoaded,
    isOpened,
    isClosed,
    isEarnRewarded,
    reward,
    errorCode,
    isReady
  } = useAdropRewardedAd(unitId);

  // コンポーネントマウント時に広告ロード
  useEffect(() => {
    if (isReady) {
      console.log('広告インスタンス準備完了、広告ロード開始');
      load();
    }
  }, [isReady, load]);

  // 広告が表示されたとき
  useEffect(() => {
    if (isOpened) {
      console.log('広告が表示されました');
      // BGM一時停止など
    }
  }, [isOpened]);

  // 広告が閉じた後に次の広告を事前ロード
  useEffect(() => {
    if (isClosed) {
      console.log('広告が閉じました');
      // BGM再開など

      // 次の広告を事前ロード
      reset();
      load();
    }
  }, [isClosed, reset, load]);

  // 報酬処理
  useEffect(() => {
    if (isEarnRewarded && reward) {
      console.log(`報酬獲得 - タイプ: ${reward.type}, 数量: ${reward.amount}`);
      grantReward(reward.type, reward.amount);
    }
  }, [isEarnRewarded, reward]);

  // エラー処理
  useEffect(() => {
    if (errorCode) {
      console.log('広告エラー:', errorCode);

      // ネットワークエラーの場合はリトライ
      if (errorCode === AdropErrorCode.network) {
        Alert.alert(
          'ネットワークエラー',
          '広告を読み込めません。3秒後にリトライします。',
          [{ text: 'OK' }]
        );

        setTimeout(() => {
          reset();
          load();
        }, 3000);
      } else {
        Alert.alert('エラー', `広告エラー: ${errorCode}`);
      }
    }
  }, [errorCode, reset, load]);

  const handleShowAd = useCallback(() => {
    if (isLoaded) {
      show();
    } else {
      Alert.alert('お知らせ', '広告がまだロードされていません。');
    }
  }, [isLoaded, show]);

  const grantReward = (type: number, amount: number) => {
    // ユーザーに報酬を支給
    Alert.alert(
      '報酬獲得!',
      `タイプ: ${type}, 数量: ${amount}`,
      [{ text: 'OK' }]
    );

    // 実際の報酬支給ロジックを実装
    // 例:ゲーム通貨追加、ライフ回復など
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>リワード広告</Text>

      {!isReady && (
        <View style={styles.loadingContainer}>
          <ActivityIndicator size="large" color="#0000ff" />
          <Text style={styles.loadingText}>広告初期化中...</Text>
        </View>
      )}

      <View style={styles.buttonContainer}>
        <Button
          title="広告ロード"
          onPress={load}
          disabled={!isReady}
        />
      </View>

      <View style={styles.buttonContainer}>
        <Button
          title={isLoaded ? "動画を見てライフをもらう" : "広告ロード中..."}
          onPress={handleShowAd}
          disabled={!isLoaded}
        />
      </View>

      <View style={styles.statusContainer}>
        <Text style={styles.statusText}>
          ステータス: {isLoaded ? '準備完了' : 'ロード中'}
        </Text>
        {errorCode && (
          <Text style={styles.errorText}>エラー: {errorCode}</Text>
        )}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
    backgroundColor: '#f5f5f5',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 30,
  },
  loadingContainer: {
    alignItems: 'center',
    marginBottom: 20,
  },
  loadingText: {
    marginTop: 10,
    color: '#666',
  },
  buttonContainer: {
    width: '100%',
    marginVertical: 8,
  },
  statusContainer: {
    marginTop: 30,
    alignItems: 'center',
  },
  statusText: {
    fontSize: 16,
    color: '#333',
  },
  errorText: {
    fontSize: 14,
    color: 'red',
    marginTop: 8,
  },
});

export default RewardedAdScreen;

バックフィル広告

バックフィル広告を使用するには、ネイティブプラットフォーム(Android/iOS)にバックフィル依存関係が追加されている必要があります。
バックフィル広告が有効な場合、直接広告が利用できないときにSDKが自動的にバックフィル広告にフォールバックします。リスナーでバックフィル関連のエラーコードを処理できます。
rewardedAd.listener = {
  onAdReceived: (ad) => {
    console.log('広告ロード完了:', ad.creativeId)
  },
  onAdFailedToReceive: (ad, errorCode) => {
    switch (errorCode) {
      case AdropErrorCode.adNoFill:
        console.log('直接広告なし、バックフィル広告をリクエスト中...')
        break
      case AdropErrorCode.backfillNoFill:
        console.log('バックフィル広告もありません')
        break
      default:
        console.log('広告ロード失敗:', errorCode)
    }
  },
}

関連ドキュメント

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

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

ポップアップ広告

ポップアップ広告実装ガイド

ネイティブ広告

ネイティブ広告実装ガイド

エラーコード

エラーコードリファレンス