Next.js: Adicionando tag de script do GA?

Criado em 30 out. 2016  ·  74Comentários  ·  Fonte: vercel/next.js

Olá!

No momento, estou convertendo meu site em um projeto next.js e não consigo descobrir como adicionar a tag de script do Google Analytics à página. Alguma ideia?

Felicidades,
Robin

Comentários muito úteis

Não há necessidade de react-ga . Use o gerenciador de tags do google com o componente <Head> para injetar análises. Existem algumas pequenas alterações no código do gerenciador de tags do google necessárias para fazê-lo funcionar em nextjs / react:

<Head>
      <script dangerouslySetInnerHTML={{__html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
      })(window,document,'script','dataLayer','GTM-XXXXXX');`}} />
    </Head>
    <noscript dangerouslySetInnerHTML={{__html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX" height="0" width="0" style="display:none;visibility:hidden;"></iframe>`}} />

image

Todos 74 comentários

checkout <Head>

@robinvdvleuten Eu sugiro criar um componente GoogleTagManager e incluí-lo no

como as pessoas mencionaram, você pode usar a tag Head ou uma solução amigável como https://github.com/react-ga/react-ga

Alguma dica sobre como fazer o react -ga funcionar com next.js?

@gtramontina deve funcionar. Caso contrário, sou um dos react-ga contribuidores, então poderia ajudar com isso

Não há necessidade de react-ga . Use o gerenciador de tags do google com o componente <Head> para injetar análises. Existem algumas pequenas alterações no código do gerenciador de tags do google necessárias para fazê-lo funcionar em nextjs / react:

<Head>
      <script dangerouslySetInnerHTML={{__html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
      })(window,document,'script','dataLayer','GTM-XXXXXX');`}} />
    </Head>
    <noscript dangerouslySetInnerHTML={{__html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX" height="0" width="0" style="display:none;visibility:hidden;"></iframe>`}} />

image

Eu recomendaria uma solução melhor para rastrear a visualização da página do cliente: autotrack. Consulte https://github.com/MoOx/phenomic/issues/384 para obter mais informações.

@impronunciable seria ótimo ter um exemplo, pois depois de algumas buscas no Google ainda estou confuso 😃 Isso poderia ser reaberto?

  • @MoOx parece implicar que Google AutoTrack em vez disso
  • mas Autotrack instrui a criar uma tag de script com código que acesse o objeto window , de modo que não funcione no lado do servidor
  • E, de qualquer forma, se estiver usando um componente de reação, como react-ga, onde deve ser colocado? Em um render ? componentWillMount ? getInitialProps ? Não é muito claro, pois meio que supõe que você use o react-router e carregue o código uma única vez para todas as páginas.

O rastreamento de página deve funcionar tanto quando a página é renderizada pelo servidor quanto ao navegar para outra página. Seria ótimo ver como tudo deve se integrar em um Next app típico com um Head, um layout de página HOC, etc.

Também seria ótimo saber se você acha que existe uma combinação melhor / mais simples / menos complicada / mais moderna do que Next.js + Google Analytics Autotrack ...

Eu posso investigar isso

Na terça, 17 de janeiro de 2017, 7h59 Sébastien Dubois [email protected]
escrevi:

@impronunciable https://github.com/impronunciable seria ótimo
tenha um exemplo, pois depois de algumas pesquisas no Google ainda estou confuso 😃
ser reaberto?

  • @MoOx https://github.com/MoOx parece implicar que react -ga não é
    necessário, deve usar o Google AutoTrack
    https://github.com/googleanalytics/autotrack em vez disso
  • mas Autotrack instrui a criar uma tag de script com código que
    acessa o objeto janela, de modo que não funciona do lado do servidor
  • e de qualquer maneira, se estiver usando um componente de reação, como react-ga, onde deveria
    ser colocado? Em uma renderização? componentWillMount? getInitialProps? Não é
    super claro, pois supõe que você use o react-router e carregue o
    codifique uma única vez para todas as páginas.

O rastreamento de página deve funcionar quando a página é renderizada pelo servidor e
em seguida, ao navegar para outra página. Seria ótimo ver como
tudo deve ser integrado em um aplicativo Next típico com um cabeçalho, uma página
layout HOC, etc.

Também seria ótimo saber se você acha que existe um melhor / mais simples / menos
combinação complicada / mais moderna do que Next.js + Google
Analytics Autotrack ...

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/zeit/next.js/issues/160#issuecomment-273108099 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AAKHp9-2bfLXj2hMGlNlkqUSRqEL7R2Cks5rTJ8kgaJpZM4KkXxa
.

Com certeza, o autotrack é mais do que suficiente, injetado apenas no lado do cliente - não há necessidade de pensar no lado do servidor.

Consulte https://github.com/MoOx/react-toulouse/commit/c42045d1001ab813c5d7eae5ab2f4f8c08c0025e para obter um exemplo. Não está usando o next, mas acho que deve ser fácil de adaptar.

Sim, não queremos rastrear renderizações de servidor, uma vez que ofuscará coisas como localização.

Não, você não precisa, pois isso será tratado pelo cliente: tenha em mente que uma página é solicitada pelo cliente e será renderizada no navegador do cliente :)

OK, não percebi que o código não deve ser executado no lado do servidor. Usei o autotrack conforme recomendado por @MoOx , acho que deve funcionar: https://github.com/relatenow/relate/commit/50dc3f317eb3efa045d5bbe40d1a1a1ad1116458

Só não confirmei ainda se conta as visualizações de página corretamente, isso é novo para mim 😬 😄

Você pode usar a visualização em "tempo real" para depurar GA facilmente.

@MoOx sim bem isso é o que me incomoda, não vejo nada no painel em tempo real quando visito https://relate.now.sh em paralelo em outra guia (0 usuários ativos)

Ainda não estou entendendo ... Não recebo nenhum dado com o código que escrevi.

Todos os exemplos que vejo parecem exigir um <script href="https://www.google-analytics.com/analytics.js" async /> mas as coisas na cabeça não parecem ser executadas no cliente? (meu console.log não é impresso no console do navegador ...)

Um exemplo ainda seria muito apreciado 🙂

Como você fez isto funcionar? Tenho tentado chamar uma função de exibição de página em componentDidMount .

A verificação do GA do aplicativo de produção falha.

@luandro não lembra dos detalhes, mas você pode dar uma olhada no commit que

Eu fiz e tentei. Fiz o mesmo que você, chamando configureAnalytics na parte superior e visualização de componentWillMount , mas ainda obtive negativo na verificação do GA .

Em seu código, não parece que você realmente conectou o page hoc em qualquer lugar, não é?

@luandro Basta adicionar ga(‘set’, ‘page’, window.location.pathname); ga(‘send’, ‘pageview’); para alterar o url do evento de exibição de página.

Talvez haja uma maneira mais 'next.js' de fazer isso, mas WRT executando scripts na página, descobri que se criasse um componente Script assim:

// modules/Script.js
export default ({children}) => (
  <script dangerouslySetInnerHTML={{__html: `(${children.toString()})();` }}></script>
);

Então eu poderia fazer o que funcionou para mim:

import Document, { Head, Main, NextScript } from 'next/document'
import Script from '../modules/Script';

export default class MyDocument extends Document {

  render () {
    return (
      <html>
        <body>
          <Main />
          <Script>
            {
              () => {
                console.log('foo');
              }
            }
          </Script>
          <NextScript />
        </body>
      </html>
    )
  }
}

A ressalva é que você deve incluir tudo em uma função.

É possível rastrear exibições de página individuais sem chamar explicitamente ga ('send', 'pageview') em cada página. Se for absolutamente necessário fazer isso, onde invocá-lo para ter certeza de que ga foi carregado?

É possível vincular a eventos de alteração de rota de alguma forma para registrar visualizações de página?

@karthikiyengar Estou usando react-ga como sugerido por outros acima e registrando page views em componentDidMount de cada página.

import ReactGA from 'react-ga'

export const initGA = () => {
  console.log('GA init')
  ReactGA.initialize('UA-xxxxxxxx-x')
}
export const logPageView = () => {
  ReactGA.set({ page: window.location.pathname })
  ReactGA.pageview(window.location.pathname)
}
componentDidMount () {
    initGA()
    logPageView()
  }

@vinaypuppal é uma prática comum initGA para todos os componentes da página?

@rongierlach Estou usando um componente Layout que chama os métodos initialize e pageview em ReactGA dentro de componentDidMount() .

export default class extends Component {
  componentDidMount() {
    ReactGA.initialize('UA-1234567-1')
    ReactGA.pageview(document.location.pathname)
  }

  render() {
    return (
      <div>
        {this.props.children}
     </div>
    )
}

Esta é a maneira mais limpa que já fiz, pois se a página fosse renderizada pelo servidor, ela precisava ser inicializada. Tenho certeza de que há um gancho que pode ignorar a inicialização se for renderizado pelo cliente.

@notrab você não poderia estar perdendo as renderizações rasas? Eles apenas farão a transição de seu aplicativo e seu componente de layout pode não remontar. Isso é o que eu tenho que pegar.

componentDidMount() {
    ReactGA.initialize('xx-xxxxxxx-x')
    let trackMe = true

    if (trackMe) {
      ReactGA.pageview(document.location.pathname)
      trackMe = false
    }

    Router.onRouteChangeStart = () => {
      NProgress.start()
      this.store.dispatch(transitionPage(true))
      trackMe = true
    }
    Router.onRouteChangeComplete = () => {
      NProgress.done()
      this.store.dispatch(transitionPage(false))
      if (trackMe) { ReactGA.pageview(document.location.pathname) }
    }
    Router.onRouteChangeError = () => {
      NProgress.done()
      this.store.dispatch(transitionPage(false))
    }

    this.store.dispatch(calculateResponsiveState(window))
  }

Tentando fazer isso funcionar, mas ainda sem resposta do Google Analytics. Este é meu código em react-ga.js :

import ReactGA from 'react-ga'

const dev = process.env.NODE_ENV !== 'production'

export const initGA = () => {
  ReactGA.initialize("UA-XXXXXXXXX-X", {
    debug: dev,
  })
}

export const trackPageView = (
  pageName = window.location.pathname + window.location.search
) => {
  ReactGA.set({page: pageName})
  ReactGA.pageview(pageName)
}

export const trackCustomEvent = (category, action) =>
  ReactGA.event({category, action})

export default undefined

E minha página de índice:

import {initGA, trackPageView} from '../modules/react-ga.js'
[...]
Index.componentDidMount = function() {
    initGA()
    trackPageView()
}

com o código UA substituído pelo meu código real, é claro.

@filostrato Como você corrigiu isso? Eu também estou preso nisso. :)

@exogenesys acabou colocando isso em utils/analytics.js :

import ReactGA from 'react-ga'

const dev = process.env.NODE_ENV !== 'production'

export const initGA = () => {
  ReactGA.initialize("UA-xxxxxxxxx-x", {
    debug: dev,
  })
}

export const logPageView = (
  pageName = window.location.pathname + window.location.search
) => {
  ReactGA.set({page: pageName})
  ReactGA.pageview(pageName)
}

export const trackCustomEvent = (category, action) =>
  ReactGA.event({category, action})

export default undefined

e alterei meu Layout.js para estender React.Component :

export default class Layout extends React.Component {
    componentDidMount () {
      if (!window.GA_INITIALIZED) {
        initGA()
        window.GA_INITIALIZED = true
    }
    logPageView()
  }

  render () {
    return (
      <Main>
        <Header />
        {this.props.children}
      </Main>
    )
  }
}

Não encontrei uma maneira de fazê-lo funcionar em um componente que utiliza getInitialProps , mas como Layout.js não funcionou bem; não tenho certeza do que fazer se quiser estatísticas mais detalhadas, mas vou cruzar essa ponte quando chegar a esse ponto.

@filostrato Isso mesmo. Muito obrigado. :)

Ei pessoal

Acabei de lidar com a implementação do GA no meu site também e é isso que eu vim.

Primeiro usei a solução de @notrab que parecia limpa e direta:

export default class extends Component {
  componentDidMount() {
    ReactGA.initialize('UA-XXXXXXX-X')
    ReactGA.pageview(document.location.pathname)
  }

  render() {
    …
  }
}

No entanto, percebi:

  • componentDidMount foi executado quando eu alternei entre páginas de diferentes tipos, então a função initialize foi chamada várias vezes
  • componentDidMount foi _apenas_ executado quando eu alternei entre páginas de tipos diferentes, então a função pageview foi chamada somente então => Eu tenho um video pagetype em meu site e vi em a visualização do GA ao vivo que, ao alternar entre diferentes páginas de vídeo, apenas a página inicial do vídeo foi rastreada

Criei um componente de ordem superior para resolver esses dois problemas. Para o primeiro usei a solução @filostrato .

import React, { Component } from 'react';
import ReactGA from 'react-ga';
import Router from 'next/router';

const debug = process.env.NODE_ENV !== 'production';

export default (WrappedComponent) => (
  class GaWrapper extends Component {
    constructor (props) {
      super(props);
      this.trackPageview = this.trackPageview.bind(this);
    }

    componentDidMount() {
      this.initGa();
      this.trackPageview();
      Router.router.events.on('routeChangeComplete', this.trackPageview);
    }

    componentWillUnmount() {
      Router.router.events.off('routeChangeComplete', this.trackPageview);
    }

    trackPageview (path = document.location.pathname) {
      if (path !== this.lastTrackedPath) {
        ReactGA.pageview(path);
        this.lastTrackedPath = path;
      }
    }

    initGa () {
      if (!window.GA_INITIALIZED) {
        ReactGA.initialize('UA-XXXXXX-XX', { debug });
        window.GA_INITIALIZED = true;
      }
    }

    render() {
      return (
        <WrappedComponent {...this.props} />
      );
    }
  }
);

E em seu componente <Layout> / <PageWrapper> / <PageScaffold> ou como você o chamar:

import GaWrapper from './ga-wrapper';

const PageScaffold = () => (…);

export default GaWrapper(PageScaffold);

Talvez isso ajude alguém.

Eu não gosto da chamada de Router.router.events.… , porque isso não faz parte da API documentada. No entanto, quando tentei chamar Router.onRouteChangeComplete que deveria ser a maneira correta , obtive um ReferenceError porque onRouteChangeComplete era undefined . Talvez a documentação esteja desatualizada?

Isso funcionou para mim em um site next.js. E contornei o erro 'janela não definida' que estava ocorrendo com a implementação usual do react-ga.

A solução

Graças ao código de @osartun , consegui chegar à seguinte solução para disparar pageview eventos usando os novos gtag (que substitui os scripts _universal analytics_):

pages/_document.js

import Document, { Head } from 'next/document';

const GA_TRACKING_ID = '..';

export default class MyDocument extends Document {
  render() {
    return (
      <html lang="en-AU">
        <Head>
          <script async src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`} />
          <script
            dangerouslySetInnerHTML={{
              __html: `
                window.dataLayer = window.dataLayer || [];
                function gtag(){dataLayer.push(arguments)};
                gtag('js', new Date());
                gtag('config', '${GA_TRACKING_ID}');
              `,
            }}
          />
        </Head>
        ...
      </html>
    );
  }
}

scaffold.js / layout.js / wraper.js / qualquer que seja o nome do seu projeto:

import url from 'url';
import Router from 'next/router';

const GA_TRACKING_ID = '...';

const withPageViews = WrappedComponent =>
  class GaWrapper extends React.Component {
    componentDidMount() {
      // We want to do this code _once_ after the component has successfully
      // mounted in the browser only, so we use a special semiphore here.
      if (window.__NEXT_ROUTER_PAGEVIEW_REGISTERED__) {
        return;
      }

      window.__NEXT_ROUTER_PAGEVIEW_REGISTERED__ = true;
      let lastTrackedUrl = '';

      // NOTE: No corresponding `off` as we want this event listener to exist
      // for the entire lifecycle of the page
      // NOTE: This does _not_ fire on first page load. This is what we want
      // since GA already tracks a page view when the tag is first loaded.
      Router.router.events.on('routeChangeComplete', (newUrl = document.location) => {
        if (newUrl === lastTrackedUrl || !window.gtag) {
          return;
        }

        // Don't double track the same URL
        lastTrackedUrl = newUrl;

        // Believe it or not, this triggers a new pageview event!
        // https://developers.google.com/analytics/devguides/collection/gtagjs/single-page-applications
        window.gtag('config', GA_TRACKING_ID, {
          page_path: url.parse(newUrl).path,
        });
      });
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  };

const PageScaffold = () => (…);

export default withPageViews(PageScaffold);

Para qualquer um que chegue atrasado à festa, o motivo pelo qual a solução de componentDidMount . Defini-los fora do componente parece resolver o problema:

https://gist.github.com/trezy/e26cb7feb2349f585d2daf449411d0a4

@trezy ao usar gtag , parece não haver necessidade de import ReactGA from 'react-ga' .

Usei seu exemplo <script dangerouslySetInnerHtml={...} /> e acabei de adicionar esta linha na injeção:

window.gaTrackingId = '${gaTrackingId}';

Depois, esse truque leve começou a funcionar:

Router.onRouteChangeComplete = () => {
  if (window.gtag) {
    window.gtag('config', window.gaTrackingId, {
      page_location: window.location.href,
      page_path: window.location.pathname,
      page_title: window.document.title,
    });
  }
};

Um analytics.js muito grande não é mais obtido, mas todas as páginas ainda são rastreadas!

Como isso não é óbvio, seria bom ter um exemplo no repo.

Ou um repositório next-google-analytics 🕵️

@prichodko Muito obrigado por montar este exemplo !!

encontrou uma lib muito boa, adicionada ao arquivo de layout principal em componentDidMount () e parece funcionar corretamente. Está bem documentado, sem confusão

https://www.npmjs.com/package/react-gtm-module

@andylacko Na verdade, eu o tinha feito para corrigir algumas coisas, como HTTPS por exemplo: https://github.com/Vadorequest/react-gtm

Apenas adicionando minha solução a isso aqui, caso possa ser útil para alguém mais tarde.

Usei o react-ga, mas a mesma lógica deve funcionar com outras ferramentas ga.

_app.js 's getInitialProps é disparado no lado do cliente sempre que o usuário clica em uma nova rota. (Primeira vez, ele será executado no lado do servidor).

componentDidMount de _app.js é executado apenas no lado do cliente.

Portanto, no meu _app.js , adicionei as seguintes linhas de código


static async getInitialProps({ Component, router, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);      
    }

    // client-side only, run on page changes, do not run on server (SSR)
    if (typeof(window) === "object") {
      ReactGA.pageview(ctx.asPath);
    }
    return { pageProps, router }
  }


  componentDidMount() {
    // client-side only, run once on mount
    ReactGA.initialize('UA-XXXXXXX-3');
    ReactGA.pageview(window.location.pathname + window.location.search);
  }

Quando a página for renderizada no servidor, nada acontecerá em getInitialProps quando envolvi o código GA em typeof(window) === "object" .

No lado do cliente, getInitialProps não será executado pela primeira vez, pois tudo é renderizado pelo servidor. GA é configurado dentro de componentDidMount no lado do cliente.

As alterações de rota subsequentes (mesmo para a mesma rota), irão acionar getInitialProps no lado do cliente e o evento ga é acionado.

Apenas adicionando minha solução a isso aqui, caso possa ser útil para alguém mais tarde.

Usei o react-ga, mas a mesma lógica deve funcionar com outras ferramentas ga.

_app.js 's getInitialProps é disparado no lado do cliente sempre que o usuário clica em uma nova rota. (Primeira vez, ele será executado no lado do servidor).

componentDidMount de _app.js é executado apenas no lado do cliente.

Portanto, no meu _app.js , adicionei as seguintes linhas de código


static async getInitialProps({ Component, router, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);      
    }

    // client-side only, run on page changes, do not run on server (SSR)
    if (typeof(window) === "object") {
      ReactGA.pageview(ctx.asPath);
    }
    return { pageProps, router }
  }


  componentDidMount() {
    // client-side only, run once on mount
    ReactGA.initialize('UA-XXXXXXX-3');
    ReactGA.pageview(window.location.pathname + window.location.search);
  }

Quando a página for renderizada no servidor, nada acontecerá em getInitialProps quando envolvi o código GA em typeof(window) === "object" .

No lado do cliente, getInitialProps não será executado pela primeira vez, pois tudo é renderizado pelo servidor. GA é configurado dentro de componentDidMount no lado do cliente.

As alterações de rota subsequentes (mesmo para a mesma rota), irão acionar getInitialProps no lado do cliente e o evento ga é acionado.

Ei, Will. Incluir ReactGA em seu webpack (como é executado no clientside) tem um efeito significativo no tamanho de sua compilação?

@ChrisEdson https://github.com/react-ga/react-ga toda a biblioteca tem 161kb compactada.

Hmm. Isso é absolutamente incrível para ser honesto!

Na quinta-feira, 28 de fevereiro de 2019 às 19:01, William Li [email protected] escreveu:

@ChrisEdson https://github.com/ChrisEdson
https://github.com/react-ga/react-ga toda a biblioteca tem 161kb compactada.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/zeit/next.js/issues/160#issuecomment-468395136 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AC5okwth_o_BLLPeqIcSBmhKineAhYfgks5vSCeUgaJpZM4KkXxa
.

esse é o número listado no GitHub para toda a biblioteca.
Como verifico o tamanho real depois de empacotado no aplicativo?

Enviado do meu iPhone

Em 1 de março de 2019, às 15:43, Chris Edson [email protected] escreveu:

Hmm. Isso é absolutamente incrível para ser honesto!

Na quinta-feira, 28 de fevereiro de 2019 às 19:01, William Li [email protected] escreveu:

@ChrisEdson https://github.com/ChrisEdson
https://github.com/react-ga/react-ga toda a biblioteca tem 161kb compactada.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/zeit/next.js/issues/160#issuecomment-468395136 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AC5okwth_o_BLLPeqIcSBmhKineAhYfgks5vSCeUgaJpZM4KkXxa
.

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub ou ignore a conversa.

Portanto, o script reduzido tem 15kb. Isso é muito pequeno.

Vou agrupar, analisar meu webpack e relatar o quanto ele adiciona na prática.

Com um tamanho de pacote total de ~ 500kb, meu ReactGA adiciona cerca de 27kb. Tão pequeno no grande esquema das coisas.

Apenas adicionando minha solução a isso aqui, caso possa ser útil para alguém mais tarde.

Usei o react-ga, mas a mesma lógica deve funcionar com outras ferramentas ga.

_app.js 's getInitialProps é disparado no lado do cliente sempre que o usuário clica em uma nova rota. (Primeira vez, ele será executado no lado do servidor).

componentDidMount de _app.js é executado apenas no lado do cliente.

Portanto, no meu _app.js , adicionei as seguintes linhas de código


static async getInitialProps({ Component, router, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);      
    }

    // client-side only, run on page changes, do not run on server (SSR)
    if (typeof(window) === "object") {
      ReactGA.pageview(ctx.asPath);
    }
    return { pageProps, router }
  }


  componentDidMount() {
    // client-side only, run once on mount
    ReactGA.initialize('UA-XXXXXXX-3');
    ReactGA.pageview(window.location.pathname + window.location.search);
  }

Quando a página for renderizada no servidor, nada acontecerá em getInitialProps quando envolvi o código GA em typeof(window) === "object" .

No lado do cliente, getInitialProps não será executado pela primeira vez, pois tudo é renderizado pelo servidor. GA é configurado dentro de componentDidMount no lado do cliente.

As alterações de rota subsequentes (mesmo para a mesma rota), irão acionar getInitialProps no lado do cliente e o evento ga é acionado.

Um problema que surge se você estiver usando o NextJS 9 é desabilitar a pré-renderização automática. Querendo saber se há um lugar melhor para colocar ReactGA.pageview(ctx.asPath); , removê-lo de getInitialProps significa que podemos remover getInitialProps e não forçar a pré-renderização automática a cancelar, conforme descrito aqui: https : //err.sh/next.js/opt-out-automatic-prerendering.

Atualização: encontrei o exemplo with-google-analytics (https://github.com/zeit/next.js/tree/canary/examples/with-google-analytics) e peguei emprestado a parte sobre: Router.events.on('routeChangeComplete', url => ReactGA.pageview(url)) Preciso testar isso para ter certeza de que o url está correto, mas parece ser do jeito certo. Eu removi o método getInitialProps e adicionei acima da declaração da classe.

@GodOfGrandeur Isso parece promissor, vou tentar no prod. A versão mencionada acima não funcionou ou parecia que sim https://medium.com/@austintoddj/using -google-analytics-with-next-js-423ea2d16a98 Adicionar seu código em _app.js parece ser acionado em todos os lugares, conforme necessário e também gosto de não ser acionado no servidor (não seria, embora seja um problema).

Não há necessidade de terceiros. Se você estiver usando gtag, use o seguinte código que criei: -

<script
    async
    src="https://www.googletagmanager.com/gtag/js?id=%your code here%" >
</script>
<script dangerouslySetInnerHTML={
    { __html: `
        window.dataLayer = window.dataLayer || [];
        function gtag(){window.dataLayer.push(arguments)}
        gtag("js", new Date());
        gtag("config", "<%your code here%>");
    `}
}>
</script>

Outra opção é usar useEffect() . Fiz isso no meu arquivo Layout.js .

useEffect(() => {
  if (process.env.NODE_ENV === 'production') {
    window.dataLayer = window.dataLayer || []
    function gtag() {
      dataLayer.push(arguments)
    }
    gtag('js', new Date())
    gtag('config', '{GOOGLE ANALYTICS CODE}', {
      page_location: window.location.href,
      page_path: window.location.pathname,
      page_title: window.document.title,
    })
  }
})

E no <Head> :

<Head>
  <script async src="https://www.googletagmanager.com/gtag/js?id={GOOGLE ANALYTICS CODE}"></script>
</Head>

@reinink Apenas quero mencionar que você pode querer passar um array vazio como o segundo prop para useEffect para que ele execute a função apenas uma vez após a renderização inicial.

useEffect(() => {...}, [])

Expandindo a solução do @reinink , aqui está um HOC funcional que uso para envolver meus componentes / modelos de layout.

import React, { useEffect } from 'react'
import Head from 'next/head'
const GoogleAnalyticsHOC = ({ children }) => {
  useEffect(() => {
    if (process.env.NODE_ENV === 'production') {
      window.dataLayer = window.dataLayer || []
      // eslint-disable-next-line
      function gtag() {
        window.dataLayer.push(arguments)
      }
      gtag('js', new Date())
      gtag('config', process.env.GOOGLE_ANALYTICS_ID, {
        page_location: window.location.href,
        page_path: window.location.pathname,
        page_title: window.document.title
      })
    }
  }, [])
  return (
    <>
      <Head>
        <script async src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GOOGLE_ANALYTICS_ID}`} />
      </Head>
      {children}
    </>
  )
}
export default GoogleAnalyticsHOC

Não foi testado exaustivamente, mas funciona e me passa como um visitante em tempo real executando localmente. :)

Encontrei este guia - esta é uma abordagem recomendada (usa react-ga)?

Eu diria que a forma recomendada é usar este exemplo oficial:

https://github.com/zeit/next.js/tree/canary/examples/with-google-analytics

Já está postado aqui. Às vezes, desejo que os problemas do github sejam mais parecidos com stackoverflow, tendo alguma resposta aceita e destacada, logo após a pergunta (quando há muitas mensagens e emojis não é suficiente. Uma opção é restringir os comentários deste post, para que as pessoas criem um novo problema em vez disso. E enquanto criam, eles descobrirão que um problema semelhante já foi criado (graças ao recurso "problemas semelhantes"), e tem uma resposta (mas ainda assim, a resposta com emojis está perdida em algum lugar no meio de uma longa história, então é não é muito conveniente encontrar respostas no github).

Já está postado aqui. Às vezes eu desejo que os problemas do github sejam mais parecidos com stackoverflow, tendo alguma resposta aceita e destacada, logo após a pergunta (quando há muitas mensagens e emojis não é suficiente ...

O Github está fazendo um protótipo disso na guia Discussões deste repo.

Screenshot 2020-04-08 at 16 59 58

@janbaykara uau, sério? Todos nós pensamos da mesma maneira :) Espero que eles encontrem uma maneira de de alguma forma traduzir um problema em uma discussão, ou será a mesma coisa (se a funcionalidade for mesclada com os problemas, e todas as discussões existentes se tornarem problemas). Mas obrigado pela resposta!

@ 3lonious Eu pessoalmente

Em relação a Next.js, verifique https://github.com/UnlyEd/next-right-now/blob/v2-mst-aptd-gcms-lcz-sty/src/components/pageLayouts/Head.tsx (usando next/Head ), é assim que incluo tags de script em meus aplicativos.

Não hesite em dar uma olhada em NRN https://unlyed.github.io/next-right-now , ele pretende ser um bom exemplo de "como fazer X" com Next.js e deve evitar muitas dores de cabeça.

Não tenho certeza se entendi, não vejo nenhuma tag de script nesse arquivo.

Esta também é uma solução que funciona. Eu não testei extensivamente, então faça você mesmo.

Em pages/_document.js , adicione isso ao seu <Head> . Consulte a documentação sobre como substituir o arquivo do documento .

<script async src='https://www.googletagmanager.com/gtag/js?id=YOUR_GA_TRACKING_ID'></script>
<script
    dangerouslySetInnerHTML={{
        __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments)}
            gtag('js', new Date());

            gtag('config', 'YOUR_GA_TRACKING_ID');
              `
      }}>
</script>

Ele relata o tráfego para minha conta do GA, pelo menos.

@ 3lonious As tags de script e de estilo funcionam da mesma maneira.
A solução acima também funciona, por experiência própria. (é como eu costumava fazer o GA funcionar)

ok, obrigado pessoal. vou tentar voltar para você

ok, eu acho que consegui funcionar

obrigado Anton. ok eu tenho um novo para você haha

Eu tenho um aplicativo de bate-papo que uso para atendimento ao cliente, mas essa tag de script também não funciona? alguma ideia?

está me dizendo para adicionar essa segunda tag no corpo? o que você faz com isso?
Screen Shot 2020-06-19 at 6 48 22 AM

Que tal TBT? Se você adicionar o google analytics, sua pontuação de velocidade diminuirá

Que tal TBT? Se você adicionar o google analytics, sua pontuação de velocidade diminuirá

Isso se deve à recomendação de colocar o script antes do conteúdo. Se você colocá-lo sob o conteúdo, a pontuação não diminuirá.

Eu pessoalmente não vejo benefícios reais em colocar o script em primeiro lugar. Se o carregamento da página foi interrompido de alguma forma, e o HTML não carregou completamente de alguma forma e foi abortado, então eu não posso contar como um hit, que seja.

Estou trabalhando com nextjs. Estou tentando usar a API de conclusão automática do reac google place. E quer inserir aquela tag de script da API? Onde devo inserir a tag do script ??

_app.js

`` `js
importar ReactGA de "react-ga";

componentDidMount() {
  ReactGA.initialize("XX-XXXXXXXXX-X", { debug: false });
  ReactGA.set({ page: this.props.router.pathname });
  ReactGA.pageview(this.props.router.pathname);
  this.unlisten = this.props.router.events.on("routeChangeComplete", (router) => {
      ReactGA.set({ page: router });
      ReactGA.pageview(router);
    });
}

Isso é hilário. Não, na verdade isso é triste. Mal posso esperar para React, Next, todo o ecossistema morrer.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

formula349 picture formula349  ·  3Comentários

wagerfield picture wagerfield  ·  3Comentários

sospedra picture sospedra  ·  3Comentários

olifante picture olifante  ·  3Comentários

DvirSh picture DvirSh  ·  3Comentários