Google アナリティクス 4 を使用

このチュートリアルでは、Google アナリティクスを使用して拡張機能の使用状況を追跡する方法について説明します。GitHub で Google アナリティクス 4 の実用的なサンプルをご覧いただけます。google-analytics.js には、Google アナリティクス関連のコードがすべて含まれています。

要件

このチュートリアルは、Chrome 拡張機能の作成に精通していることを前提としています。拡張機能の記述方法については、スタートガイド チュートリアルをご覧ください。

広告表示オプションをトラッキングするには、Google アナリティクス 4 アカウントもセットアップする必要があります。拡張機能には独自の URL がないため、アカウントを設定する際は [ウェブサイトの URL] 欄で任意の値を使用できます。

Google アナリティクスの Measurement Protocol を使用する

Manifest V3 以降、Chrome 拡張機能ではリモートでホストされるコードを実行できません。つまり、拡張機能のイベントのトラッキングには Google アナリティクスの Measurement Protocol を使用する必要があります。Measurement Protocol を使用すると、HTTP リクエストを通して Google アナリティクス サーバーに直接イベントを送信できます。このアプローチの利点は、Service Worker を含む拡張機能内のあらゆる場所から分析イベントを送信できることです。

API 認証情報を設定する

最初のステップは、api_secretmeasurement_id を取得することです。アナリティクス アカウントでこれらの ID を取得する方法については、Measurement Protocol に関するドキュメントをご覧ください。

client_id を生成する

2 番目のステップでは、特定のデバイスまたはユーザーの固有識別子である client_id を生成します。この ID は、拡張機能がユーザーのブラウザにインストールされていれば、同じである必要があります。任意の文字列を指定できますが、クライアントに固有のものである必要があります。これは、self.crypto.randomUUID() を呼び出して生成できます。client_idchrome.storage.local に格納して、拡張機能がインストールされている限り同じになるようにします。

chrome.storage.local を使用するには、マニフェスト ファイルで storage 権限が必要です。

manifest.json:

{
  
  "permissions": ["storage"],
  
}

これで、chrome.storage.local を使用して client_id を保存できます。

async function getOrCreateClientId() {
  const result = await chrome.storage.local.get('clientId');
  let clientId = result.clientId;
  if (!clientId) {
    // Generate a unique client ID, the actual value is not relevant
    clientId = self.crypto.randomUUID();
    await chrome.storage.local.set({clientId});
  }
  return clientId;
}

アナリティクス イベントを送信する

API 認証情報と client_id を使って、fetch リクエストを介して Google アナリティクスにイベントを送信できます。

const GA_ENDPOINT = 'https://www.google-analytics.com/mp/collect';
const MEASUREMENT_ID = `G-...`;
const API_SECRET = `...`;

fetch(
  `${GA_ENDPOINT}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`,
  {
    method: 'POST',
    body: JSON.stringify({
      client_id: await getOrCreateClientId(),
      events: [
        {
          name: 'button_clicked',
          params: {
            id: 'my-button',
          },
        },
      ],
    }),
  }
);

これにより、button_clicked イベントが送信されます。このイベントは、Google アナリティクスのイベント レポートに表示されます。Google アナリティクスのリアルタイム レポートにイベントを表示するには、session_idengagement_time_msec の 2 つの追加パラメータを指定する必要があります。

推奨パラメータ session_idengagement_time_msec を使用する

session_idengagement_time_msec はどちらも、リアルタイムなどの標準レポートでユーザー アクティビティを表示するために必要なことから、Google アナリティクス Measurement Protocol の使用時に推奨されるパラメータです。

session_id は、ユーザーが拡張機能を継続的に操作している期間を表します。デフォルトでは、30 分間操作がなければセッションは終了します。セッションの継続時間に制限はありません。

Chrome 拡張機能では、通常のウェブサイトとは異なり、ユーザー セッションが明確に認識されません。そのため、拡張機能でユーザー セッションの意味を定義する必要があります。たとえば、新しいユーザー インタラクションはすべて新しいセッションになることがあります。その場合は、タイムスタンプを使用して、イベントごとに新しいセッション ID を生成できます。

次の例は、イベントが報告されない状態が 30 分間続くと新しいセッションをタイムアウトにする方法を示しています(この時間は、拡張機能のユーザーの行動に合わせてカスタマイズできます)。この例では、chrome.storage.session を使用して、ブラウザの実行中にアクティブなセッションを保存します。セッションとともに、最後にイベントが発生した時刻を保存します。これにより、アクティブなセッションの有効期限が切れているかどうかを判断できます。

const SESSION_EXPIRATION_IN_MIN = 30;

async function getOrCreateSessionId() {
  // Store session in memory storage
  let {sessionData} = await chrome.storage.session.get('sessionData');
  // Check if session exists and is still valid
  const currentTimeInMs = Date.now();
  if (sessionData && sessionData.timestamp) {
    // Calculate how long ago the session was last updated
    const durationInMin = (currentTimeInMs - sessionData.timestamp) / 60000;
    // Check if last update lays past the session expiration threshold
    if (durationInMin > SESSION_EXPIRATION_IN_MIN) {
      // Delete old session id to start a new session
      sessionData = null;
    } else {
      // Update timestamp to keep session alive
      sessionData.timestamp = currentTimeInMs;
      await chrome.storage.session.set({sessionData});
    }
  }
  if (!sessionData) {
    // Create and store a new session
    sessionData = {
      session_id: currentTimeInMs.toString(),
      timestamp: currentTimeInMs.toString(),
    };
    await chrome.storage.session.set({sessionData});
  }
  return sessionData.session_id;
}

次の例では、前のボタンのクリック イベント リクエストに session_idengagement_time_msec を追加します。engagement_time_msec には、100 ms のデフォルト値を指定できます。

const GA_ENDPOINT = "https://www.google-analytics.com/mp/collect";
const MEASUREMENT_ID = `G-...`;
const API_SECRET = `...`;
const DEFAULT_ENGAGEMENT_TIME_IN_MSEC = 100;

fetch(
`${GA_ENDPOINT}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`,
  {
    method: "POST",
    body: JSON.stringify({
      client_id: await getOrCreateClientId(),
      events: [
        {
          name: "button_clicked",
          params: {
            session_id: await this.getOrCreateSessionId(),
            engagement_time_msec: DEFAULT_ENGAGEMENT_TIME_IN_MSEC,
            id: "my-button",
          },
        },
      ],
    }),
  }
);

このイベントは、Google アナリティクスのリアルタイム レポートに次のように表示されます。

Google アナリティクスのリアルタイム イベント。

ポップアップ、サイドパネル、拡張機能ページでページビューをトラッキングする

Google アナリティクス Measurement Protocol では、ページビューをトラッキングするための特別な page_view イベントがサポートされています。ポップアップ ページ、サイドパネル、拡張機能ページを新しいタブで訪問したユーザーをトラッキングするために使用します。page_view イベントには、page_title パラメータと page_location パラメータも必要です。次の例では、拡張機能のポップアップのドキュメント load イベントでページビュー イベントを発生させます。

popup.js:

window.addEventListener("load", async () => {
  fetch(`${GA_ENDPOINT}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`,
  {
    method: "POST",
    body: JSON.stringify({
      client_id: await getOrCreateClientId(),
      events: [
        {
          name: "page_view",
          params: {
            session_id: await getOrCreateSessionId(),
            engagement_time_msec: DEFAULT_ENGAGEMENT_TIME_IN_MSEC,
            page_title: document.title,
            page_location: document.location.href
          },
        },
      ],
    }),
  });
});

popup.js スクリプトは、ポップアップの html ファイルにインポートし、他のスクリプトが実行される前に実行する必要があります。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Analytics Demo Popup</title>
    <script src="./popup.js" type="module"></script>
  </head>
  <body>
    <h1>Analytics Demo</h1>
  </body>
</html>

ポップアップ ビューは、Google アナリティクスのリアルタイム レポートの他のページビューと同様に表示されます。

Google アナリティクス リアルタイム ダッシュボードに表示されるページビュー イベント。

Service Worker での分析イベントのトラッキング

Google アナリティクスの Measurement Protocol を使用すると、拡張機能 Service Worker で分析イベントをトラッキングできます。たとえば、Service Worker で unhandledrejection event をリッスンすることにより、Service Worker でキャッチされていない例外を Google アナリティクスに記録できます。これは、ユーザーから報告される可能性のある問題のデバッグに大いに役立ちます。

service-worker.js:

addEventListener("unhandledrejection", async (event) => {
  `${GA_ENDPOINT}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`,
  {
    method: "POST",
    body: JSON.stringify({
      client_id: getOrCreateClientId(),
      events: [
        {
          // Note: 'error' is a reserved event name and cannot be used
          // see https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference?client_type=gtag#reserved_names
          name: "extension_error",
          params: {
            session_id: await this.getOrCreateSessionId(),
            engagement_time_msec: DEFAULT_ENGAGEMENT_TIME_IN_MSEC,
            message: error.message,
            stack: error.stack,
          },
        },
      ],
    }),
  }
});

これで、Google アナリティクスのレポートにエラーイベントが表示されるようになります。

Google アナリティクスのイベント ダッシュボードに表示されるエラーイベント。

デバッグ

Google アナリティクスには、拡張機能に対するアナリティクス イベントのデバッグに、次の 2 つの便利な機能があります。

  1. イベント定義内のエラーを報告する特別なデバッグ エンドポイント https://www.google-analytics.com**/debug**/mp/collect
  2. Google アナリティクスのリアルタイム レポート: 発生したイベントが表示されます。