第04章:Reactでカスタムイベント送信📣🧑💻
この章は「ボタンを押した」「保存した」「AI整形した」みたいなあなたのアプリ固有の行動を、Analytics(GA4)に送れるようになる回です📊✨ 送れたら、Console の DebugView で「今まさに飛んでる!」を確認します👀🔥 (Firebase)
この章のゴール🏁✨

- React のクリックなどをトリガーに、
logEvent()で カスタムイベントを送信できる📤 (Firebase) - DebugView でイベントを目視確認できる👀🧪 (Firebase)
- 「イベント名・パラメータの作法」を守って、あとで分析しやすい形にできる🧠🧩 (GA4Spy)
まず“作法”だけ先に押さえる🧠🧯
1) できれば「推奨イベント」→無理なら「カスタム」🎯
GA4には、分析しやすいように 推奨イベント名が用意されてます(該当しそうなら寄せるのが吉)📚✨ (Google for Developers)
ただ、メモアプリの memo_save みたいにピッタリが無いなら、カスタムでOKです🙆♂️
2) イベント名のルール(地味だけど超重要)🧷

- 英小文字+
_で統一すると事故りにくい(例:memo_save) - 40文字以内/英数字と
_/先頭は英字…などの命名ルールがあります✍️ (GA4Spy) firebase_/google_/ga_みたいな 予約プレフィックスは避けるのが安全です🚫 (Google ヘルプ)
3) パラメータは「少なく・固定」🧩
- 1イベントあたり 最大25個まで(上限あり)📦 (Google ヘルプ)
- イベント種類(イベント名)はプロジェクトあたり 500種類を超えないように(増やしすぎ注意)⚠️ (Firebase)
- 「同じイベントなのに param 名が毎回ブレる」が一番つらいので、表を作って固定が正解です🗒️✨
4) 個人情報(PII)は絶対に送らない🙅♂️🔒
メール・電話番号・住所・氏名など、個人を直接特定できる情報は イベントに入れないでください🚫 (Google ヘルプ)
(例:user_email みたいなパラメータ名は論外…!😇)
実装:Reactからイベントを送る🛠️✨
ここでは「保存ボタンで memo_save を送る」を作ります📝💾
手順1:Analyticsを“安全に初期化”する(ブラウザだけ)🌐

Reactでも、SSR混在(Next.jsなど)だと「サーバー側で落ちる」ことがあるので、isSupported() を挟んでおくのが安心です🧯 (Firebase)
// src/lib/analytics.ts
import { getAnalytics, isSupported, logEvent, type Analytics } from "firebase/analytics";
import { app } from "./firebaseApp"; // initializeApp済みのappをexportしてる想定
let analytics: Analytics | undefined;
export async function getAnalyticsSafe() {
if (analytics) return analytics;
// Analyticsが使える環境かチェック(ブラウザ要件など)
if (await isSupported()) {
analytics = getAnalytics(app);
return analytics;
}
return undefined;
}
export async function track(eventName: string, params?: Record<string, unknown>) {
const a = await getAnalyticsSafe();
if (!a) return; // SSRや未対応環境では何もしない
logEvent(a, eventName, params);
}
getAnalytics()/logEvent()/isSupported()は Firebase Web SDK のAPIです📚 (Firebase)logEvent()は「イベント名+(任意で)パラメータ」を送れます📣 (Firebase)
手順2:ボタン押下で track() を呼ぶ🖱️📤

// 例:保存ボタン(React)
import { track } from "../lib/analytics";
function SaveButton() {
const onSave = async () => {
// 保存処理(Firestoreなど)…
// ✅ イベント送信
await track("memo_save", {
screen: "memo",
method: "button",
});
};
return <button onClick={onSave}>保存</button>;
}
ポイント🧠✨
screenやmethodみたいな「分析に効く最小パラメータ」だけで十分です👌- 「送ったパラメータをレポートで見たい」なら、GA4側で カスタム定義として登録が必要になることがあります(DebugViewでは見えても、標準レポートに出ない問題)📌 (Firebase)
手順3:AIボタン(Firebase AI Logic)にもイベントを付ける🤖📣
![]()
「AI整形」みたいな機能は、のちの A/B やコスト管理にも効くので、今のうちに送ると強いです💪 Firebase AI Logic 自体は「クライアントからGemini/Imagenを安全に呼ぶ」ための土台として用意されています。(Firebase)
例)AI整形ボタン押下時:
await track("ai_format_click", { screen: "memo" });
例)AI処理が終わった時(成功/失敗だけ):
await track("ai_format_result", { status: "success" }); // error もあり
確認:DebugViewで“今飛んでる”を目で見る👀🧪

Webの DebugView は **Google Analytics Debugger(Chrome拡張)**を使うのが公式手順です🧩 (Firebase)
やることはこの流れ👇
- Google Analytics Debugger を入れる(Chrome拡張)🧩
- 拡張を有効化して、対象ページをリロード🔄
- Firebase Console → Analytics → DebugView を開く👀
- ボタンを押して、
memo_saveが出るか確認✅ (Firebase)
注意⚠️
- Debugモードで送ったイベントは 通常の集計や BigQuery エクスポートに含まれない扱いになります(デバッグ専用)🧯 (Firebase)
よくある詰まりポイント集🧯😇

- イベント名の表記ゆれ:
memo_saveとmemoSaveが混ざる → 別イベント扱いで地獄👹(イベント名は大小文字区別)(Firebase) - イベント種類を増やしすぎ:画面ごとに別名にして 500種類に近づく → 後で詰む⚠️ (Firebase)
- PIIを入れちゃう:メールなどを送ってしまう → そもそもNG🚫 (Google ヘルプ)
- SSRで落ちる:サーバー側で analytics を触って例外 →
isSupported()で回避🧯 (Firebase)
ミニ課題🧩✍️
次の3イベントを実装して、DebugViewで見えるところまでやってみてください🔥
memo_save(保存ボタン)💾ai_format_click(AI整形ボタン)🤖settings_open(設定画面を開いた)⚙️
それぞれに共通で screen を付ける(例:memo / settings)📌
チェック✅🎉
- DebugViewでイベントがリアルタイムに見えた?👀 (Firebase)
- イベント名はルール通り(40文字以内・
_・予約プレフィックス回避)?🧷 (GA4Spy) - 送ってる情報に個人情報が混ざってない?🔒 (Google ヘルプ)
AIで“イベント表→実装→テスト観点”を一気に作る🤝🤖
ここ、AIがめちゃくちゃ得意です⚡
- FirebaseのAI支援(Gemini in Firebase など)は、Firebaseの画面やツール上で開発・デバッグを助けてくれます🧠🛠️ (Firebase)
- Gemini CLI はエージェント的に作業を進められる設計で、Firebase向けのワークフロー連携(MCP/拡張)も案内されています💻🧩 (Google for Developers)
- Google の Antigravity は “エージェントを束ねて開発する” 方向のIDEで、導入用の公式Codelabもあります🛸 (Google Codelabs)
おすすめの投げ方(コピペ用)👇
- 「このアプリ機能一覧から、GA4の推奨イベントに寄せつつ、足りない分はカスタムで。イベント名・params・目的を表で出して」
- 「イベント名ルール(40文字以内、
_、予約プレフィックス回避)と、PII禁止を守れてるかレビューして」 (GA4Spy)
次の第5章(ユーザープロパティ)へ行く前に、もし「このミニアプリはメモ+画像+AI整形だよ」みたいに機能が決まってるなら、その前提で **イベント表(5〜10個)を“あなた用に最適化”**して作れます📊🧩 (この章のコードに、そのまま落とし込める形で出します😆🔥)