Next.js: ¿Agregar etiqueta de secuencia de comandos de GA?

Creado en 30 oct. 2016  ·  74Comentarios  ·  Fuente: vercel/next.js

¡Hola!

Actualmente estoy convirtiendo mi sitio web en un proyecto next.js y no puedo averiguar cómo agregar la etiqueta de secuencia de comandos de Google Analytics a la página. ¿Alguna idea?

Salud,
Robin

Comentario más útil

No es necesario react-ga . Utilice el administrador de etiquetas de Google con el componente <Head> para inyectar análisis. Hay algunos pequeños cambios en el código del administrador de etiquetas de Google necesarios para que funcione en 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 comentarios

pagar <Head>

@robinvdvleuten Sugeriría crear un componente GoogleTagManager e incluirlo en el encabezado o inmediatamente después, según su elección de implementación.

como la gente mencionó, puede usar la etiqueta Head o una solución fácil de reaccionar como https://github.com/react-ga/react-ga

¿Algún consejo sobre cómo hacer que react-ga funcione con next.js?

@gtramontina debería funcionar. De lo contrario, soy uno de los contribuyentes de react-ga por lo que podría ayudar con eso

No es necesario react-ga . Utilice el administrador de etiquetas de Google con el componente <Head> para inyectar análisis. Hay algunos pequeños cambios en el código del administrador de etiquetas de Google necesarios para que funcione en 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

Recomendaría una mejor solución para rastrear la vista de la página del lado del cliente: autotrack. Consulte https://github.com/MoOx/phenomic/issues/384 para obtener más información.

@impronunciable , sería genial tener un ejemplo, ya que después de buscar en Google todavía estoy confundido 😃 ¿Podría reabrirse?

  • @MoOx parece implicar que react-ga no es necesario, debería usar Google AutoTrack en su lugar
  • pero Autotrack indica que cree una etiqueta de script con código que acceda al objeto window , por lo que no funciona en el lado del servidor
  • y de todos modos, si usa un componente de reacción como react-ga, ¿dónde debería colocarse? En un render ? componentWillMount ? getInitialProps ? No está muy claro, ya que supone que usa react-router y carga el código una sola vez para todas las páginas.

El seguimiento de la página debería funcionar tanto cuando la página está renderizada por el servidor como cuando se navega a otra página. Sería genial ver cómo debería integrarse todo en una aplicación típica de Next con un encabezado, un diseño de página HOC, etc.

También sería bueno saber si cree que hay una combinación mejor / más simple / menos engorrosa / más avanzada que Next.js + Google Analytics Autotrack ...

Puedo investigar esto

El martes 17 de enero de 2017 a las 7:59 a.m. Sébastien Dubois [email protected]
escribió:

@impronunciable https://github.com/impronunciable sería genial
tengo un ejemplo, ya que después de buscar en Google todavía estoy confundido 😃 ¿Podría esto
ser reabierto?

  • @MoOx https://github.com/MoOx parece implicar que react-ga no lo es
    necesario, debe utilizar Google AutoTrack
    https://github.com/googleanalytics/autotrack en su lugar
  • pero Autotrack indica que cree una etiqueta de script con código que
    accede al objeto de la ventana, por lo que no funciona del lado del servidor
  • y de todos modos si usa un componente de reacción como react-ga, ¿dónde debería
    ser puesto? ¿En un render? componenteWillMount? getInitialProps? No es
    super claro, ya que supone que usa react-router y carga el
    codifique una sola vez para todas las páginas.

El seguimiento de la página debería funcionar tanto cuando la página está renderizada por el servidor como
luego, al navegar a otra página. Sería genial ver cómo
todo debería integrarse en una aplicación típica de Next con un encabezado, una página
diseño HOC, etc.

También sería bueno saber si cree que hay una mejor / más simple / menos
combinación engorrosa / más avanzada que Next.js + Google
Autotrack de análisis ...

-
Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/zeit/next.js/issues/160#issuecomment-273108099 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AAKHp9-2bfLXj2hMGlNlkqUSRqEL7R2Cks5rTJ8kgaJpZM4KkXxa
.

Estoy bastante seguro de que el autotrack es más que suficiente, solo se inyecta en el lado del cliente, no es necesario pensar en el lado del servidor.

Consulte https://github.com/MoOx/react-toulouse/commit/c42045d1001ab813c5d7eae5ab2f4f8c08c0025e para ver un ejemplo. No se usa a continuación, pero creo que debería ser fácil de adaptar.

Sí, no queremos rastrear las representaciones del servidor, ya que ofuscará cosas como la ubicación.

No, no lo hace, ya que será manejado por el cliente: tenga en cuenta que el cliente solicita una página y se procesará en el navegador del cliente :)

OK, no me di cuenta de que el código no debería ejecutarse en el lado del servidor. Entonces usé autotrack según lo recomendado por @MoOx , creo que esto debería funcionar: https://github.com/relatenow/relate/commit/50dc3f317eb3efa045d5bbe40d1a1a1ad1116458

Aún no he confirmado si cuenta las visitas a la página correctamente, esto es nuevo para mí 😬 😄

Puede utilizar la vista "en tiempo real" para depurar GA fácilmente.

@MoOx sí bueno eso es lo que me molesta, no veo nada en el panel en tiempo real cuando visito https://relate.now.sh en paralelo en otra pestaña (0 usuarios activos)

Todavía no obtengo esto ... No obtengo ningún dato con el código que escribí.

Todos los ejemplos que veo parecen requerir un <script href="https://www.google-analytics.com/analytics.js" async /> pero las cosas en Head no parecen ejecutarse en el cliente. (mi console.log no está impreso en la consola del navegador ...)

Un ejemplo aún sería muy apreciado 🙂

Como hiciste que funcionara? He estado intentando llamar a una función de vista de página en componentDidMount .

La aplicación de producción GA Check falla.

@luandro no recuerda los detalles, pero puede ver el compromiso que vinculé arriba si ayuda

Lo hice y lo probé. Hice lo mismo que tú, llamé a configureAnalytics en la parte superior y a la vista de página en componentWillMount , pero todavía obtengo negativo en GA Check .

En su código, no parece que haya conectado la página hoc a ninguna parte, ¿verdad?

@luandro Simplemente agregue ga(‘set’, ‘page’, window.location.pathname); ga(‘send’, ‘pageview’); para cambiar la URL del evento de vista de página.

Tal vez haya una forma más 'next.js' de hacer esto, pero WRT ejecutando scripts en la página, encontré que si creaba un componente Script así:

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

Entonces podría hacer esto que funcionó para mí:

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

La advertencia es que debe incluir todo en una función.

¿Es posible realizar un seguimiento de las páginas vistas individuales sin llamar explícitamente a ga ('enviar', 'página vista') en cada página? Si es absolutamente necesario hacerlo, ¿dónde lo invocamos para tener la certeza de que se ha cargado ga?

¿Es posible vincular los eventos de cambio de ruta de alguna manera para registrar páginas vistas?

@karthikiyengar Estoy usando react-ga como sugirieron otros arriba y registrando páginas vistas en 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 ¿ es una práctica común initGA para cada componente de la página?

@rongierlach Estoy usando un componente Layout que llama a los métodos initialize y pageview en 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 es la forma más limpia que he hecho hasta ahora, ya que si la página estuviera renderizada por el servidor, debe inicializarse. Estoy seguro de que hay un gancho que podría omitir la inicialización si es renderizado por el cliente.

@notrab , ¿no podrías perder los renders superficiales? Su aplicación simplemente hará la transición y es posible que su componente de diseño no se vuelva a montar. Esto es lo que tengo para atraparlos.

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

Intentando que esto funcione, pero aún no hay respuesta de Google Analytics. Este es mi código en 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

Y mi página de índice:

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

con el código UA reemplazado por mi código real, por supuesto.

@filostrato ¿Cómo lo arreglaste? Yo también estoy atascado. :)

@exogenesys Terminó poniendo esto en 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

y cambié mi Layout.js para extender 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>
    )
  }
}

No encontré una manera de hacerlo funcionar en un componente que utiliza getInitialProps , pero como Layout.js no funcionó bien; No estoy seguro de qué hacer si quiero estadísticas más detalladas, pero cruzaré ese puente cuando llegue.

@filostrato Eso lo hizo. Muchas gracias. :)

Hola chicos

También me he ocupado de la implementación de GA en mi sitio y esto es lo que se me ocurrió.

Primero usé la solución de @notrab que parecía limpia y sencilla:

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

  render() {
    …
  }
}

Sin embargo, noté:

  • componentDidMount se ejecutó cuando cambié entre páginas de diferentes tipos, por lo que la función initialize se llamó varias veces
  • componentDidMount se ejecutó _only_ cuando cambié entre páginas de diferentes tipos, por lo que la función pageview se llamó solo entonces => Tengo un tipo de página video en mi sitio web y vi en la vista en vivo de GA que, al cambiar entre diferentes páginas de video, solo se realizó un seguimiento de la página de video inicial

Creé un componente de orden superior para abordar estos dos problemas. Para el primero usé la solución de

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

Y en su componente <Layout> / <PageWrapper> / <PageScaffold> o como lo llame:

import GaWrapper from './ga-wrapper';

const PageScaffold = () => (…);

export default GaWrapper(PageScaffold);

Quizás eso ayude a alguien.

Sin embargo, no me gusta la llamada de Router.router.events.… , porque esto no es parte de la API documentada. Sin embargo, cuando intenté llamar a Router.onRouteChangeComplete que debería ser la forma correcta , obtuve un ReferenceError porque onRouteChangeComplete era undefined . ¿Quizás la documentación está desactualizada?

Esto me ha funcionado en un sitio web next.js. Y evité el error de 'ventana no definida' con el que me estaba encontrando con la implementación habitual de react-ga.

La solución

Gracias al código de pageview usando el nuevo gtag Google (que reemplaza los scripts de _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 / cualquiera que sea el nombre de su proyecto:

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 cualquiera que llegue tarde a la fiesta, la razón por la que la solución de componentDidMount . Definirlos fuera del componente parece solucionar el problema:

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

@trezy cuando usa gtag , parece que no hay necesidad de import ReactGA from 'react-ga' .

Usé su ejemplo <script dangerouslySetInnerHtml={...} /> y acabo de agregar esta línea en la inyección:

window.gaTrackingId = '${gaTrackingId}';

Luego, este truco ligero comenzó 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,
    });
  }
};

Ya no se recupera un analytics.js bastante grande, ¡pero se sigue rastreando todas las páginas!

Dado que esto no es obvio, sería bueno tener un ejemplo en el repositorio.

O un repositorio next-google-analytics 🕵️

@prichodko ¡¡ Muchas gracias por armar este ejemplo !!

encontré una biblioteca bastante buena, agregada al archivo de diseño principal en componentDidMount () y parece funcionar correctamente. Está bien documentado, sin prisas.

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

@andylacko De hecho, lo había bifurcado para arreglar algunas cosas, como HTTPS, por ejemplo: https://github.com/Vadorequest/react-gtm

Solo agrego mi solución a esto aquí en caso de que pueda ser útil para alguien más adelante.

Usé react-ga pero la misma lógica debería funcionar con otras herramientas de ga.

El getInitialProps de _app.js se activa en el lado del cliente cada vez que el usuario hace clic en una nueva ruta. (La primera vez que se ejecutará en el lado del servidor).

componentDidMount de _app.js ejecuta solo en el lado del cliente.

Entonces, en mi _app.js , agregué las siguientes líneas 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);
  }

Cuando la página se procesa en el servidor, no sucederá nada en getInitialProps ya que envolví el código GA en typeof(window) === "object" .

En el lado del cliente, getInitialProps no se ejecutará por primera vez ya que todo se procesa en el servidor. GA se configura dentro de componentDidMount en el lado del cliente.

Los cambios de ruta posteriores (incluso para la misma ruta) activarán getInitialProps en el lado del cliente y se activará el evento ga.

Solo agrego mi solución a esto aquí en caso de que pueda ser útil para alguien más adelante.

Usé react-ga pero la misma lógica debería funcionar con otras herramientas de ga.

El getInitialProps de _app.js se activa en el lado del cliente cada vez que el usuario hace clic en una nueva ruta. (La primera vez que se ejecutará en el lado del servidor).

componentDidMount de _app.js ejecuta solo en el lado del cliente.

Entonces, en mi _app.js , agregué las siguientes líneas 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);
  }

Cuando la página se procesa en el servidor, no sucederá nada en getInitialProps ya que envolví el código GA en typeof(window) === "object" .

En el lado del cliente, getInitialProps no se ejecutará por primera vez ya que todo se procesa en el servidor. GA se configura dentro de componentDidMount en el lado del cliente.

Los cambios de ruta posteriores (incluso para la misma ruta) activarán getInitialProps en el lado del cliente y se activará el evento ga.

Hola Will. ¿Incluir ReactGA en su paquete web (ya que se ejecuta en el lado del cliente) tiene un efecto significativo en el tamaño de su compilación?

@ChrisEdson https://github.com/react-ga/react-ga toda la biblioteca tiene 161 kb comprimidos.

Hmm. ¡Eso es absolutamente enorme para ser honesto!

El jueves 28 de febrero de 2019 a las 19:01, William Li [email protected] escribió:

@ChrisEdson https://github.com/ChrisEdson
https://github.com/react-ga/react-ga toda la biblioteca tiene 161 kb comprimidos.

-
Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/zeit/next.js/issues/160#issuecomment-468395136 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AC5okwth_o_BLLPeqIcSBmhKineAhYfgks5vSCeUgaJpZM4KkXxa
.

ese es el número que aparece en GitHub para toda la biblioteca.
¿Cómo verifico el tamaño real una vez empaquetado en la aplicación?

Enviado desde mi iPhone

El 1 de marzo de 2019, a las 15:43, Chris Edson [email protected] escribió:

Hmm. ¡Eso es absolutamente enorme para ser honesto!

El jueves 28 de febrero de 2019 a las 19:01, William Li [email protected] escribió:

@ChrisEdson https://github.com/ChrisEdson
https://github.com/react-ga/react-ga toda la biblioteca tiene 161 kb comprimidos.

-
Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/zeit/next.js/issues/160#issuecomment-468395136 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AC5okwth_o_BLLPeqIcSBmhKineAhYfgks5vSCeUgaJpZM4KkXxa
.

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub o silencia el hilo.

Entonces, el guión minificado es 15kb. Eso es bastante pequeño.

Voy a analizar el paquete de mi paquete web e informar sobre cuánto agrega en la práctica.

Dentro de un tamaño de paquete total de ~ 500 kb, mi ReactGA agrega aproximadamente 27 kb. Tan pequeño en el gran esquema de las cosas.

Solo agrego mi solución a esto aquí en caso de que pueda ser útil para alguien más adelante.

Usé react-ga pero la misma lógica debería funcionar con otras herramientas de ga.

El getInitialProps de _app.js se activa en el lado del cliente cada vez que el usuario hace clic en una nueva ruta. (La primera vez que se ejecutará en el lado del servidor).

componentDidMount de _app.js ejecuta solo en el lado del cliente.

Entonces, en mi _app.js , agregué las siguientes líneas 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);
  }

Cuando la página se procesa en el servidor, no sucederá nada en getInitialProps ya que envolví el código GA en typeof(window) === "object" .

En el lado del cliente, getInitialProps no se ejecutará por primera vez ya que todo se procesa en el servidor. GA se configura dentro de componentDidMount en el lado del cliente.

Los cambios de ruta posteriores (incluso para la misma ruta) activarán getInitialProps en el lado del cliente y se activará el evento ga.

Un problema que surge si está utilizando NextJS 9 es que esto con deshabilita la representación previa automática. Si nos preguntamos si hay un lugar mejor para colocar el ReactGA.pageview(ctx.asPath); , eliminarlo de getInitialProps significa que podemos eliminar getInitialProps y no forzar a la representación previa automática a excluirse como se describe aquí: https : //err.sh/next.js/opt-out-automatic-prerendering.

Actualización: encontré el ejemplo with-google-analytics (https://github.com/zeit/next.js/tree/canary/examples/with-google-analytics) y tomé prestado el bit sobre: Router.events.on('routeChangeComplete', url => ReactGA.pageview(url)) Necesito probar esto para asegurarme de que la URL sea correcta pero se vea de la manera correcta. Eliminé el método getInitialProps y lo agregué encima de la declaración de clase.

@GodOfGrandeur Esto suena prometedor, lo intentaré en prod. La versión mencionada anteriormente no funcionaba o parecía que sí https://medium.com/@austintoddj/using -google-analytics-with-next-js-423ea2d16a98 Agregar su código en _app.js parece activarse en todas partes según sea necesario y también me gusta que no se active en el servidor (no lo habría hecho, aunque es un problema).

No es necesario ningún tercero, si está utilizando gtag, utilice el siguiente código que creé:

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

Otra opción es usar useEffect() . He hecho esto dentro de mi archivo 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,
    })
  }
})

Y en el <Head> :

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

@reinink Solo quiero mencionar que es posible que desee pasar una matriz vacía como segundo accesorio a useEffect para que solo ejecute la función una vez después del renderizado inicial.

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

Ampliando la solución de @reinink , aquí hay un HOC funcional que utilizo para envolver mis componentes / plantillas de diseño.

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

No se ha probado exhaustivamente, pero funciona y me hago pasar por un visitante en tiempo real que se ejecuta localmente. :)

Encontré esta guía : ¿es este un enfoque recomendado (usa react-ga)?

Yo diría que la forma recomendada es usar este ejemplo oficial:

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

Ya está publicado aquí. A veces deseo que los problemas de github se parezcan más a stackoverflow, que acepten y resalten algunas respuestas justo después de la pregunta (cuando hay demasiados mensajes y emojis no es suficiente. Una opción es restringir los comentarios de esta publicación, para que la gente cree un nuevo problema en su lugar. Y mientras crean, encontrarán que ya se creó un problema similar (gracias a la función "problemas similares"), y tiene una respuesta (pero aún así, la respuesta con emojis se pierde en algún lugar en medio de una larga historia, por lo que es no es muy conveniente encontrar respuestas en github).

Ya está publicado aquí. A veces deseo que los problemas de github se parezcan más a stackoverflow, que acepten y resalten algunas respuestas justo después de la pregunta (cuando hay demasiados mensajes y emojis no es suficiente ...

Github está creando un prototipo de esto en la pestaña Discusiones de este repositorio.

Screenshot 2020-04-08 at 16 59 58

@janbaykara wow, ¿en serio? Todos pensamos de la misma manera :) Sin embargo, espero que encuentren una manera de traducir un problema en una discusión, o será lo mismo (si la funcionalidad se fusionará con los problemas y todas las discusiones existentes se convertirán en problemas). ¡Pero gracias por la respuesta!

@ 3lonious He abandonado personalmente Google Analytics, ya que no hace un buen trabajo con SPA en general. (experiencia realmente mala, especialmente con SSR + CSR y eventos dobles difíciles de rastrear)

Con respecto a Next.js, consulte https://github.com/UnlyEd/next-right-now/blob/v2-mst-aptd-gcms-lcz-sty/src/components/pageLayouts/Head.tsx (usando next/Head ), así es como incluyo etiquetas de script en mis aplicaciones.

No dude en echar un vistazo a NRN https://unlyed.github.io/next-right-now , está destinado a ser un buen ejemplo de "cómo hacer X" con Next.js y debería ahorrarle bastantes dolores de cabeza.

No estoy seguro de entenderlo, ¿no veo ninguna etiqueta de script en ese archivo?

Esta también es una solución que funciona. No lo he probado extensamente, así que hágalo usted mismo.

En pages/_document.js , agregue esto a su <Head> . Consulte los documentos sobre cómo anular el archivo del 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>

Informa el tráfico a mi cuenta de GA al menos.

Las etiquetas de
La solución anterior también funciona, por experiencia. (así es como solía hacer funcionar GA)

ok gracias chicos. Voy a intentar responderte

ok, creo que lo hice funcionar

gracias Anton. ok tengo uno nuevo para ti jaja

Tengo una aplicación de chat que uso para el servicio al cliente, pero esa etiqueta de script tampoco funciona. ¿algunas ideas?

¿Me está diciendo que agregue esta segunda etiqueta en el cuerpo? ¿Qué haces con eso?
Screen Shot 2020-06-19 at 6 48 22 AM

¿Qué hay de TBT? Si agrega Google Analytics, reducirá su puntaje de velocidad

¿Qué hay de TBT? Si agrega Google Analytics, reducirá su puntaje de velocidad

Eso se debe a su recomendación de colocar el guión antes que el contenido. Si lo coloca debajo del contenido, la puntuación no bajará.

Personalmente, no veo los beneficios reales de colocar el guión primero. Si la carga de la página se interrumpió de alguna manera, y HTML no se cargó por completo de alguna manera y se canceló, entonces es posible que no lo cuente como un éxito, así que como sea.

Estoy trabajando con nextjs. Estoy tratando de usar la API de autocompletar react google place. ¿Y quiere insertar esas etiquetas de script de API? ¿Dónde debo insertar esas etiquetas de script?

_app.js

`` js
importar ReactGA desde "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);
    });
}

Esto es muy gracioso. No, en realidad esto es triste. No puedo esperar a que React, Next, muera todo el ecosistema.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

wagerfield picture wagerfield  ·  3Comentarios

olifante picture olifante  ·  3Comentarios

knipferrc picture knipferrc  ·  3Comentarios

swrdfish picture swrdfish  ·  3Comentarios

DvirSh picture DvirSh  ·  3Comentarios