本教程演示了如何使用 Google Analytics 跟踪扩展程序的用量。您可以在 GitHub 上找到可正常运行的 Google Analytics 示例,其中 google-analytics.js 包含所有与 Google Analytics 相关的代码。
要求
本教程假定您熟悉如何编写 Chrome 扩展程序。如果您需要有关如何编写扩展程序的信息,请阅读入门教程。
您还必须设置 Google Analytics 账号,才能跟踪扩展程序。 请注意,在设置账号时,您可以在“网站的网址”字段中使用任意值,因为扩展程序没有自己的网址。
使用 Google Analytics Measurement Protocol
自 Manifest V3 起,Chrome 扩展程序不得执行远程托管的代码。这意味着您必须使用 Google Analytics Measurement Protocol 来跟踪扩展程序事件。借助 Measurement Protocol,您可以通过 HTTP 请求直接将事件发送到 Google Analytics 服务器。这种方法的优势在于,您可以从扩展程序的任何位置(包括 Service Worker)发送分析事件。
设置 API 凭据
如需向 Google Analytics 发送事件,您需要 api_secret 和 measurement_id。请参阅 Measurement Protocol 文档,详细了解 Measurement Protocol 的一般规范。
第 1 步:创建网站数据流
由于 Chrome 扩展程序会被跟踪为 Web 环境,因此您必须在 Google Analytics 媒体资源中设置网站数据流:
- 前往 Google Analytics 管理页面。
- 在媒体资源列中,点击数据收集和修改,然后选择数据流。
- 点击添加数据流,然后点击网站。
- 在 Website 网址(网站网址)字段中输入任意占位网址(例如
https://extension或扩展程序的 Chrome 应用商店网址)。 - 输入数据流名称(例如
My Chrome Extension)。 - 点击创建数据流。
创建完成后,您的衡量 ID(看起来像 G-XXXXXXXXXX)将显示在“数据流详情”页面的顶部。
第 2 步:生成 Measurement Protocol API 密钥
如需生成 Measurement Protocol 所需的 api_secret,请前往您刚刚创建的网站数据流的设置:
- 依次前往管理 > 数据收集和修改 > 数据流,然后选择您的网站数据流。
在事件部分中,点击 Measurement Protocol API 密钥。
如果系统提示您阅读并接受 Measurement Protocol 条款,请按提示操作。
点击创建。
为密钥输入别名(例如
Chrome Extension Secret),然后点击创建以生成密钥。复制生成的 Secret 值。
生成 client_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 = `${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_id 和 engagement_time_msec。
使用推荐参数 session_id 和 engagement_time_msec
session_id 和 engagement_time_msec 都是使用 Google Analytics 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_id 和 engagement_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 getOrCreateSessionId(),
engagement_time_msec: DEFAULT_ENGAGEMENT_TIME_IN_MSEC,
id: "my-button",
},
},
],
}),
}
);
该事件将按如下方式显示在 Google Analytics 实时报告中。

跟踪弹出式窗口、侧边栏和扩展程序页面中的网页浏览
Google Analytics 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 Analytics 实时报告中的任何其他网页浏览量一样显示:

在 Service Worker 中跟踪 Analytics 事件
使用 Google Analytics Measurement Protocol 可以在扩展程序服务工作线程中跟踪分析事件。例如,通过监听 Service Worker 中的 unhandledrejection event,您可以将 Service Worker 中任何未捕获的异常记录到 Google Analytics 中,这有助于调试用户可能会报告的问题。
service-worker.js:
addEventListener("unhandledrejection", async (event) => {
fetch(`${GA_ENDPOINT}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`,
{
method: "POST",
body: JSON.stringify({
client_id: await 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 getOrCreateSessionId(),
engagement_time_msec: DEFAULT_ENGAGEMENT_TIME_IN_MSEC,
message: event.reason.message,
stack: event.reason.stack,
},
},
],
}),
});
});
现在,您可以在 Google Analytics 报告中看到错误事件:

调试
Google Analytics 提供了两项实用功能,可用于调试扩展程序中的 Google Analytics 事件:
- 一个特殊调试端点
https://www.google-analytics.com**/debug**/mp/collect,用于报告事件定义中的任何错误。 - Google Analytics 实时报告,用于显示传入的事件。