Monitorando Core Web Vitals: INP e Enviando Dados para o Google Analytics 4 via Google Tag Manager

O que você irá aprender?

    Fala galera, beleza?

    Nesse ultimos dias me deparei com um cenário de otimização de perfomance voltado nos dados do Google Search Console que acredito que seja interessante de compartilhar aqui vocês, mesmo não sendo algo diretamente relacionado ao Google Analytics 4 e Google Tag Manager.

    Uma a cada dois meses sento para revisitar algumas métricas de SEO on code, mas principalmente acompanhar as métricas de performance do nosso site, não sei se é uma janela viável, mas é confortável pra mim então mantenho assim. Eis que me deparo com a seguinte situação:

    Ponto interessante é que de fato no histórico da Métricas Boss sempre tivemos majoritariamente os acessos orgânicos baseados em desktop, mas com esse alerta decidi investir a oportunidade ou até mesmo se fazia sentido olhar para o mobile. >Temos mais tráfego via desktop por que nossos usuários se sentem mais confortáveis no computador ou, nosso site não é otimizado para mobile o suficiente para que o Google nos indique nas primeiras posições para nossas palavras chaves. Pensei ...

    Após pensar e dar uma olhada nos dados, observei que sim, o público em quantidade de pesquisas é bem menor no mobile para a maioria dos nossos temas, mas não significava que não era puta público. Muito pelo contrário era um publico 50% menor mais dentro de 1000000 de impressões, ou seja, otimizar para passar a receber esse tráfego fazia sentido uma vez que no mobile temos 1,5% dos clicks comparando com 3,5% no desktop. Porém o ponto principal era a posição média, uma vez que existe uma diferença entre os 2 de mais de 10 posições, ou seja, vamos arrumar a casa para ver se nossa posição média cresce e automaticamente passarmos a receber esse trafego :)

    O que são core web vitals?

    As Core Web Vitals são um conjunto de métricas essenciais desenvolvidas pelo Google para avaliar a experiência do usuário em termos de desempenho, interatividade e estabilidade visual de uma página web. Essas métricas foram projetadas para ajudar os desenvolvedores a entender e melhorar a qualidade da experiência do usuário em seus sites. As Core Web Vitals iniciais incluíam três métricas principais:

    1. Largest Contentful Paint (LCP): Mede o tempo que leva para o maior elemento visível na janela de visualização ser carregado.
    2. First Input Delay (FID): Mede o tempo de resposta inicial de um site à primeira interação do usuário.
    3. Cumulative Layout Shift (CLS): Avalia a estabilidade visual, medindo a quantidade de movimento inesperado do layout da página.

    No entanto, em 2022, o Google anunciou uma mudança significativa nas Core Web Vitals, substituindo a métrica FID pela nova métrica Interaction to Next Paint (INP). Esta mudança foi motivada pela necessidade de uma métrica mais robusta e representativa para medir a interatividade e a responsividade ao longo de toda a sessão do usuário, e não apenas na primeira interação.

    O Que é a Métrica INP?

    A métrica Interaction to Next Paint (INP) mede a latência de todas as interações que ocorrem durante a vida útil de uma página, não se limitando apenas à primeira interação como o FID. O INP avalia a responsividade de uma página web levando em conta o tempo desde o início da interação do usuário (como um clique ou toque) até o momento em que a próxima renderização da tela é visível. Este valor é uma representação mais fiel da experiência do usuário, fornecendo uma visão abrangente de como a página responde a todas as interações.

    Monitorando o tempo entre as interações

    Para monitorar a métrica INP, podemos usar a API PerformanceObserver para coletar dados de interações em tempo real. Neste projeto, estamos utilizando a plataforma Next.js 13, que é uma tecnologia moderna e poderosa para o desenvolvimento de aplicações web. Nem todos os desenvolvedores têm acesso ou experiência com essa tecnologia, mas ela oferece muitos benefícios, incluindo a capacidade de realizar renderização no servidor e no cliente de maneira eficiente.

    Aqui está como podemos implementar uma função que monitora as interações de desempenho e chama um callback fornecido com os dados relevantes sobre cada interação.

    const RATING_COLORS = {
      good: "#0CCE6A",
      "needs-improvement": "#FFA400",
      poor: "#FF4E42",
    };
    
    export function onInteraction(callback) {
      const valueToRating = (score) =>
        score <= 200 ? "good" : score <= 500 ? "needs-improvement" : "poor";
    
      const observer = new PerformanceObserver((list) => {
        const interactions = {};
    
        for (let entry of list.getEntries().filter((entry) => entry.interactionId)) {
          interactions[entry.interactionId] = interactions[entry.interactionId] || [];
          interactions[entry.interactionId].push(entry);
        }
    
        for (let interaction of Object.values(interactions)) {
          const entry = interaction.reduce((prev, curr) =>
            prev.duration >= curr.duration ? prev : curr
          );
          const entryTarget = interaction.map((entry) => entry.target).find((target) => !!target);
          const value = entry.duration;
    
          callback({
            attribution: {
              eventEntry: entry,
              eventTarget: entryTarget,
              eventTime: entry.startTime,
              eventType: entry.name,
            },
            entries: interaction,
            name: "Interaction",
            rating: valueToRating(value),
            value,
          });
        }
      });
    
      observer.observe({
        type: "event",
        durationThreshold: 0,
        buffered: true,
      });
    }
    

    >PS. Esse código não foi 100% implementado por mim, fiz algumas alterações apenas peguei ele fuxicando no github pessoas que estavam com o mesmo problema que eu, então, fica o salve para o mmocny mesmo sabendo que ele mesmo nunca vai ler isso e se ler não vai compreender, meu mais sincero obrigado :)

    Ao ver esse script e principalmente testar para entender quais eram as principais interações que estavam com algum tipo de problema, fiz alguma refatorações mais não consegui para menos de 300ms e ai que veio a idéia, por que não passar a monitorar esse tipo de comportamento para entender qual é o componente que gera o problema e automaticamente tratar de uma vez por todas?

    Como isso fiz algumas modificações para enviar as informações para dentro da camada de dados do Google Tag Manager e consequentemente enviar para o Google Analytics 4:

    export function logInteraction(interaction) {
      console.groupCollapsed(
        `[${interaction.name}] %c${interaction.value.toFixed(0)} ms (${interaction.rating})`,
        `color: ${RATING_COLORS[interaction.rating] || "inherit"}`
      );
    
      console.log("Interaction target:", interaction.attribution.eventTarget);
    
      for (let entry of interaction.entries) {
        console.log(`Interaction event type: %c${entry.name}`, "font-family: monospace");
    
        const adjustedPresentationTime = Math.max(entry.processingEnd, entry.startTime + entry.duration);
    
        console.table([
          {
            subPartString: "Input delay",
            "Time (ms)": Math.round(entry.processingStart - entry.startTime),
          },
          {
            subPartString: "Processing time",
            "Time (ms)": Math.round(entry.processingEnd - entry.processingStart),
          },
          {
            subPartString: "Presentation delay",
            "Time (ms)": Math.round(adjustedPresentationTime - entry.processingEnd),
          },
        ]);
      }
    
      console.log(interaction);
      console.groupEnd();
    
      // Push to dataLayer if interaction duration is 200ms or more
      if (interaction.value >= 200) {
        window.dataLayer = window.dataLayer || [];
        window.dataLayer.push({
          event: "poor_interaction",
          interaction: {
            name: interaction.name,
            value: interaction.value,
            rating: interaction.rating,
            target: interaction.attribution.eventTarget,
          },
        });
      }
    }
    

    Com as interações sendo monitoradas, podemos registrar os dados e, caso a duração da interação seja maior ou igual a 200ms, enviar um evento para a camada de dados (dataLayer). Esses eventos podem então ser capturados e enviados para o Google Analytics 4 via Google Tag Manager.

    Não vou ficar nesse momento agora te ensinando como implementar os eventos dentro do Google Analytics 4, ok? Tem outros materiais aqui e inclusive no Métricas Boss Prime tem um curso inteiro sobre como implementar eventos, fechou?

    Uma vez otimizei uma série de outros pontos é importante ressaltar que você após resolver o problema você precisará esperar 28 dias para que a validação do Google termine e te de a nova visão sobre a otimização, a diferença é que agora vou conseguir ir direto na raiz do problema uma vez que estou monitorando isso mais de perto.

    A transição de FID para INP nas Core Web Vitals reflete a evolução das necessidades de medição de interatividade e desempenho. Utilizando a API PerformanceObserver, podemos coletar dados detalhados sobre a métrica INP e, com o Google Tag Manager, enviar esses dados para o Google Analytics 4. Implementando essas práticas, você estará um passo à frente na otimização do desempenho e na melhoria contínua do seu site, garantindo uma experiência de usuário de alta qualidade.

    Utilizando Next.js 13, conseguimos implementar essas práticas de forma eficiente, aproveitando os benefícios dessa plataforma moderna para criar aplicações web robustas e responsivas. Se você está interessado em melhorar a experiência do usuário no seu site, monitorar a métrica INP e enviar esses dados para o GA4 é um passo essencial.

    Espero que esse conteudo tenha te ajudado e qualquer coisa só me catar no Linkedin e no instagram que a gente troca uma idéia beleza?

    WhatsApp