このチュートリアルでは、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 アナリティクス サーバーに直接イベントを送信できます。このアプローチの利点は、サービス ワーカーを含む拡張機能のあらゆる場所から分析イベントを送信できることです。
API 認証情報を設定する
最初のステップは、api_secret と measurement_id を取得することです。アナリティクス アカウントでこれらの値を取得する方法については、Measurement Protocol のドキュメントをご覧ください。
client_id を生成する
2 番目のステップは、特定のデバイス/ユーザーの一意の識別子 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 アナリティクスにイベントを送信できます。
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_id と engagement_time_msec の 2 つの追加パラメータを指定する必要があります。
推奨パラメータ session_id と engagement_time_msec を使用する
session_id と engagement_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_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 this.getOrCreateSessionId(),
engagement_time_msec: DEFAULT_ENGAGEMENT_TIME_IN_MSEC,
id: "my-button",
},
},
],
}),
}
);
このイベントは、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 アナリティクスの Measurement Protocol を使用すると、拡張機能のサービス ワーカーでアナリティクス イベントをトラッキングできます。たとえば、サービス ワーカーで unhandledrejection event をリッスンすることで、サービス ワーカーでキャッチされなかった例外を 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 アナリティクスには、拡張機能へのアナリティクス イベントのデバッグに役立つ 2 つの機能があります。
- イベント定義のエラーを報告する特別なデバッグ エンドポイント
https://www.google-analytics.com**/debug**/mp/collect。 - イベントが届くと表示される Google アナリティクスのリアルタイム レポート。