「広告を入れれば月5万円くらいにはなりますよね」という質問を、個人開発の相談で何度か受けたことがあります。答えは「DAUによります」なのですが、それだけでは相談者の役に立ちません。
収益化の判断が難しいのは、広告・買い切り・サブスクの3つが同じ単位で語られないからです。広告はeCPMで、買い切りは購入率で、サブスクは転換率とチャーンで語られる。単位が違うものを並べても、どれを先に入れるべきかは決まりません。
ですのでまず、3つを「1,000 DAUあたりの月次収益」という同じ土俵に置き直すところから始めます。実装手順はそのあとです。数えてから作ると、作る順番そのものが変わります。
収益モデルの選び方 — 3つの柱を理解する
アプリの収益化には大きく3つの柱があります。それぞれの特徴を正しく理解した上で、自分のアプリに最適な組み合わせを選ぶことが成功への第一歩です。
広告収入モデル
ユーザーに無料でアプリを使ってもらいながら、広告表示で収益を得るモデルです。ダウンロード数を最大化しやすい反面、1ユーザーあたりの収益(ARPU)は比較的低くなります。
向いているアプリの特徴として、日常的に繰り返し使うツール系アプリ、幅広い層をターゲットにしたカジュアルゲーム、ニュースや天気などの情報系アプリが挙げられます。
アプリ内課金(IAP)モデル
基本機能を無料で提供し、追加機能やコンテンツに対して個別に課金するモデルです。ユーザーが本当に価値を感じた機能にだけ支払うため、満足度が高くなりやすい特徴があります。
向いているアプリは、機能を段階的に拡張できる構造のアプリ、写真編集のフィルターやスタンプなどデジタルコンテンツ系、ゲームのアイテムやステージ追加などです。
サブスクリプションモデル
月額または年額で継続的に課金するモデルです。安定した定期収入(MRR)を得られるのが最大の魅力で、App StoreとGoogle Playの両方で開発者取り分が2年目以降85%に優遇されるメリットもあります。
向いているアプリは、継続的にコンテンツが更新されるアプリ、クラウド同期やバックアップなどサーバーコストが発生するアプリ、プロフェッショナル向けの高機能ツールです。
1,000 DAU で、3つのモデルがそれぞれいくら生むのかを数える
3つの柱の性格は上のとおりですが、これだけでは「自分のアプリではどれが効くのか」は決まりません。単位を揃えて計算してみます。
以下は 1,000 DAU のアプリを想定した試算スクリプトです。日本・iOS の eCPM 実測レンジの中央値と、ストア手数料15%(小規模事業者プログラム適用時)を前提にしています。
// monetization-mix.mjs
const DAU = 1000, DAYS = 30, CUT = 0.15;
const AD = { bannerImp: 4.0, interImp: 1.6, eCpmBanner: 180, eCpmInter: 1250 };
const adMonthly = (dau) => {
const banner = dau * AD.bannerImp * DAYS / 1000 * AD.eCpmBanner;
const inter = dau * AD.interImp * DAYS / 1000 * AD.eCpmInter;
return { banner, inter, total: banner + inter };
};
// 契約者数は漸化式で追う。定常値だけ見ると1年目を読み違える
const subSeries = (dau, monthlyConv, churn, months) => {
const newSubs = dau * monthlyConv;
let S = 0; const out = [];
for (let m = 1; m <= months; m++) { S = S * (1 - churn) + newSubs; out.push(S); }
return { newSubs, series: out, steady: newSubs / churn };
};
const mrr = (S) => S * 580 * (1 - CUT);
手元の Node v22.22.3 で実行した結果です。
| モデル | 内訳 | 1,000 DAU の月次収益 |
| 広告のみ | バナー 21,600円 + 遷移広告 60,000円 | 81,600円 |
| 広告除去IAP(月次購入率 0.2%) | 購入2.0人・売上1,666円 − 失う広告163円 | +1,503円 |
| 広告除去IAP(月次購入率 0.5%) | 購入5.0人・売上4,165円 − 失う広告408円 | +3,757円 |
| 広告除去IAP(月次購入率 1.2%) | 購入12.0人・売上9,996円 − 失う広告979円 | +9,017円 |
買い切りIAPの列に「失う広告」を引いている点に注目してください。広告除去を買ったユーザーからは、以後その分の広告収益が出ません。売上をそのまま足し込むと、実際より1割ほど多く見積もることになります。額が小さいので無視されがちですが、購入率が上がるほど効いてきます。
「転換率2〜5%」という数字は、分母が書かれていない
サブスクの試算でつまずくのはここでした。よく引用される「無料→有料の転換率2〜5%」は、多くの場合累計インストール数に対する累計課金者の割合です。これを「DAUの月次転換率」として使うと、まったく別の数字が出ます。
| 月次転換率 | churn | 新規契約 | 12ヶ月後の契約者(MRR) | 定常状態の契約者(MRR) | 定常の90%到達 |
0.4% (累計2.5%相当) | 3% | 4人/月 | 41人(20,125円) | 133人(65,733円) | 76ヶ月 |
| 5% | 4人/月 | 37人(18,128円) | 80人(39,440円) | 45ヶ月 |
| 8% | 4人/月 | 32人(15,587円) | 50人(24,650円) | 28ヶ月 |
| 12% | 4人/月 | 26人(12,889円) | 33人(16,433円) | 18ヶ月 |
2.5% (DAU月次と誤読) | 3% | 25人/月 | 255人(125,780円) | 833人(410,833円) | 76ヶ月 |
| 5% | 25人/月 | 230人(113,301円) | 500人(246,500円) | 45ヶ月 |
| 8% | 25人/月 | 198人(97,419円) | 313人(154,063円) | 28ヶ月 |
| 12% | 25人/月 | 163人(80,557円) | 208人(102,708円) | 18ヶ月 |
分母の読み方ひとつで、定常MRRの見積もりが6倍変わります。事業計画に貼る数字としては致命的な幅です。
1年目のチャーンは、思ったほど効かない
この表でもうひとつ意外だったのが、churn の効き方です。
定常状態で比べると、churn 3% と 12% では契約者数が133人と33人で4倍の差がつきます。ところが12ヶ月時点では41人と26人、MRRにして1.6倍の差にしかなりません。契約者数が定常に落ち着くまでに、churn 3% では76ヶ月かかるからです。低いチャーンは「積み上がるのが遅い」とほぼ同義でもあります。
ここから導かれる実務上の判断は、次のようなものになります。
- 1年目のMRRを押し上げたいなら、効くのはチャーン改善ではなく新規契約数(=転換率と母数)です
- チャーン改善への投資が数字に出るのは2年目以降。ただし出たときの効き幅は大きい
- リリース直後に解約防止機能を作り込むより、ペイウォールの露出面を増やすほうが先です
そして月次転換率0.4%の現実的な前提では、12ヶ月時点のサブスクMRRは churn 3% でも20,125円で、広告のみの81,600円に61,475円届きません。1,000 DAU規模でサブスクに一本化するのは、少なくとも1年目に関しては不利な賭けです。
私自身、この計算を先にやっていれば、初期のアプリでサブスクを主軸に据えるという判断はしなかったと思います。数字が悪かったのではなく、数字を見ずに決めていたのが問題でした。
Rork AIで広告を実装する
AdMobの基本セットアップ
Rork AIでアプリを生成する際に、広告実装を組み込む方法を解説します。
Rork AIへのプロンプト例:
「レシピ管理アプリを作成してください。
画面下部にAdMobのバナー広告を表示し、
レシピ一覧から詳細への遷移時にインタースティシャル広告を
5回に1回の頻度で表示する仕様にしてください。
広告IDはテスト用のものを使ってください」
Rork AIは、React Nativeベースのアプリにadmobライブラリを組み込み、適切な広告表示ロジックを生成してくれます。
広告配置のベストプラクティス
広告の配置場所はユーザー体験と収益の両方に大きく影響します。以下の原則を押さえておきましょう。
- バナー広告は画面下部に固定配置し、コンテンツ領域を圧迫しない
- インタースティシャル広告は自然な画面遷移のタイミングで表示する
- リワード広告は「広告を見てボーナスを獲得」という形でユーザーに選択肢を与える
- 操作の途中で突然広告が表示される設計は避ける(ストアのレビュー低下に直結する)
広告頻度の調整
広告の表示頻度は、収益とユーザー離脱率のバランスで決まります。一般的なガイドラインとして、インタースティシャル広告はアクション3〜5回に1回、リワード広告は1セッションあたり2〜3回が上限です。
リリース後にデータを見ながら調整していくことが前提なので、広告頻度をアプリ内で変更できるリモート設定の仕組みを最初から組み込んでおくことをお勧めします。
Rork AIへのプロンプト例:
「広告の表示頻度をFirebase Remote Configで
サーバー側から変更できる仕組みを追加してください。
デフォルト値はインタースティシャル5回に1回、
リワード広告1セッション3回上限にしてください」
アプリ内課金(IAP)の実装
課金アイテムの設計
アプリ内課金の成功は、何を有料にするかの設計にかかっています。鉄則は「無料部分だけでも十分に便利で、有料機能があるとさらに快適になる」という構造です。
課金アイテムの典型的なパターンとして、以下のようなものがあります。
- 機能アンロック型:無料版で制限されている機能を解放する(例: エクスポート機能、高度な検索)
- コンテンツ追加型:テーマ、フィルター、テンプレートなどのデジタルコンテンツ(例: プレミアムテーマパック ¥480)
- 容量拡張型:保存件数やクラウドストレージ容量の上限を引き上げる
- 広告除去型:すべての広告を非表示にする(例: 広告除去 ¥980 買い切り)
Rork AIでの実装手順
Rork AIへのプロンプト例:
「写真編集アプリに以下のアプリ内課金を追加してください:
1. プレミアムフィルターパック(¥480 / $3.99 買い切り)
2. 広告除去(¥980 / $6.99 買い切り)
3. 高解像度エクスポート(¥320 / $2.49 買い切り)
購入状態はAsyncStorageに保存し、
購入復元ボタンも設定画面に配置してください。
App Store / Google Play両対応でお願いします」
価格設定の考え方
アプリ内課金の価格設定は、ターゲット市場とアプリのカテゴリによって大きく異なります。参考として、以下のような価格帯が一般的です。
- 小規模な機能アンロック: ¥160〜¥480($0.99〜$2.99)
- コンテンツパック: ¥320〜¥980($1.99〜$6.99)
- 広告除去: ¥480〜¥1,480($2.99〜$9.99)
- プロ版フルアンロック: ¥1,480〜¥3,800($9.99〜$24.99)
迷った場合は、まず安めの価格でリリースし、コンバージョン率を見ながら調整していくアプローチが安全です。
サブスクリプションの実装
サブスクプランの設計
サブスクリプションは、月額と年額の2プランを用意するのが基本です。年額プランには月額の2ヶ月分程度の割引を付け、長期契約を促進します。
プラン設計例:
- Free: 基本機能(月5回のAI分析、広告あり)
- Pro Monthly: ¥580/月(無制限AI分析、広告なし、クラウド同期)
- Pro Annual: ¥4,800/年(月額換算¥400、2ヶ月分お得)
Rork AIでの実装
Rork AIへのプロンプト例:
「健康管理アプリにサブスクリプション機能を追加してください:
- 無料プラン: 基本的な記録機能、月5回のAI健康アドバイス
- Proプラン月額: ¥580/月、無制限AI分析、詳細レポート、広告非表示
- Proプラン年額: ¥4,800/年
無料トライアル7日間を提供し、
トライアル終了3日前にプッシュ通知でリマインドする仕様にしてください。
サブスク状態の管理にはrevenue-catライブラリを使ってください」
解約率を下げるための工夫
サブスクリプションで最も重要なのは、解約率(チャーンレート)をいかに低く保つかです。以下の施策が効果的です。
- 定期的に新機能や新コンテンツを追加し、継続する価値を実感させる
- サブスク開始直後のオンボーディングで、有料機能の使い方をしっかりガイドする
- 解約理由のアンケートを実施し、改善に活かす
- 解約しようとしたユーザーに割引オファーを提示する(Win-backフロー)
課金状態が「まだ分からない」時間を、型で持たせる
実装で最も多く踏んだ不具合は、価格でも配置でもなく、起動直後の数百ミリ秒でした。
RevenueCat であれ StoreKit 直叩きであれ、課金状態の取得は非同期です。アプリが起動してから購入情報が返るまでのあいだ、状態は「有料」でも「無料」でもなく「まだ分からない」です。ところが実装では、たいてい boolean 1個で持ってしまいます。
// よくある実装。isPro の初期値は false になる
const [isPro, setIsPro] = useState(false);
useEffect(() => { Purchases.getCustomerInfo().then(i => setIsPro(!!i.entitlements.active.pro)); }, []);
return isPro ? <PremiumScreen /> : <><BannerAd /><FreeScreen /></>;
このコードは、課金済みのユーザーが起動するたびに一瞬だけ広告を表示します。ストアレビューに「課金したのに広告が出る」と書かれる典型的な原因です。ユーザーからは間欠的にしか再現しないため、報告を受けても手元で確認できません。
修正は、状態を3値にするだけです。
// entitlement.ts
export type Entitlement = 'unknown' | 'entitled' | 'notEntitled';
export function useEntitlement(): Entitlement {
const [state, setState] = useState<Entitlement>('unknown');
useEffect(() => {
let alive = true;
Purchases.getCustomerInfo()
.then(info => {
if (!alive) return;
setState(info.entitlements.active['pro'] ? 'entitled' : 'notEntitled');
})
.catch(() => {
// 取得失敗時も notEntitled に倒さない。オフライン起動で有料ユーザーに広告が出る
if (alive) setState('unknown');
});
return () => { alive = false; };
}, []);
return state;
}
重要なのは、unknown のときの既定値を画面の面ごとに変えることです。ひとつの既定で揃えようとすると、必ずどちらかが壊れます。
// 面ごとに「分からないとき」の振る舞いを分ける
export const shouldShowAds = (s: Entitlement) => s === 'notEntitled'; // 不明なら出さない
export const shouldShowPaywall = (s: Entitlement) => s === 'notEntitled'; // 不明なら出さない
export const canUnlockPremium = (s: Entitlement) => s === 'entitled'; // 不明なら開けない
export const shouldShowLoader = (s: Entitlement) => s === 'unknown';
広告とペイウォールは「不明なら出さない」、プレミアム機能の解放は「不明なら開けない」。逆向きに見えますが、どちらも誤りが起きたときに損をするのが誰かで決めています。広告を出し損ねても失うのは数円ですが、課金済みユーザーに広告を見せると信頼を失います。逆に、未課金ユーザーに有料機能を開けてしまえば収益がそのまま漏れます。
この4本の関数を先ほどのシナリオに通すと、挙動の差がはっきりします。
| 状況 | 3値ゲート | boolean 1個 |
| 広告 | ペイウォール | 機能解放 | ローダー | 広告 | 機能解放 |
| 起動直後・復元未完了(課金済み) | — | — | — | 出す | 出す | — |
| 起動直後・復元未完了(未課金) | — | — | — | 出す | 出す | — |
| 復元完了・課金あり | — | — | 出す | — | — | 出す |
| 復元完了・課金なし | 出す | 出す | — | — | 出す | — |
| オフライン起動・キャッシュ無し | — | — | — | 出す | 出す | — |
太字にした2行が、boolean 1個の実装で課金済みユーザーに広告が出てしまうケースです。オフライン起動のほうは復元がタイムアウトするまで続くので、数百ミリ秒では済みません。
Rork AI にこの構造を作らせるときは、プロンプトで型を先に指定しておくと素直に従ってくれます。
Rork AI へのプロンプト例:
「課金状態を 'unknown' | 'entitled' | 'notEntitled' の3値の型で管理してください。
広告表示とペイウォール表示は notEntitled のときのみ、
プレミアム機能の解放は entitled のときのみ許可し、
unknown の間はスケルトンを表示してください。
getCustomerInfo が失敗した場合も notEntitled に倒さないでください」
「isProフラグを作って」と頼むと boolean で返ってきます。壊れ方まで含めて指示するのが、生成AIに実装させるときのコツだと感じています。
複合型マネタイズ戦略
実際のアプリでは、単一のモデルだけでなく複数を組み合わせるのが一般的です。効果的な組み合わせパターンをご紹介します。
パターン1: 広告 + 広告除去IAP
最もシンプルな組み合わせです。無料ユーザーには広告を表示し、広告を煩わしく感じたユーザーには買い切りの広告除去を提供します。
収益構造として、大多数のユーザーからは広告収入を、コアユーザーからはIAP収入を得る二重の収益源になります。
パターン2: フリーミアム + サブスク
基本機能を無料で提供し、高度な機能をサブスクで解放するモデルです。SaaS型のアプリに最適で、安定した月次収入を見込めます。
ポイントは、無料版でも「使えるアプリ」であること。制限が厳しすぎるとユーザーが離脱し、緩すぎると課金動機が生まれません。
パターン3: 広告 + サブスク + IAP(フルスタック)
すべての収益モデルを組み合わせるフルスタック型です。無料ユーザーには広告、ライトユーザーにはIAP、ヘビーユーザーにはサブスクと、ユーザーセグメントごとに最適な収益化を行います。
管理が複雑になるため、まずはシンプルなモデルから始めて段階的に追加していくことをお勧めします。
リリース後の収益最適化
A/Bテストの実施
収益化の各要素は、仮説に基づいて設計した後、データで検証していく必要があります。A/Bテストで検証すべき主要な項目は以下の通りです。
- 広告の配置場所と表示頻度
- 課金アイテムの価格帯
- ペイウォール(課金画面)のデザインとコピー
- 無料トライアルの期間(3日 vs 7日 vs 14日)
- サブスクプランの構成(月額のみ vs 月額+年額 vs 月額+年額+永久)
Rork AIへのプロンプト例:
「Firebase A/Bテストの機能を追加してください。
テスト対象はサブスクリプション画面のレイアウトで、
パターンA(機能リスト重視)とパターンB(社会的証明重視)の
2パターンを50:50で出し分けてください。
コンバージョンイベントは'subscription_started'で計測します」
KPIモニタリング
収益の健全性を測る主要KPIを日常的にモニタリングしましょう。
- ARPU(ユーザーあたり平均収益): 広告 + IAP + サブスクの合計をDAUで割った値
- コンバージョン率: 分母を必ず明記する。「累計インストールに対する累計課金者」なら2〜5%が目安ですが、「DAUに対する月次」なら0.3〜0.8%程度です(混同すると見積もりが6倍ずれます)
- LTV(顧客生涯価値): 1ユーザーがアプリを使い続ける間に生み出す総収益
- チャーンレート: 月あたりのサブスク解約率(目標: 5%以下)
- ROAS(広告費用対効果): ユーザー獲得広告費に対する収益の比率
季節性とプロモーション
年末年始、新学期、ブラックフライデーなどの時期には、期間限定セールや特別オファーが効果的です。サブスクの年額プランを20%オフにする、限定コンテンツパックを配布するなど、イベントに合わせた施策を計画しておきましょう。
よくある失敗パターンと対策
無料版が使いものにならない
課金してほしいあまりに無料版の機能を絞りすぎると、ユーザーはアプリの価値を実感する前に離脱してしまいます。「無料でも十分便利、課金するともっと便利」のバランスを意識しましょう。
広告が多すぎる
収益を優先して広告を増やしすぎると、ストアの評価が急落します。特にインタースティシャル広告の頻度には注意が必要です。ユーザーレビューで「広告が多い」というコメントが増えてきたら、即座に頻度を見直しましょう。
価格が高すぎる / 安すぎる
価格設定は地域やカテゴリによって最適値が異なります。競合アプリの価格をリサーチした上で、A/Bテストで検証するのが最も確実な方法です。
サブスク解約後のフォローがない
解約したユーザーを放置せず、一定期間後に「復帰割引」を提供するWin-backキャンペーンを実施しましょう。既存ユーザーの復帰は、新規ユーザー獲得よりもはるかにコスト効率が良いです。
個人開発者の視点から(実体験メモ)
Rorkでアプリを組みながら収益化を触っていて、考えが変わった点が3つあります。
ひとつは、収益モデルを決める作業が実装より先に来るということです。以前は「とりあえず広告を入れて、伸びたらサブスクを検討する」という順番で進めていました。ところが広告前提で作った画面設計は、あとからペイウォールを差し込む場所がありません。バナーのために確保した下部の帯と、価値を伝えるための余白は、同じ場所を取り合います。数えてから作ると、この衝突を先に避けられます。
ふたつめは、収益化のコードほど生成AIとの相性が悪いということです。画面レイアウトやAPI呼び出しは、生成されたものをそのまま使ってもだいたい動きます。ところが課金まわりは、動いているように見えて壊れている状態が長く続きます。3値ゲートの話がまさにそれで、シミュレータでも実機でも「正常に動く」ように見えてしまいます。生成させたあとに、壊れ方のほうを自分でテストする必要があります。
みっつめは、eCPMの数字を人から聞くのをやめたことです。同じ「バナー180円」でも、アプリのカテゴリと地域構成で倍は動きます。他人の数字を前提に事業計画を立てると、あとで説明のつかない差が出ます。上の試算スクリプトも、そのまま使うのではなく、AdMobの管理画面から自分の実測値を入れて回すためのものとして書きました。定数を4つ差し替えるだけで、自分のアプリの数字になります。
全体を振り返って — 数えてから作る
3つのモデルを同じ土俵に並べてみると、1,000 DAU規模での順番はかなりはっきりします。まず広告で81,600円の土台を作り、そこに広告除去IAPを数千円単位で足す。サブスクは1年目のMRRではなく、2年目以降の積み上がりを狙って早めに種を蒔いておく——という順番です。
ただしこの結論は、私が入れた定数の上に立っています。eCPMもチャーンも、アプリのカテゴリと地域構成で簡単に倍動きます。
ですので次の一歩としてお勧めしたいのは、記事の実装に手をつける前に、上の monetization-mix.mjs の定数4つ(eCpmBanner / eCpmInter / 月次転換率 / churn)を、AdMobとApp Store Connectの管理画面から拾った自分の実測値に差し替えて一度回してみることです。5分で終わります。そこで出た数字が、どのモデルから実装すべきかを教えてくれます。
私自身、この順番を逆にして時間を溶かしました。同じ回り道をせずに済めば嬉しく思います。お読みいただきありがとうございました。