フロントエンド開発の先端を突っ走るNext.js
next.js アプリの初期化( npx create-next-app@latest <アプリ名> ) または pnpm create next-app@latest <アプリ名> または bun create next-app <アプリ名> )

Next.jsでFirebase Analyticsを使う

Next.jsにFirebaseアナリティクス(Google Analytics)を追加するには、 クライアントサイドでFirebase Analyticsを初期化し、必要に応じてイベント計測を行うようにします

手順概要

  1. Firebaseプロジェクト作成・設定
  2. Firebase SDK依存パッケージのインストール
  3. 環境変数でFirebase設定情報を管理
  4. クライアントコンポーネントでAnalytics初期化
  5. カスタムイベントの記録

1. Firebaseプロジェクト作成

  • Firebaseコンソールで新規プロジェクトを作成し、Google Analyticsの設定を有効化します。
  • プロジェクトの「設定」→「全般」→「マイアプリ」から measurementId を含む構成情報を取得します。

2. Firebase SDKのインストール

npm install firebase

3. Next.jsファイルの作成

.env.local`

NEXT_PUBLIC_FIREBASE_API_KEY=xxx
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=xxx
NEXT_PUBLIC_FIREBASE_PROJECT_ID=xxx
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=xxx
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=xxx
NEXT_PUBLIC_FIREBASE_APP_ID=xxx
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=xxx

src/common/firebase/firebaseConfig.ts


import type { Analytics } from "firebase/analytics";
import { getAnalytics, isSupported } from "firebase/analytics";
import type { FirebaseApp } from "firebase/app";
import { getApps, initializeApp } from "firebase/app";

const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
  measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

// Firebase アプリの初期化(既に初期化されている場合は既存のものを使用)
export const app: FirebaseApp =
  getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0];

// Analytics シングルトンインスタンス
let analyticsInstance: Analytics | null = null;
let analyticsInitialized = false;

// Analytics の初期化(内部的に1度だけ実行)
const initializeAnalytics = async (): Promise<void> => {
  if (analyticsInitialized) return;

  if (typeof window !== "undefined" && (await isSupported())) {
    analyticsInstance = getAnalytics(app);
    analyticsInitialized = true;
  } else {
    analyticsInitialized = true; // 失敗しても再試行しない
  }
};

// Analytics インスタンスを取得(常に同じインスタンスを返す)
export const getFirebaseAnalytics = (): Analytics | null => {
  return analyticsInstance;
};

// アプリ起動時に自動初期化
if (typeof window !== "undefined") {
  initializeAnalytics();
}

AnalyticsProvider.tsx

"use client";

import { logEvent } from "firebase/analytics";
import { usePathname } from "next/navigation";
import { type ReactNode, useEffect } from "react";
import { getFirebaseAnalytics } from "@/common/firebase/firebaseConfig";

type AnalyticsProviderProps = {
  children: ReactNode;
};

export const AnalyticsProvider = ({ children }: AnalyticsProviderProps) => {
  const pathname = usePathname();

  // pathname変更時にpage_viewイベントを送信
  useEffect(() => {
    const analytics = getFirebaseAnalytics();
    if (analytics) {
      logEvent(analytics, "page_view", {
        page_path: pathname,
      });
    }
  }, [pathname]);

  return <>{children}</>;
};

src/app/providers.tsx

"use client";

import type { FC, ReactNode } from "react";
import { AnalyticsProvider } from "@/common/firebase/AnalyticsProvider";

type Props = {
  children: ReactNode;
};

export const Providers: FC<Props> = ({ children }) => {
  return (
    <AnalyticsProvider>
      {children}
    </AnalyticsProvider>
  );
};

呼び出し方

src/app/layout.tsx で以下のようにして呼び出します。

<Providers>{children}</Providers>

これだけでページ遷移時に自動的にGoogleアナリティクスに送信されます。

# イベントの送信方法

useLogEvent.ts

"use client";

import { logEvent as firebaseLogEvent } from "firebase/analytics";
import { getFirebaseAnalytics } from "@/common/firebase/firebaseConfig";

export const useLogEvent = () => {
  const logEvent = (
    eventName: string,
    eventParams?: Record<string, string | number | boolean>,
  ) => {
    const analytics = getFirebaseAnalytics();
    if (analytics) {
      firebaseLogEvent(analytics, eventName, eventParams);
    }
  };

  return { logEvent };
};
const { logEvent } = useLogEvent();
// バリデーションエラー時の処理
logEvent("任意のイベント名", {
    // 任意のオブジェクト
});

logEvent の公式イベントにはどういう種類があるか

Google Analyticsの公式イベントについて、カテゴリ別に説明します。

アプリ一般向け

  • app_open: アプリが起動されたとき(バックグラウンドから復帰も含む)
  • screen_view: 新しい画面やページが表示されたとき
  • select_content: ユーザーがコンテンツを選択したとき(記事、動画、商品など)
  • user_engagement: ユーザーがアプリをアクティブに使用している時間を測定

eコマース向け

  • add_to_cart: 商品がカートに追加されたとき
  • add_to_wishlist: 商品がウィッシュリストに追加されたとき
  • begin_checkout: チェックアウトプロセスが開始されたとき
  • purchase: 購入が完了したとき
  • refund: 返金が処理されたとき
  • view_item: 商品の詳細ページが表示されたとき
  • view_item_list: 商品リスト(カテゴリページ、検索結果など)が表示されたとき
  • view_cart: カートページが表示されたとき

ゲームアプリ向け

  • level_start: ゲームのレベルが開始されたとき
  • level_end: ゲームのレベルが終了したとき
  • level_up: プレイヤーがレベルアップしたとき
  • unlock_achievement: 実績・アチーブメントが解除されたとき
  • earn_virtual_currency: 仮想通貨(コイン、ジェムなど)を獲得したとき
  • spend_virtual_currency: 仮想通貨を使用したとき
  • post_score: スコアが投稿されたとき

アクション・認証

  • login: ユーザーがログインしたとき
  • sign_up: 新規ユーザーが登録したとき
  • share: コンテンツが共有されたとき(SNSシェアなど)
  • join_group: ユーザーがグループに参加したとき

パフォーマンス・設定

  • tutorial_begin: チュートリアルが開始されたとき
  • tutorial_complete: チュートリアルが完了したとき
  • ad_impression: 広告が表示されたとき

補足: これらの公式イベントを使用することで、Google Analyticsでの標準レポートが自動的に機能し、他のアプリとの比較も可能になります。

ローカルでFirebase (Google) アナリティクスの送信をデバッグする

https://chromewebstore.google.com/detail/google-analytics-debugger/jnkmfdileelhofjcijamephohjechhna

DebugViewの表示手順

Google Analytics 4(GA4)の管理画面にログインします。​

左下の「管理」をクリックします。​

「プロパティ」列から「データの表示」を探し、「DebugView」を選択します。​

DebugViewの画面が起動し、左側に過去30分のイベントタイムライン、右側に各イベントの詳細情報が見られます。​

● Core Web Vitalsを取得してFirebase Analyticsに送信する。

https://dev.classmethod.jp/articles/classmethod-study-meeting-osaka-react-core-web-vital/

https://nextjs.org/learn/seo/web-performance

Core Web Vitals指標一覧

Next.jsのuseReportWebVitalsフックで取得できる指標は以下の通りです。

指標名 正式名称 説明 測定内容
LCP Largest Contentful Paint 最大のコンテンツ要素が描画されるまでの時間 メインコンテンツの読み込み速度
INP Interaction to Next Paint 操作から次の描画までの時間 全体的なインタラクティブ性 2
CLS Cumulative Layout Shift ページの視覚的安定性 レイアウトのずれの累積値
FID First Input Delay ユーザーの最初の操作に対する応答時間 インタラクティブ性(非推奨、INPに置き換え)
TTFB Time to First Byte サーバーからの最初のバイト受信までの時間 ネットワークリクエストの応答速度
FCP First Contentful Paint 最初のコンテンツが画面に描画されるまでの時間 ページの初期レンダリング速度

実装詳細

No.2673
10/20 16:31

edit