使用 Google Analytics (分析) 4

本教學課程說明如何使用 Google Analytics 追蹤擴充功能的使用情形。您可以在 Github 上找到可用的 Google Analytics 4 範例,其中 google-analytics.js 包含所有 Google Analytics 相關程式碼。

需求條件

本教學課程假設您已熟悉如何編寫 Chrome 擴充功能。如需瞭解如何編寫擴充功能,請參閱入門教學課程

您也必須設定 Google Analytics 4 帳戶,才能追蹤擴充功能。請注意,設定帳戶時,您可以在網站網址欄位中使用任何值,因為擴充功能不會有自己的網址。

使用 Google Analytics Measurement Protocol

自 Manifest V3 起,Chrome 擴充功能不得執行遠端代管的程式碼。也就是說,您必須使用 Google Analytics Measurement Protocol 追蹤擴充功能事件。您可以透過 Measurement Protocol 提出 HTTP 要求,將事件直接傳送至 Google Analytics 伺服器。這種做法的好處是,您可以在擴充功能的任何位置 (包括服務工作人員) 傳送 Analytics 事件。

設定 API 憑證

首先,請取得 api_secretmeasurement_id。如要瞭解如何為 Analytics 帳戶取得這些資料,請參閱 Measurement Protocol 說明文件

生成client_id

第二步是為特定裝置/使用者產生專屬 ID,即 client_id。只要擴充功能安裝在使用者瀏覽器上,ID 就應維持不變。可以是任意字串,但必須是該用戶端的專屬字串。將 client_id 儲存在 chrome.storage.local 中,確保只要擴充功能已安裝,這個值就會保持不變。

使用 chrome.storage.local 時,需要在資訊清單檔案中加入 storage 權限:

manifest.json:

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

接著,您可以使用 chrome.storage.local 儲存 client_id

function getRandomId() {
  const digits = '123456789'.split('');
  let result = '';

  for (let i = 0; i < 10; i++) {
    result += digits[Math.floor(Math.random() * 9)];
  }

  return result;
}

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. We use
    // the <number>.<number> format since this is typical for GA client IDs.
    const unixTimestampSeconds = Math.floor(new Date().getTime() / 1000);
    clientId = `${this.getRandomId()}.${unixTimestampSeconds}`;
    await chrome.storage.local.set({clientId});
  }
  return clientId;
}

傳送數據分析事件

有了 API 憑證和 client_id,您就能透過 fetch 要求將事件傳送至 Google Analytics:

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 Analytics 事件報表中。如要在 Google Analytics 即時報表中查看事件,您必須提供兩個額外參數:session_idengagement_time_msec

使用建議參數 session_idengagement_time_msec

使用 Google Analytics Measurement Protocol 時,建議一併傳送 session_idengagement_time_msec 參數,因為標準報表 (例如「即時」報表) 需要這些參數,才能顯示使用者活動。

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 Analytics 即時報表會顯示如下事件。

Google Analytics 中的即時事件。

追蹤彈出式視窗、側邊面板和擴充功能頁面中的網頁瀏覽

Google Analytics Measurement Protocol 支援用來追蹤網頁瀏覽的特殊 page_view 事件。您可以使用這項功能,追蹤在新分頁中造訪彈出式視窗、側邊面板或擴充功能頁面的使用者。page_view 事件也需要 page_titlepage_location 參數。以下範例會在擴充功能彈出視窗的 document 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
          },
        },
      ],
    }),
  });
});

您需要在彈出式視窗的 HTML 檔案中匯入 popup.js 指令碼,且應在執行任何其他指令碼之前執行:

<!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 Analytics 即時報表中,彈出式視窗檢視畫面會像其他網頁檢視畫面一樣顯示:

Google Analytics 即時資訊主頁中顯示的網頁瀏覽事件。

在 Service Worker 中追蹤 Analytics 事件

使用 Google Analytics Measurement Protocol,即可在擴充功能服務工作人員中追蹤 Analytics 事件。舉例來說,只要監聽服務工作人員中的 unhandledrejection event,您就能將服務工作人員中任何未處理的例外狀況記錄到 Google Analytics,這有助於偵錯使用者回報的問題。

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 Analytics 報表中查看錯誤事件:

錯誤事件,如 Google Analytics 事件資訊主頁所示。

偵錯

Google Analytics 提供兩項實用功能,可協助您偵錯擴充功能中的 Analytics 事件:

  1. 專用偵錯端點 https://www.google-analytics.com**/debug**/mp/collect:用於回報事件定義中的任何錯誤。
  2. Google Analytics 即時報表,會顯示傳送的事件。