Usar o Google Analytics 4

Este tutorial demonstra como acompanhar o uso da sua extensão usando o Google Analytics. Há um exemplo ativo do Google Analytics 4 no GitHub (em inglês), em que google-analytics.js inclui todo o código relacionado ao Google Analytics.

Requisitos

Este tutorial presume que você conheça a criação de extensões do Chrome. Se você precisar de informações sobre como escrever uma extensão, leia o Tutorial de início.

Você também precisa configurar uma conta do Google Analytics 4 para acompanhar sua extensão. Ao configurar a conta, você pode usar qualquer valor no campo "URL do site", já que sua extensão não terá um URL próprio.

Uso do Measurement Protocol do Google Analytics

Desde o Manifest V3, as extensões do Chrome não podem executar código hospedado remotamente. Isso significa que você precisa usar o Measurement Protocol do Google Analytics para acompanhar eventos de extensão. Com o Measurement Protocol, você pode enviar eventos diretamente aos servidores do Google Analytics usando solicitações HTTP. Uma vantagem dessa abordagem é que ela permite enviar eventos de análise de todos os lugares da extensão, incluindo o service worker.

Configurar credenciais de API

A primeira etapa é conseguir um api_secret e um measurement_id. Siga a documentação do Measurement Protocol para saber como acessá-las na sua conta do Google Analytics.

Gerar um client_id

A segunda etapa é gerar um identificador exclusivo para um dispositivo/usuário específico, o client_id. O ID precisa permanecer o mesmo, desde que a extensão esteja instalada no navegador do usuário. Pode ser uma string arbitrária, mas precisa ser exclusiva para o cliente. É possível gerar um chamando self.crypto.randomUUID(). Armazene o client_id no chrome.storage.local para que ele permaneça igual enquanto a extensão estiver instalada.

O uso de chrome.storage.local exige a permissão storage no arquivo de manifesto:

manifest.json:

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

Em seguida, use chrome.storage.local para armazenar o 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;
}

Enviar um evento do Analytics

Com as credenciais da API e o client_id, você pode enviar um evento para o Google Analytics usando uma solicitação fetch:

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',
          },
        },
      ],
    }),
  }
);

Isso envia um evento button_clicked, que vai aparecer no seu relatório de eventos do Google Analytics. Se você quiser ver seus eventos no Relatório de tempo real do Google Analytics, precisará fornecer dois parâmetros adicionais: session_id e engagement_time_msec.

Use os parâmetros recomendados session_id e engagement_time_msec

Tanto session_id quanto engagement_time_msec são parâmetros recomendados ao usar o Measurement Protocol do Google Analytics porque são necessários para que a atividade do usuário seja mostrada em relatórios padrão, como o Relatório de tempo real.

Uma session_id descreve um período em que o usuário interage continuamente com sua extensão. Por padrão, uma sessão termina após 30 minutos de inatividade do usuário. Não há limite para a duração dela.

Diferentemente dos sites normais nas extensões do Chrome, não há uma noção clara de uma sessão de usuário. Portanto, é preciso definir o significado de uma sessão de usuário na sua extensão. Por exemplo, cada nova interação do usuário pode ser uma nova sessão. Nesse caso, você pode simplesmente gerar um novo ID de sessão para cada evento (ou seja, usando um carimbo de data/hora).

O exemplo a seguir demonstra uma abordagem que esgotará o tempo limite de uma nova sessão após 30 minutos sem eventos relatados. Esse tempo pode ser personalizado para se adequar melhor ao comportamento do usuário da sua extensão. O exemplo usa chrome.storage.session para armazenar a sessão ativa enquanto o navegador está em execução. Junto com a sessão, armazenamos a última vez em que um evento foi disparado. Dessa forma, podemos saber se a sessão ativa expirou:

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;
}

O exemplo a seguir adiciona session_id e engagement_time_msec à solicitação de evento de clique do botão anterior. Para engagement_time_msec, é possível fornecer um valor padrão de 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",
          },
        },
      ],
    }),
  }
);

O evento aparece da seguinte forma no Relatório de tempo real do Google Analytics.

Eventos em tempo real no Google Analytics.

Acompanhar visualizações de página em pop-up, painel lateral e páginas de extensão

O Measurement Protocol do Google Analytics é compatível com um evento page_view especial para acompanhar visualizações de página. Use-o para acompanhar os usuários que acessam suas páginas pop-up, o painel lateral ou a página de uma extensão em uma nova guia. O evento page_view também requer os parâmetros page_title e page_location. O exemplo a seguir dispara um evento de visualização de página no evento load do documento para um pop-up de extensão:

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
          },
        },
      ],
    }),
  });
});

O script popup.js precisa ser importado no arquivo html do pop-up e ser executado antes de qualquer outro script:

<!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>

A visualização pop-up aparece como qualquer outra visualização de página no Relatório de tempo real do Google Analytics:

Evento de visualização de página conforme exibido no painel em tempo real do Google Analytics.

Rastrear eventos de análise em service workers

Com o Measurement Protocol do Google Analytics, é possível acompanhar eventos de análise de funcionários de serviços de extensão. Por exemplo, detectando o unhandledrejection event no service worker, você pode registrar todas as exceções não identificadas no service worker no Google Analytics, o que pode ser muito útil para depurar problemas que os usuários podem relatar.

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,
          },
        },
      ],
    }),
  }
});

Agora o evento de erro aparece nos seus relatórios do Google Analytics:

Evento de erro conforme exibido no painel de eventos do Google Analytics.

Depuração

O Google Analytics oferece dois recursos úteis para depurar eventos de análise na sua extensão:

  1. Um endpoint de depuração especial https://www.google-analytics.com**/debug**/mp/collect que informa erros nas definições dos seus eventos.
  2. O Relatório em tempo real do Google Analytics que mostra os eventos conforme eles chegam.