AdMob メディエーションを設定した翌朝、ダッシュボードを開いて思わず固まりました。
eCPM が30%下がっていたのです。「複数の広告ネットワークを競わせれば収益が上がる」という理屈で導入したのに、逆の結果が出ました。胸の奥がすっと冷えるような感覚を、今でも覚えています。2014年から個人でアプリ開発を続けてきた中で、収益周りでこれほど「やってしまった」と思った瞬間はほとんどありませんでした。
個人開発で長くAdMobと付き合っていると、収益最大化のための試行錯誤はどうしても量が増えていきます。その経験からすると、メディエーション導入直後の失敗は「あるある」です。特にRorkで作ったアプリは、設定の落とし穴にはまりやすいポイントが独自にあると気づきました。
以下では、私が実際に踏んだ失敗と回復の過程を追います。eCPMが下がる仕組み、Rork特有の3つの落とし穴、効果を数値で確かめる計測方法、そして「そもそも導入すべきか」の判断基準まで、順を追って共有していきます。
AdMob メディエーションで何が起きていたか
メディエーションとは、複数の広告ネットワーク(AppLovin、Unity Ads、Meta Audience Network など)に入札させて、最高額を提示したネットワークの広告を表示する仕組みです。うまく機能すれば eCPM は上がります。
ただし「うまく機能すれば」という条件付きです。
私が経験した eCPM 下落の原因は、後から振り返ると明確でした。ウォーターフォール(各ネットワークへの入札順序)の設定が間違っていたのです。AdMob が最初に呼ばれるべき場面で、単価の低いネットワークが先に応答してしまっていました。
Rorkで広告実装をするとき、AIが生成するコードはAdMobの基本設定としては問題ありません。ただしメディエーションアダプターの追加設定は、コード外のコンソール操作が多く、AIの出力だけでは完結しない部分が残ります。そこが詰まりやすいポイントです。
メディエーションが eCPM を下げてしまう理屈
「競わせれば上がるはず」なのに下がる。この矛盾を理解するには、ウォーターフォール方式の内部動作を押さえる必要があります。
ウォーターフォール方式では、各ネットワークに優先順位(eCPMフロア)を割り当て、上から順に「この単価で広告を出せますか」と問い合わせます。あるネットワークが応答すれば、そこで確定して下位には問い合わせません。
ここに罠があります。フロアを低く設定したネットワークが上位に来ていると、本来もっと高く売れたはずの表示枠を、安値で即決してしまうのです。オークションで言えば、最高額の入札を待たずに最初に手を挙げた人へ売ってしまう状態です。
私のケースでは、初期値の $0.50 フロアのネットワークが実質的な「即決係」になっていました。本来 $1.80〜$2.20 で売れる枠が、$0.50 前後で次々と処理されていた。これが30%下落の正体でした。
つまりメディエーションは「導入すれば上がる」ものではなく、「各ネットワークのフロアを実態に合わせて初めて機能する」仕組みだということです。ここを飛ばすと、ネットワークを増やしたことがそのまま収益の穴になります。
Rork アプリ特有の3つの落とし穴
落とし穴1: ウォーターフォールの順序をデフォルトのまま放置する
AdMob コンソールでメディエーションを設定するとき、各ネットワークの eCPM フロアをデフォルト値のままにしていませんか。
Googleが推奨する「Bidding(入札型)」方式を使えば自動最適化されますが、一部のネットワークは現時点でもウォーターフォール方式にしか対応していません。この場合、eCPM フロアを実際の表示単価から±10〜15%の範囲で手動設定する必要があります。
私の失敗は、初期設定の $0.50 というフロアをそのまま使ったことでした。実際の eCPM が $1.80 〜 $2.20 のレンジで推移していたため、$0.50 フロアの低品質な広告が大量に表示されてしまいました。フロアを $1.50 に設定し直したところ、3日で元の水準に戻りました。
落とし穴2: iOS の ATT と広告 ID の連携が切れる
Rork のプロジェクトで ATT(App Tracking Transparency)の実装を後から追加したとき、メディエーション側のネットワークが広告IDを受け取れていない状態になることがあります。
ATT の許可を取得した後、メディエーションアダプターを初期化するタイミングが重要です。ATT の許可を取得する前にアダプターを初期化してしまうと、iOS 14以降では広告IDなしで動作するため、ターゲティングなし広告が表示され続けます。
import { requestTrackingPermission } from 'react-native-tracking-transparency';
import MobileAds from 'react-native-google-mobile-ads';
// ✅ ATT許可取得 → アダプター初期化の順番が正しい
const initializeAdsAfterATT = async () => {
// iOS のみ ATT を先に処理
if (Platform.OS === 'ios') {
const status = await requestTrackingPermission();
console.log('ATT status:', status);
}
// ATT 処理後に AdMob SDK を初期化
await MobileAds().initialize();
// この時点でメディエーションアダプターも自動初期化される
};
Rork のプロンプトで「ATT許可取得後にAdMob SDKを初期化する」と明示すると、AIもこの順番でコードを生成します。ただし既存プロジェクトに後からATTを追加するときは、生成コードをそのまま使わず、初期化タイミングを必ず確認してください。
落とし穴3: Android と iOS でアダプター設定を分けていない
Rork は iOS/Android 両対応のコードを一括で生成しますが、AdMob メディエーションのアダプターは OS ごとに別のパッケージIDが必要です。
app.json のプラグイン設定で iOS 用と Android 用を分けて記述していないと、どちらかのプラットフォームでアダプターが認識されずに広告が表示されないことがあります。
// app.json のプラグイン設定例(iOS/Android 分離)
{
"plugins": [
[
"react-native-google-mobile-ads",
{
"androidAppId": "ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX",
"iosAppId": "ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX",
"userTrackingUsageDescription": "This identifier will be used to deliver personalized ads to you.",
"skAdNetworkItems": [
{ "SKAdNetworkIdentifier": "cstr6suwn9.skadnetwork" },
{ "SKAdNetworkIdentifier": "4fzdc2evr5.skadnetwork" }
]
}
]
]
}
SKAdNetworkItems の一覧は各ネットワークが公式ドキュメントで提供していますが、バージョン更新のたびに内容が変わります。月に1回は確認する習慣をつけておくと、iOS 広告の表示率が落ちるトラブルを防げます。
ウォーターフォールと入札型(Bidding)をどう併用するか
「じゃあ全部 Bidding にすればいい」と思われるかもしれません。実際、対応しているネットワークは Bidding に寄せるのが正解です。ただ現実には、ウォーターフォールでしか繋げられないネットワークが残るため、両者の併用になります。
私が最終的に落ち着いた棲み分けを表にまとめます。
| 方式 | 向くネットワーク | 設定の手間 | フロア調整 |
| Bidding(入札型) | AdMob本体・Meta・AppLovin など主要どころ | 低い(自動最適化) | 不要 |
| ウォーターフォール | Bidding未対応の中小ネットワーク | 高い(手動) | 実測から±10〜15%で手動設定 |
考え方はシンプルです。Bidding 対応ネットワークはすべて Bidding に入れて自動オークションに任せ、その上でウォーターフォール側は「Biddingの落札額を下回らないフロア」を設定します。こうするとウォーターフォールが安値で即決する事故が起きません。
Rorkで作ったアプリでも、この構成の判断はコンソール側の作業なので、生成コードには影響しません。むしろコードを気にせず収益設計に集中できる点は、AIビルダーを使う利点だと感じています。
導入前後の eCPM を自分で計測する仕組み
メディエーションの効果は「なんとなく上がった気がする」で判断してはいけません。私が30%下落に気づけたのも、日次で eCPM を記録していたからでした。
AdMobのレポートは管理画面でも見られますが、導入前後を並べて比較するなら、AdMob API から日次で取得して手元に残す仕組みを一度作っておくと後が楽です。React Native アプリ側ではなく、収益データを引くだけの軽いスクリプトで十分です。
// AdMob Reporting API から日次 eCPM を取得する最小構成の例
// 認証済みの google-auth ライブラリで accessToken を取得済みとする
async function fetchDailyEcpm(accountId: string, accessToken: string) {
const endpoint =
`https://admob.googleapis.com/v1/accounts/${accountId}/mediationReport:generate`;
const body = {
reportSpec: {
dateRange: { startDate: last7Days().start, endDate: last7Days().end },
dimensions: ['DATE', 'AD_SOURCE'],
metrics: ['ESTIMATED_EARNINGS', 'IMPRESSIONS'],
},
};
const res = await fetch(endpoint, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
// 収益 ÷ 表示回数 × 1000 で eCPM を自前計算し、ネットワーク別に並べる
return res.json();
}
大切なのは AD_SOURCE(広告ソース)ディメンションでネットワーク別に分解することです。全体の eCPM が下がったとき、どのネットワークが足を引っ張っているかが一目でわかります。私の場合、この分解でようやく「$0.50フロアのネットワークだけ表示回数が異常に多い」という事実に気づけました。
数値を毎日残しておくと、感覚ではなく事実で判断できます。収益周りの意思決定において、この差はとても大きいと実感しています。
メディエーションを入れるべきか、見送るべきか
ここまで書いておいてなんですが、すべてのアプリにメディエーションが必要なわけではありません。導入と運用にはそれなりの手間がかかるため、規模が見合わなければ AdMob 単体のほうが健全です。
私なりの判断の目安を挙げておきます。
- 日次のインプレッションがまだ数千に届かないうちは、メディエーションより先にeCPMフロアや広告フォーマットの見直しで伸びしろが大きいです
- 主要国からのアクセスが中心なら、まず Bidding 対応ネットワークだけで組み、ウォーターフォールは後回しでも構いません
- 手動フロア調整を月1回は見直せる運用体制があるか。これがないとウォーターフォールは放置されて劣化します
逆に言えば、ある程度のインプレッションがあり、運用に月数十分を割ける個人開発者であれば、メディエーションは十分に投資対効果が見合います。導入それ自体より、導入後に手を入れ続けられるかどうかが分かれ目です。
回復してわかったこと
設定を修正してから2週間後、eCPM は導入前の水準に戻り、さらに8%ほど上回るようになりました。メディエーションが本来の機能を発揮し始めたのです。
個人開発でメディエーションを扱うとき、最初の設定に時間をかけることが後の収益に大きく効きます。Rorkでアプリを素早く作れるようになったぶん、広告設定のような「コード外の作業」に時間を割く余裕も生まれました。それは良い変化だと思っています。
基本的なAdMob設定についてはRork AdMob広告収益化ガイドを、ATTの承認率を上げる実装についてはATT承認率を最大化する方法も参照してみてください。
まず AdMob コンソールでウォーターフォールのeCPMフロアを実態に近い値に設定し直すことが、今日からできる最初のアクションです。過去のデータがあれば、直近7日間の平均 eCPM から±10%の範囲を目安にしてみてください。
同じ失敗をしている方の、遠回りを少しでも短くできれば幸いです。お読みいただきありがとうございました。