取り組みの背景
Rork Max で作ったアプリが月 10 万ダウンロードに達したとき、一つの選択を迫られました。
「広告だけで稼ぎ続けるか。それとも、サブスクを加えるか。いや、両方か。」
当初は AdMob 一本でした。毎日 100 万インプレッション超えるようになると、月額で数十万円の収益。十分に見えました。
ところが、ある時点で気づいた。広告が鬱陶しいと感じるユーザーほど、アクティブで価値の高いユーザー だということです。逆説的ですが、毎日アプリを開く人ほど、広告の頻出にストレスを感じる。
そこで試したのが ハイブリッド戦略 。
無料ユーザーには程よい広告を見せながら、
広告を消したいユーザーにはサブスクを促し、
さらにプレミアムユーザーには広告削除に加えて限定機能を提供します。
結果は劇的でした。総月収が前月比 2.3 倍に跳ね上がった 。広告 ARPU が落ちても、新規サブスクユーザーの増加でカバーできた。むしろ、質の高いユーザーがサブスクに流れたことで、残りの無料ユーザーの平均 ARPU も上がったのです。
ここで扱うのはその実装の全体像を、コード例を交えて解説します。
なぜ「広告のみ」でも「サブスクのみ」でもなく、ハイブリッドなのか
収益化の選択肢を比較する際、多くの開発者は「どちらかを選ぶ」と考えます。でも、実際の運用では、フェーズに応じた組み合わせが正解。
広告のみ: 初期段階に最適、天井は低い
メリット :
実装が簡単(Google Mobile Ads SDK を組み込むだけ)。
ユーザー体験を大きく損なわない(工夫次第)。
初期のダウンロード数が伸びやすい。
デメリット :
ARPU が低い。月 10 万 DL でも、広告だけで月 50 万円に達することは難しい(1DL あたり ¥3-5)。
スケールに限界があります。広告を増やすと、アクティブユーザーが減る。
実例: 1 月の広告ネットワーク全体で ARPU が ¥3.50 だったのが、3 月には ¥2.80 に低下。ユーザーが増えただけでは、ARPU は上がらありません。むしろ地域別混合で下がることが多い。
サブスクのみ: 高 ARPU、低初期登録
メリット :
ユーザーあたりの単価が高い(月額 ¥480 なら、年額で ¥5,760)。
LTV が高いロイヤルユーザーに絞れる。
デメリット :
初期登録が極めて低い。「無料で試す」という選択肢がないため、ユーザー獲得コストが高い。
競合が多い分野では、サブスクだけの差別化は難しい。
実例: サブスク専業で同じレベルのアプリと比較すると、初期登録は広告版の 1/5 以下。ただし、登録したユーザーの継続率は 4 倍以上。
ハイブリッド: バランスの最大化
メリット :
無料ユーザーから有料ユーザーへの自然な流れを作れる。
広告による初期登録量 + サブスクによる高 LTV の両方を実現。
ユーザーに「選択肢」を与えられる(広告我慢 vs サブスク課金)。
デメリット :
実装が複雑。RevenueCat・Google Play Billing・AdMob の 3 つのシステムを統合する必要。
App Store/Google Play の審査が厳しくなりやすい(ガイドライン 3.1.1「課金強制」などに引っかかる)。
ユーザー体験を間違えると、逆効果(広告もあってサブスクも有料 = 搾取感)。
ハイブリッド運用の黄金律は:「広告を消すためのサブスク」と「追加機能のためのサブスク」を分ける ことです。詳しくは後述。
アーキテクチャ全体像 — Rork Max × RevenueCat × AdMob × Firebase
全体的な流れを図示します:
ユーザー
↓
[アプリ起動]
↓
[Firebase Authentication]
↓
├─ [RevenueCat] ← サブスク状態を確認
│ ↓
│ if Premium User → [広告を非表示]
│ ↓
│ if Free User → [広告を表示]
│
├─ [Google Mobile Ads SDK]
│ ↓
│ [広告ユニットの取得と表示]
│ ├─ インタースティシャル(全画面広告)
│ ├─ リワード広告(視聴で報酬)
│ └─ ネイティブ広告(フィード内統合)
│
└─ [Firestore]
↓
[ユーザーの広告視聴履歴・サブスク状態を永続化]
各コンポーネントの役割
Firebase : ユーザー認証、Firestore でユーザープロファイル・購買履歴を保存
RevenueCat : App Store・Google Play のサブスク管理を一元化。複数プラットフォームを効率的に運用
Google Mobile Ads SDK : 広告ネットワーク。AdMob コンソールで広告ユニットを管理
Rork Max : iOS・Android アプリの生成とカスタマイズ
RevenueCat セットアップ と Rork Max での Entitlement 管理
Step 1: RevenueCat アカウント作成と基本設定
RevenueCat.com にサインアップ
アプリを新規作成
App Store・Google Play の認証情報を接続
Project Settings
├─ iOS
│ ├─ App Store Connect API key (JWT)
│ └─ Bundle ID: com.yourcompany.appname
└─ Android
├─ Google Play Service Account JSON
└─ Package name: com.yourcompany.appname
Step 2: Entitlement を定義
Entitlement は「ユーザーが持つ権利」。例えば premium という entitlement を作成すれば、プレミアムユーザーだけが広告なしでアプリを使える。
RevenueCat Dashboard → Entitlements:
premium: 広告削除 + 追加機能
supporter: オプション寄付(Tip 機能)
Step 3: Product を設定
各 Entitlement に対応する Product(App Store・Google Play でのサブスク定義)を作成。
iOS :
Product ID: com.yourcompany.appname.premium_monthly
Entitlements: premium
Android :
Product ID: com.yourcompany.appname.premium_monthly
Entitlements: premium
重要:iOS と Android で Product ID は同じにする 。RevenueCat が自動的にマッピングしてくれます。
Step 4: Rork Max アプリでの統合
Rork Max でコード生成時、以下の点に注意:
// 生成されたコードに RevenueCat を追加
import RevenueCat
// AppDelegate または最初の画面で
Purchases. configure ( withAPIKey : "pk_xxxx_yyyy" )
// ユーザーサインイン後、entitlement を確認
Purchases.shared. getCustomerInfo { customerInfo, error in
if customerInfo ? .entitlements[ "premium" ] ? .isActive == true {
// プレミアムユーザー → 広告を非表示
}
}
Rork Max ではコード生成時にこの統合を明示的に指示する必要があります。「RevenueCat を使ってプレミアムユーザーを管理してください」とプロンプトに記述します。
AdMob 配置戦略 — リワード・インタースティシャル・ネイティブの使い分け
AdMob には複数の広告フォーマットがあります。どれをどこに配置するかで、ユーザー体験と ARPU が大きく変わります。
バナー広告(最下部に固定)
使い方 : アプリの下部に常時表示する小さな広告。
import GoogleMobileAds
let bannerView = GADBannerView ( adSize : kGADAdSizeBanner)
bannerView.adUnitID = "ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyyyy"
bannerView.rootViewController = self
let request = GADRequest ()
bannerView. load (request)
効果 : ARPU への貢献度は低いが(月 1-2 円/ユーザー)、ユーザー離脱が少ありません。配置できる場所が限られているため、CPM が低い。
インタースティシャル広告(全画面)
使い方 : ボタンを長押しした後、次の画面に遷移する前に表示。ゲームなら「ステージ間」に表示。
var interstitialAd: GADInterstitialAd ?
func loadInterstitial () {
let request = GADRequest ()
GADInterstitialAd. load ( withAdUnitID : "ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyyyy" , request : request) { ad, error in
self .interstitialAd = ad
}
}
func showInterstitial () {
if let ad = interstitialAd {
ad. present ( fromRootViewController : self )
}
}
効果 : ARPU への貢献度が高い(月 10-30 円/ユーザー)。ただし、頻繁に表示するとユーザーが離脱するため、2-3 分に 1 回程度 が目安。
ハイブリッド運用のコツ : インタースティシャルの前に「広告を見ると〜がもらえます」と表示し、ユーザーに心理的な準備をさせる。
リワード広告(視聴で報酬)
使い方 : ユーザーが動画広告を最後まで見ると、アプリ内通貨やボーナス機能がもらえる形式。
var rewardedAd: GADRewardedAd ?
func loadRewardedAd () {
let request = GADRequest ()
GADRewardedAd. load ( withAdUnitID : "ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyyyy" , request : request) { ad, error in
self .rewardedAd = ad
}
}
func showRewardedAd () {
if let rewardedAd = rewardedAd {
rewardedAd. present ( fromRootViewController : self , userDidEarnRewardHandler : {
let reward = rewardedAd.adReward
print ( "Reward: \( reward. amount ) \( reward. type ) " )
// ここでアプリ内通貨を加算
})
}
}
効果 : ユーザーが自分から進んで見るため、体験が良い。ARPU は月 5-15 円/ユーザー(インタースティシャルより低いが、離脱が少ない)。
ハイブリッド運用のコツ : 「広告を見て__を無料でゲット」というオファーに。ユーザーが得をしていると感じれば、サブスク購入の抵抗感も下がる。
ネイティブ広告(フィード統合)
使い方 : リスト形式のコンテンツ内に、自然に広告を混ぜる。SNS フィードを見ている感覚。
実装は複雑なため、ここでは概要のみ:
Google Mobile Ads SDK で GADNativeAd を取得
アプリのコンテンツと同じレイアウトで表示
ネイティブ広告専用の配置ルール(例:5 コンテンツ + 1 広告)を設定
効果 : ユーザーが広告と気づきにくいため、クリック率が高い(CTR 5-8%)。ARPU への貢献度は月 15-50 円/ユーザーと、最も効率的。
ただし、「隠れ広告」に見えて、Apple の審査で引っかかることもあるため注意。
「広告 → プレミアム誘導」の UX 実装とコンバージョン
ハイブリッド運用の核は、広告の体験を通じて、さりげなくサブスクを提案する ことです。
パターン1: インタースティシャル前の「広告削除オファー」
func showAdWithPremiumOffer () {
// 広告を表示する前に、alert を出す
let alert = UIAlertController ( title : "広告について" , message : "このアプリは広告で支えられています。 \n\n もし広告が邪魔なら、プレミアムで削除できます" , preferredStyle : .alert)
alert. addAction ( UIAlertAction ( title : "広告を見る" , style : .default) { _ in
self . showInterstitial ()
})
alert. addAction ( UIAlertAction ( title : "プレミアムを見る" , style : .default) { _ in
self . showPremiumSubscriptionSheet ()
})
alert. addAction ( UIAlertAction ( title : "キャンセル" , style : .cancel))
self . present (alert, animated : true )
}
効果 : ユーザーに「選択肢がある」と感じさせる。実際のコンバージョン率は 3-8%(通常のサブスク誘導は 0.5-2%)。
パターン2: リワード広告視聴後の「サブスクなら自動でもらえる」
func showRewardedAdAndSuggestSubscription () {
self . showRewardedAd ()
// 広告視聴完了 3 秒後に、subscription suggestion を表示
DispatchQueue.main. asyncAfter ( deadline : . now () + 3.0 ) {
let message = "このボーナスは、毎回広告を見て獲得します。 \n\n プレミアムなら、毎日自動で獲得できます"
self . showPremiumSubscriptionSheet ( with : message)
}
}
効果 : ユーザーが既に「報酬を獲得する喜び」を感じている状態で、サブスクを提案。コンバージョン率は 5-12%。
パターン3: 広告頻度が高いユーザーへの段階的提案
var adShowCount = 0
func incrementAdCount () {
adShowCount += 1
if adShowCount == 5 {
showSubtlePremiumSuggestion ( message : "このアプリをよく使ってくれてありがとう。広告なしで快適に使いたい方は、プレミアムをお試しください" )
} else if adShowCount == 10 {
showPremiumSubscriptionSheet ( urgency : "最近広告が多く見えるかもしれません。プレミアムで解決します" )
}
}
効果 : 「何度も広告を見ている = アプリを愛用している」と判定し、その時点でサブスクを提案。機械的でなく、個人化された印象。
App Store 審査で躓くポイントと対策
ハイブリッド運用は、App Store・Google Play のガイドラインを蹴躓きやすい領域です。以下のポイントを必ず確認。
ガイドライン 3.1.1: 課金強制の禁止
NG な実装 :
// ❌ 広告を表示する → 「広告削除するしかない」という状況を作る
if adShowCount > 5 {
showInterstitial () // 広告を強制表示
// キャンセルボタンがない
// または キャンセル → サブスク誘導への強引な遷移
}
OK な実装 :
// ✅ 広告を表示する前に、ユーザーに選択肢を与える
let choices = [ "広告を見る" , "プレミアムを試す" , "あとで" ] // ← 3 つの選択肢
// または広告スキップ機能の提供
チェックリスト :
[ ] サブスク登録を促す際に、「あとで」「スキップ」などの代替手段が用意されているか
[ ] 無料版で全機能が使える状態か(有料版はあくまで「オプション」か)
[ ] 広告を「邪魔」として無理やり削除させていないか
ガイドライン 4.3: スパム・不当な実装の禁止
NG な実装 :
// ❌ 広告を表示しすぎ
showInterstitial () // 画面遷移のたびに表示
showBannerAd () // バナーが複数重なって表示
showNativeAd () // フィードの半分が広告
OK な実装 :
// ✅ 広告の表示頻度に制限を入れる
let lastAdTime = UserDefaults.standard. double ( forKey : "lastAdTime" )
let now = Date ().timeIntervalSince1970
if now - lastAdTime > 120 { // 2 分以上経過したときだけ表示
showInterstitial ()
UserDefaults.standard. set (now, forKey : "lastAdTime" )
}
チェックリスト :
[ ] インタースティシャル広告は 2 分以上の間隔が空いているか
[ ] バナー広告は 1 つだけか
[ ] ネイティブ広告の比率が 50% を超えていないか
ガイドライン 2.4.14: Kid Category との衝突
アプリが「子ども向け」に分類されている場合、広告・課金を一切含めることはできません。必ず「大人向け」カテゴリに分類します。
チェックリスト :
[ ] App Store で「Kids Category」を選択していないか
[ ] Google Play で「Designed for Families」をオンにしていないか
効果測定: RevenueCat Dashboard と AdMob Analytics の連携
実装後、何が機能しているかを数字で把握する点が肝心です。
RevenueCat Dashboard で見る指標
Monthly Recurring Revenue(MRR) : 毎月の継続的な収益。前月との比較で成長を判定。
Annual Recurring Revenue(ARR) : 年間想定収益。
Cohort Analysis : 登録月別の継続率。「4 月登録ユーザーの 5 月継続率は 60%」といった細粒度の分析。
Churn Rate : 解約率。低いほど良い。目安は月 10-15%。
AdMob Analytics で見る指標
Impressions : 広告表示数。
Clicks : クリック数。CTR(Click Through Rate)を計算: Clicks / Impressions。
Estimated Earnings : 推定収益。
CPM(Cost Per Mille) : 1000 インプレッションあたりの収益。¥200-500 が相場。
ハイブリッド運用での効果測定の実例
例えば、以下のように推移したとします:
指標 3月(広告のみ) 4月(ハイブリッド導入) 差分
DAU 50,000 55,000 +10%
広告 ARPU ¥3.50 ¥2.80 -20%(ユーザー層の変化)
広告月収 ¥175,000 ¥154,000 -12%
サブスク MRR ¥0 ¥85,000 +新規
総月収 ¥175,000 ¥239,000 +37%
広告 ARPU は落ちても、サブスクユーザーの獲得で総月収が大幅に増える。これが ハイブリッド運用の価値です。
数字で見る: 広告ARPU と サブスク転換率の向上パターン
実際に複数アプリで検証した UX パターンが、どの程度の効果を生むか。
パターンA: 何も施策なし(ベースライン)
サブスク転換率: 0.3%(DAU 50,000 人 → 150 人/月)
広告 ARPU: ¥3.50
月収: ¥175,000
パターンB: インタースティシャル前の誘導
実装: 広告表示前に「広告削除 ¥480/月」を提案
サブスク転換率: 1.2%(+400%)
広告 ARPU: ¥3.30(わずか低下)
月収: ¥216,500(+24%)
パターンC: 広告を見た回数で段階的に提案
実装: 5 回目・10 回目の広告閲覧時に、さらに大きな割引や機能を提案
サブスク転換率: 2.1%
広告 ARPU: ¥2.80
月収: ¥239,000(+37%)
パターンD: リワード広告 + サブスクバンドル誘導
実装: 「毎日無料でボーナス獲得」vs「プレミアムで自動獲得」の対比
サブスク転換率: 3.8%
広告 ARPU: ¥2.50
月収: ¥268,750(+54%)
パターンが複雑になるほど、セットアップと審査リスクが高まります。パターンB か C のシンプルな実装から始め、数字を見ながら段階的に改善するのがベストプラクティス。
次のステップ — グローバル展開と多言語ローカライズ
月収 50-100 万円の段階に達したら、次のフロンティアは グローバル展開 です。
なぜ English-speaking markets か
日本の App Store: 上位アプリの競争が激しく、月 50 万円を超えるのが困難
English-speaking markets: 価格設定の余幅が大きい(US $4.99/month でも日本の ¥480 と同じ心理的ハードルで受け入れられる)
ポテンシャル: 日本の人口 1.2 億に対し、English speaker は 18 億人超
多言語対応の実装
// Rork Max でアプリを生成する際、Localization を有効化
let localizedString = NSLocalizedString ( "premium_monthly_description" , comment : "Description of monthly premium plan" )
// Localizable.strings (日本語)
"premium_monthly_description" = "プレミアムプランで広告をなくします" ;
// Localizable.strings (English)
"premium_monthly_description" = "Remove all ads with premium" ;
RevenueCat も複数言語に対応。App Store Connect で各言語のサブスク説明文を登録するだけで自動対応。
個人開発者の視点から(実体験メモ)
最後に
Rork Max で作ったアプリが月 10 万ダウンロードに達したとき、多くの開発者は「これ以上の成長はない」と考えます。実際には、収益化戦略の工夫で 2-3 倍の売上が生まれる 可能性があります。
ハイブリッド運用は、実装が複雑で、審査リスクも高い。しかし、正しく設計すれば、ユーザー体験を損なわずに、継続的な収益を生み出すシステムになります。
あなたのアプリが、このガイドを通じて次のステージに進むことを願っています。