取り組みの背景:なぜ収益分析ダッシュボードが個人開発者に必要か
個人でアプリを開発・運営していると、収益の全体像を把握するのが意外と難しいと感じることはありませんか。AdMob の広告収益はコンソールで確認でき、サブスクリプションは App Store Connect や RevenueCat で見られ、アプリ内課金はまた別のダッシュボード……とデータが分散しており、「今月のトータル収益はいくらか」「どの機能がユーザーの課金を促しているか」といった問いに即座に答えられない状況になりがちです。
この問題を根本から解決するのが、Firebase × BigQuery × Looker Studio を組み合わせた統合収益分析ダッシュボードです。Firebase Analytics のイベントデータを BigQuery に自動エクスポートし、そこにカスタムのクエリを書いて収益指標を集計し、Looker Studio で誰でも読めるビジュアルダッシュボードを作る——この一連の流れを Antigravity AI IDE を使って効率的に構築するのが本記事のテーマです。
Antigravity のエージェント機能とコード補完を活用することで、BigQuery の SQL クエリ作成・Cloud Functions のスクリプト実装・Looker Studio のデータソース設定を一気通貫で進められ、通常なら数日かかる初期構築を半日以下に短縮できます。
Firebase Analytics を導入済みで、より深い収益分析をしたいと感じている開発者
AdMob やサブスクリプション収益の推移を可視化してビジネス意思決定に活かしたい方
BigQuery や Looker Studio を試したいが、どこから手をつけてよいかわからない方
Antigravity を使ったデータパイプライン構築に興味がある方
アーキテクチャ全体像:データの流れを理解する
まずシステム全体のデータフローを整理します。構成要素は以下の通りです。
Firebase Analytics(イベント収集) : アプリ内のユーザー行動・課金イベントを収集するコア基盤
BigQuery Export(自動連携) : Firebase コンソールで1回設定するだけで、イベントデータが毎日 BigQuery に自動エクスポートされる
BigQuery(データウェアハウス) : SQL でカスタム集計・結合・フィルタリングができる Google 管理のデータウェアハウス
Cloud Functions for Firebase(変換・補完) : 外部 API(AdMob Reporting API、RevenueCat Webhooks など)のデータを BigQuery に書き込むグルーコード
Looker Studio(BI ダッシュボード) : BigQuery をデータソースとしてグラフ・表を作成し、共有リンクで閲覧できる Google の無料 BI ツール
Antigravity はこのパイプラインの実装とデバッグ を一貫してサポートします。SQL クエリの自動補完、Cloud Functions のボイラープレート生成、BigQuery スキーマ設計のアドバイス、エラーの根本原因特定まで、エディタを離れずに完結します。
Step 1:Firebase と BigQuery の連携設定を Antigravity で自動化する
1-1. Firebase BigQuery Export の有効化
Firebase コンソールで BigQuery リンクを有効化するだけで、イベントデータの日次エクスポートが始まります。手順は Firebase コンソール → プロジェクト設定 → 連携タブ → BigQuery の「リンク」から行います。
しかし実際の難所は、エクスポートされたデータのスキーマを理解してクエリを書くこと です。Firebase が BigQuery にエクスポートするテーブルはネストされた STRUCT 型で構成されており、慣れていないと途端に難しくなります。
Antigravity のチャット欄に次のように入力してみてください。
Firebase BigQuery エクスポートテーブルのスキーマを解説して。
events_YYYYMMDD テーブルから購入イベント(in_app_purchase)を
抽出して日別の収益合計を出すクエリを書いて。
Antigravity はテーブル構造の説明とともに、以下のようなクエリを生成します。
-- Firebase BigQuery エクスポートから日別IAP収益を集計
-- events_* はワイルドカードで全日付テーブルを対象にする
SELECT
-- イベント日付(タイムゾーン変換:UTC→JST)
DATE (TIMESTAMP_MICROS(event_timestamp), 'Asia/Tokyo' ) AS event_date,
-- 通貨コード(JPY / USD など)
( SELECT value . string_value
FROM UNNEST(event_params)
WHERE key = 'currency' ) AS currency,
-- 収益合計(マイクロ単位を通常単位に変換)
ROUND ( SUM (
( SELECT value . int_value
FROM UNNEST(event_params)
WHERE key = 'value' ) / 1000000 . 0
), 2 ) AS total_revenue_usd,
-- 購入件数
COUNT ( * ) AS purchase_count
FROM
-- プロジェクトIDとデータセット名は実際の値に置き換える
`YOUR_PROJECT_ID.analytics_XXXXXXXXX.events_*`
WHERE
event_name = 'in_app_purchase'
-- 直近90日を対象(コスト最適化)
AND _TABLE_SUFFIX >= FORMAT_DATE( '%Y%m%d' , DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY ))
GROUP BY
event_date, currency
ORDER BY
event_date DESC
このクエリをそのまま BigQuery のクエリエディタに貼り付けて実行できます。
1-2. データセットとテーブルの確認
BigQuery コンソールで analytics_XXXXXXXXX データセットが作成されていることを確認します。events_YYYYMMDD テーブル(日付ごとに1テーブル)と events_intraday_YYYYMMDD テーブル(当日のリアルタイムデータ)が自動生成されているはずです。
もしデータが空の場合、Firebase Analytics の初期化から収集開始まで最大24時間かかることがあります。Antigravity に「BigQuery に Firebase データが届いているか確認するクエリ」を生成してもらい、データ到着を検証しましょう。
Step 2:BigQuery でカスタム収益クエリを作成する
2-1. AdMob 収益データを BigQuery に取り込む
Firebase BigQuery エクスポートには AdMob の収益データは直接含まれません。AdMob Reporting API を使って収益データを取得し、BigQuery に書き込む Cloud Function を作成する必要があります。
Antigravity に次の指示を出します。
AdMob Reporting API から日次収益データを取得して
BigQuery の admob_revenue テーブルに書き込む
Node.js の Cloud Function を書いて。
Cloud Scheduler で毎朝8時に実行するスケジュール設定も含めて。
生成されるコードの骨格は以下のようになります。
// functions/src/syncAdMobRevenue.js
const { google } = require ( 'googleapis' );
const { BigQuery } = require ( '@google-cloud/bigquery' );
const bigquery = new BigQuery ();
const DATASET_ID = 'revenue_analytics' ; // BigQueryデータセット名
const TABLE_ID = 'admob_revenue' ; // 書き込み先テーブル名
/**
* AdMob Reporting API から昨日の収益データを取得して BigQuery に保存する
* Cloud Scheduler から HTTP POST でトリガーされる
*/
exports . syncAdMobRevenue = async ( req , res ) => {
try {
const auth = await google.auth. getClient ({
scopes: [ 'https://www.googleapis.com/auth/admob.readonly' ],
});
const admob = google. admob ({ version: 'v1' , auth });
// 昨日の日付範囲を設定(JST基準)
const yesterday = new Date ();
yesterday. setDate (yesterday. getDate () - 1 );
const dateStr = yesterday. toISOString (). split ( 'T' )[ 0 ];
const [ year , month , day ] = dateStr. split ( '-' ). map (Number);
const publisherId = process.env. ADMOB_PUBLISHER_ID ;
const report = await admob.accounts.networkReport. generate ({
parent: `accounts/${ publisherId }` ,
requestBody: {
reportSpec: {
dateRange: {
startDate: { year, month, day },
endDate: { year, month, day },
},
dimensions: [ 'APP' , 'AD_UNIT' , 'COUNTRY' ],
metrics: [ 'ESTIMATED_EARNINGS' , 'IMPRESSIONS' , 'CLICKS' ],
},
},
});
// BigQuery に書き込む行データを整形
const rows = (report.data || [])
. filter ( row => row.row)
. map ( row => ({
date: dateStr,
app_id: row.row.dimensionValues?. APP ?.value || '' ,
ad_unit: row.row.dimensionValues?. AD_UNIT ?.value || '' ,
country: row.row.dimensionValues?. COUNTRY ?.value || '' ,
// 収益はマイクロ単位(1,000,000で割ると USD)
estimated_earnings_usd:
(row.row.metricValues?. ESTIMATED_EARNINGS ?.microsValue || 0 ) / 1000000 ,
impressions: parseInt (row.row.metricValues?. IMPRESSIONS ?.integerValue || 0 ),
clicks: parseInt (row.row.metricValues?. CLICKS ?.integerValue || 0 ),
synced_at: new Date (). toISOString (),
}));
if (rows. length > 0 ) {
await bigquery. dataset ( DATASET_ID ). table ( TABLE_ID ). insert (rows);
console. log ( `✅ ${ rows . length }行のAdMobデータを BigQuery に書き込みました` );
}
res. status ( 200 ). json ({ success: true , rows: rows. length });
} catch (error) {
console. error ( 'AdMob同期エラー:' , error);
res. status ( 500 ). json ({ error: error.message });
}
};
このコードを Antigravity のエディタで開き、Cmd+I でインラインチャットを起動して「エラーハンドリングを強化して」「Cloud Functions v2 対応にして」などの追加指示を出すと、その場で改善されます。
2-2. 全収益ソースを統合するビュー(View)を作成する
IAP・AdMob・サブスクリプションの3ソースを横断して見るために、BigQuery の**ビュー(仮想テーブル)**を作成します。
-- 全収益ソースを統合する BigQuery ビュー
CREATE OR REPLACE VIEW `YOUR_PROJECT_ID.revenue_analytics.unified_revenue` AS
-- 1. アプリ内課金(IAP)収益(Firebase Analytics から)
SELECT
DATE (TIMESTAMP_MICROS(event_timestamp), 'Asia/Tokyo' ) AS date ,
'iap' AS revenue_type,
app_info . id AS app_id,
geo . country AS country,
ROUND (
( SELECT value . int_value FROM UNNEST(event_params) WHERE key = 'value' ) / 1000000 . 0 , 4
) AS revenue_usd,
user_pseudo_id AS user_id
FROM `YOUR_PROJECT_ID.analytics_XXXXXXXXX.events_*`
WHERE event_name = 'in_app_purchase'
AND _TABLE_SUFFIX >= FORMAT_DATE( '%Y%m%d' , DATE_SUB(CURRENT_DATE(), INTERVAL 365 DAY ))
UNION ALL
-- 2. AdMob 広告収益
SELECT
PARSE_DATE( '%Y-%m-%d' , date ) AS date ,
'admob' AS revenue_type,
app_id, country,
estimated_earnings_usd AS revenue_usd,
NULL AS user_id
FROM `YOUR_PROJECT_ID.revenue_analytics.admob_revenue`
WHERE PARSE_DATE( '%Y-%m-%d' , date ) >= DATE_SUB(CURRENT_DATE(), INTERVAL 365 DAY )
UNION ALL
-- 3. サブスクリプション収益(RevenueCat Webhook → BigQuery)
SELECT
DATE (purchased_at) AS date ,
'subscription' AS revenue_type,
app_id,
country_code AS country,
price_in_purchased_currency / exchange_rate AS revenue_usd,
subscriber_attributes . user_id AS user_id
FROM `YOUR_PROJECT_ID.revenue_analytics.revenuecat_events`
WHERE event_type = 'INITIAL_PURCHASE'
AND DATE (purchased_at) >= DATE_SUB(CURRENT_DATE(), INTERVAL 365 DAY )
このビューさえ作れば、Looker Studio からは1つのデータソースとして全収益を参照できます。
Step 3:Looker Studio でリアルタイム収益ダッシュボードを構築する
3-1. BigQuery をデータソースとして接続する
Looker Studio にアクセスし、「レポートを作成」→「データを追加」→「BigQuery」を選択します。先ほど作成した unified_revenue ビューを選択すれば、即座にダッシュボード構築を開始できます。
3-2. 主要 KPI ウィジェットの設計
Antigravity に「Looker Studio でどんなグラフ・指標を設置すべきか」を相談すると、個人開発者向けの推奨レイアウトを提案してくれます。典型的な構成は以下の通りです。
スコアカード(上段) :
今月の総収益(USD)
先月比(%増減)
DAU(Daily Active Users)
ARPU(Average Revenue Per User)
折れ線グラフ(中段) :
日別収益推移(revenue_type ごとに色分け:IAP / AdMob / サブスクリプション)
直近90日の累計収益
棒グラフ・表(下段) :
国別収益(上位10カ国)
アプリ別収益割合(複数アプリを運営している場合)
3-3. 計算フィールドで KPI を定義する
Looker Studio では「計算フィールド」を使って指標を定義できます。ARPU の計算フィールドは以下のように設定します。
// ARPU計算フィールド(Looker Studio の計算式)
SUM(revenue_usd) / COUNT_DISTINCT(user_id)
Antigravity に「Looker Studio の計算フィールドの書き方を教えて」と聞くと、Looker Studio 固有のシンタックスで計算式を生成してくれます。
Step 4:Antigravity エージェントで週次レポート自動配信パイプラインを構築する
ダッシュボードができたら、次は「毎週自動でレポートを作成してメールや Slack に送る」仕組みを作りましょう。Antigravity の Agent Panel(Cmd+Shift+A)を開き、次のような指示を入力します。
以下のパイプラインを実装して:
1. 毎週月曜8時に Cloud Scheduler でトリガー
2. BigQuery から先週の収益サマリーを取得
3. SendGrid でHTMLメールを整形して送信
4. Slack の #revenue チャンネルにも同じサマリーを投稿
5. Cloud Run でホスティング(最小インスタンス0)
Antigravity はこの複合要件を分解し、必要なファイル群を自動生成します。生成されるコアロジックの例を示します。
// services/weeklyReport.js
const { BigQuery } = require ( '@google-cloud/bigquery' );
const sgMail = require ( '@sendgrid/mail' );
const { WebClient } = require ( '@slack/web-api' );
const bigquery = new BigQuery ();
const slack = new WebClient (process.env. SLACK_BOT_TOKEN );
/**
* 先週の収益サマリーを BigQuery から取得する
*/
async function fetchWeeklyRevenue () {
const query = `
SELECT
revenue_type,
ROUND(SUM(revenue_usd), 2) AS total_revenue,
COUNT(DISTINCT user_id) AS unique_buyers,
COUNT(*) AS transaction_count
FROM \` YOUR_PROJECT_ID.revenue_analytics.unified_revenue \`
WHERE date BETWEEN DATE_SUB(DATE_TRUNC(CURRENT_DATE(), WEEK(MONDAY)), INTERVAL 7 DAY)
AND DATE_SUB(DATE_TRUNC(CURRENT_DATE(), WEEK(MONDAY)), INTERVAL 1 DAY)
GROUP BY revenue_type
ORDER BY total_revenue DESC
` ;
const [ rows ] = await bigquery. query ({ query });
return rows;
}
/**
* 収益データをHTMLメール形式に整形して SendGrid で送信する
*/
async function sendRevenueEmail ( revenueData ) {
sgMail. setApiKey (process.env. SENDGRID_API_KEY );
const totalRevenue = revenueData. reduce (( sum , r ) => sum + r.total_revenue, 0 ). toFixed ( 2 );
await sgMail. send ({
to: process.env. REPORT_EMAIL ,
from: process.env. FROM_EMAIL ,
subject: `📊 週次収益レポート ${ new Date (). toLocaleDateString ( 'ja-JP' ) }` ,
html: `
<h2>📊 先週の収益レポート</h2>
<p>総収益: <strong>$${ totalRevenue }</strong></p>
${ revenueData . map ( r =>
`<p>${ r . revenue_type }: $${ r . total_revenue }(${ r . unique_buyers || '-'}件)</p>`
). join ( '' ) }
<p><a href="${ process . env . LOOKER_DASHBOARD_URL }">→ 詳細ダッシュボードを見る</a></p>
` ,
});
console. log ( '✅ 週次レポートメール送信完了' );
}
/**
* Slack の #revenue チャンネルにサマリーを投稿する
*/
async function postSlackSummary ( revenueData ) {
const total = revenueData. reduce (( s , r ) => s + r.total_revenue, 0 ). toFixed ( 2 );
const lines = revenueData. map ( r => `• ${ r . revenue_type }: $${ r . total_revenue }` ). join ( ' \n ' );
await slack.chat. postMessage ({
channel: '#revenue' ,
text: `📊 *週次収益レポート* \n 総収益: *$${ total }* \n\n ${ lines }` ,
});
console. log ( '✅ Slack サマリー投稿完了' );
}
module . exports = { fetchWeeklyRevenue, sendRevenueEmail, postSlackSummary };
生成後は Cmd+I でインラインチャットを開き、「SendGrid の代わりに Resend を使うように変更して」「前週比を計算するコードを追加して」などの追加改善を行えます。
Step 5:収益分析から得られるインサイトをプロダクトに活かす
ダッシュボードを構築しただけでは意味がありません。重要なのは「データを見て何を変えるか」です。以下のパターンが特に参考になります。
AdMob 収益が特定の国で高い場合 : その国のユーザー向けに広告フォーマットや配信頻度を最適化する施策を実行します。Antigravity に「AdMob で eCPM を高める国別戦略 2026」を相談すると、優先度付きの施策リストを生成してくれます。
IAP 転換率が低い場合 : Firebase Analytics のファネルデータ(funnel_progression イベント)と課金イベントを BigQuery で結合し、どのステップで離脱しているかを特定します。この結合クエリも Antigravity に自然言語で依頼すれば即座に生成できます。
サブスクリプションの解約率が高い場合 : RevenueCat の CANCELLATION イベントと Firebase のエンゲージメントデータを BigQuery で突き合わせ、解約前にどのような行動パターンがあったかを分析します。
Antigravity × AdMob × Firebase Analytics: 広告収益を月100万円に伸ばすデータドリブン最適化完全マスターガイドでは、AdMob 側の最適化手法を詳しく解説していますので、ダッシュボード構築後の次のステップとして参照してください。
また、Antigravity × StoreKit 2 サブスクリプション収益最大化の上級戦略 では、解約防止・価格最適化・AI 分析を組み合わせた高度なサブスクリプション戦略を詳解しています。
よくあるエラーと対処法
BigQuery に Firebase データが届かない : Firebase コンソールで BigQuery リンクのステータスを確認してください。「有効」になっていても、新しくインストールしたアプリからのイベントが届くまで最大24時間かかります。events_intraday_YYYYMMDD テーブルに当日データが入っているかを確認することでリアルタイムの収集状況を確認できます。
BigQuery クエリで No matching signature エラー : Firebase のネストされた STRUCT に対して UNNEST() を使わずに直接フィールドにアクセスしようとするとこのエラーが出ます。Antigravity にエラーメッセージを貼り付けると、正しい UNNEST の使い方を提案してくれます。
Cloud Function のデプロイが失敗する : ENOSPC(ストレージ不足)エラーの場合、Cloud Build のキャッシュが肥大化している可能性があります。gcloud builds cancel で進行中のビルドをキャンセルし、キャッシュをクリアしてから再デプロイしてください。
Looker Studio でデータソースが認証エラーになる : BigQuery のデータセットに Looker Studio のサービスアカウントへ BigQuery Data Viewer ロールが付与されているか確認してください。
AdMob API のレート制限エラー : AdMob Reporting API の1日のリクエスト上限は200回です。Cloud Scheduler のトリガー頻度を落とすか、一度取得したデータをキャッシュして再リクエストを避ける実装を Antigravity に相談してください。
まとめ
Firebase × BigQuery × Looker Studio の収益分析ダッシュボードを Antigravity を使って構築する流れを解説しました。改めて全体のステップを振り返ります。
Firebase BigQuery Export を有効化し、イベントデータの自動蓄積を開始する
BigQuery で IAP・AdMob・サブスクリプションを統合する unified_revenue ビューを作成する
Looker Studio でリアルタイムの収益ダッシュボードを可視化する
Cloud Function + Cloud Scheduler + Slack 連携で週次レポートを自動配信するパイプラインを構築する
Antigravity を使うことで、SQL クエリの生成・Cloud Functions の実装・エラーの根本原因特定が格段に速くなります。一度このパイプラインを構築してしまえば、以降は毎日自動でデータが蓄積され、収益の全体像をリアルタイムで把握しながらプロダクトの意思決定ができるようになります。
データを根拠に意思決定できる個人開発者は、感覚だけで判断する場合と比べて収益最大化の打率が格段に高くなります。ぜひ本記事を参考に、ご自身の収益分析基盤を構築してみてください。
データパイプラインや分析基盤の設計