リワード広告はユーザーが動画広告を最後まで視聴すると、ゲーム内通貨、ライフ、ヒントなどの報酬を提供する全画面動画広告です。
主な特徴
- 全画面を占める動画広告
- ユーザーが広告を完全に視聴した場合のみ報酬を提供
- ユーザーが直接広告視聴を選択(例:「動画を見てライフをもらう」ボタン)
- 報酬タイプと数量を設定可能
開発環境ではテストユニットIDを使用してください。
実装方法
リワード広告は2つの方式で実装できます:
- クラス方式 -
AdropRewardedAdクラスを直接使用
- 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を使用すると広告状態を自動的に管理できます。
パラメータ
広告コントロールコンソールで発行された広告ユニットID。nullを渡すと広告インスタンスが生成されません。
戻り値
広告状態を初期化して新しい広告インスタンスを生成します。
reward
{ type: number, amount: number } | undefined
報酬情報(タイプと数量)
広告表示中に戻るボタンが押されたかどうか。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)
広告コントロールコンソールで発行された広告ユニットID
プロパティ
広告がロードされて表示可能な状態かどうか(読み取り専用)
ロードされた広告のクリエイティブID(読み取り専用)
ロードされた広告のキャンペーンID(読み取り専用)
ロードされた広告のランディングURL(読み取り専用)
ロードされた広告のブラウザターゲット設定(BrowserTarget.EXTERNALまたはBrowserTarget.INTERNAL)(読み取り専用)
listener
AdropListener | undefined
広告イベントを受信するリスナー
メソッド
広告をリクエストします。結果はリスナーのonAdReceivedまたはonAdFailedToReceiveで通知されます。
広告リソースを解放します。コンポーネントアンマウント時に呼び出す必要があります。
AdropListenerインターフェース
すべてのコールバックはオプションです。必要なコールバックのみ設定してください。
コールバック
onAdReceived(ad: AdropAd)
広告受信に成功したときに呼び出されます。この時点からshow()メソッドで広告を表示できます。
onAdFailedToReceive(ad: AdropAd, errorCode?: any)
広告受信に失敗したときに呼び出されます。エラーコードで失敗原因を確認できます。
onAdImpression(ad: AdropAd)
広告が表示され、インプレッション記録が送信されたときに呼び出されます。
ユーザーが広告をクリックしたときに呼び出されます。
onAdWillPresentFullScreen(ad: AdropAd)
広告画面が表示される直前に呼び出されます。
onAdDidPresentFullScreen(ad: AdropAd)
広告画面が完全に表示された後に呼び出されます。
onAdWillDismissFullScreen(ad: AdropAd)
広告画面が閉じられる直前に呼び出されます。
onAdDidDismissFullScreen(ad: AdropAd)
広告画面が完全に閉じられた後に呼び出されます。次の広告を事前ロードするのに適したタイミングです。
onAdFailedToShowFullScreen(ad: AdropAd, errorCode?: any)
広告表示に失敗したときに呼び出されます。エラーコードで失敗原因を確認できます。
onAdBackButtonPressed(ad: AdropAd)
広告表示中にユーザーが戻るボタンを押したときに呼び出されます。Androidのみ。
リワード専用コールバック
onAdEarnRewardHandler(ad: AdropAd, type: number, amount: number)
ユーザーが広告を最後まで視聴し、報酬を獲得したときに呼び出されます。
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)
}
},
}
関連ドキュメント
インタースティシャル広告
インタースティシャル広告実装ガイド