¿Cómo configurar Google Analytics para React-Router?

82

Estoy intentando configurar Google Analytics en mi sitio de reacción y me he encontrado con algunos paquetes, pero ninguno tiene el tipo de configuración que tengo en términos de ejemplos. Esperaba que alguien pudiera arrojar algo de luz sobre esto.

El paquete que estoy viendo es react-ga .

Mi método de renderizado en mi se index.jsve así.

React.render((
<Router history={createBrowserHistory()}>
    <Route path="/" component={App}>
        <IndexRoute component={Home} onLeave={closeHeader}/>
        <Route path="/about" component={About} onLeave={closeHeader}/>
        <Route path="/gallery" component={Gallery} onLeave={closeHeader}/>
        <Route path="/contact-us" component={Contact} onLeave={closeHeader}>
            <Route path="/contact-us/:service" component={Contact} onLeave={closeHeader}/>
        </Route>
        <Route path="/privacy-policy" component={PrivacyPolicy} onLeave={closeHeader} />
        <Route path="/feedback" component={Feedback} onLeave={closeHeader} />
    </Route>
    <Route path="*" component={NoMatch} onLeave={closeHeader}/>
</Router>), document.getElementById('root'));
John Fu
fuente
4
Publicado una respuesta para react-router-4/ a react-router-domcontinuación, la respuesta principal aquí es para versiones anteriores de react-router y desafortunadamente no funcionará con v4.
Peter Berg
¿Cómo agrego esto con StaticRouter mientras estoy usando react SSR?
Subhendu Kundu

Respuestas:

83

Mantenga una referencia a su objeto de historial. es decir

import { createBrowserHistory } from 'history';

var history = createBrowserHistory();

ReactDOM.render((
    <Router history={history}>
        [...]

Luego agregue un oyente para registrar cada página vista. (Esto supone que ya ha configurado el window.gaobjeto de la forma habitual).

history.listen((location) => {
    window.ga('set', 'page', location.pathname + location.search);
    window.ga('send', 'pageview');
});
David L. Walsh
fuente
16
Esto no tendrá en cuenta los eventos u otros tipos de visitas que se envíen. Seguirán haciendo referencia a la URL en el momento de la carga de la página. En su lugar, deberá establecer el nuevo valor en el rastreador antes de enviar la vista de página, por ejemplo ga('set', 'page', location.pathname + location.search); ga('send', 'pageview');.
Philip Walton
1
Hola David, ¿tu ejemplo usa código ga regular del sitio de ga o está usando el paquete react-ga? Gracias.
John Fu
Aún no he decidido cómo solucionarlo, pero esta información también podría ser útil: stackoverflow.com/questions/30052693/… (explica por qué la atribución podría no funcionar correctamente en algunos casos y también presenta altas tasas de rebote ).
DeTeam
No desea un tercer parámetro en el comando de envío. "Si bien técnicamente el comando de envío para visitas a páginas vistas acepta un campo de página opcional como tercer parámetro, no se recomienda pasar el campo de página de esa manera al rastrear aplicaciones de una sola página. Esto se debe a que los campos pasados ​​a través del comando de envío no están configurados en el rastreador: se aplican solo al hit actual. No actualizar el rastreador causará problemas si su aplicación envía visitas que no sean visitas a la página (por ejemplo, eventos o interacciones sociales), ya que esas visitas se asociarán con cualquier valor de página que tuviera el rastreador cuando se creó. "
Joshua Robinson
29

Dado que Google Analytics se carga e inicializa con un ID de seguimiento.

Aquí hay una solución para react-router versión 4 que usa el <Route>componente para rastrear las vistas de página.

<Route path="/" render={({location}) => {
  if (typeof window.ga === 'function') {
    window.ga('set', 'page', location.pathname + location.search);
    window.ga('send', 'pageview');
  }
  return null;
}} />

Simplemente representa este componente dentro de <Router>(pero no como un hijo directo de a <Switch>).

Lo que sucede es que cada vez que cambia la propiedad de ubicación, se produce una nueva representación de este componente (que en realidad no representa nada) que activa una vista de página.

heyhugo
fuente
1
React-router 4. ¿Hay algo que no pueda hacer?
Anthony Cregan
1
Publicó otra solución de react-router-4 a continuación que no implica la modificación de rutas individuales. Lamentablemente, esta es definitivamente una situación del tipo "elige tu veneno".
Peter Berg
1
¿No significa esto que ir a "/" no generará nada?
Dana Woodman
3
Solo tienes otra ruta que emita lo que quieras @DanaWoodman. Esto supone que la ruta no está en unSwitch
bozdoz
¿Esto rastreará dos páginas vistas en la página de destino? Al ver que GA rastrea la página de destino automáticamente, activamos un evento de vista de página adicional para ella. ¿O GA lo filtra?
ArneHugo
27

Estoy usando React Router v4 y la etiqueta de sitio global de Google Analytics , que parece ser la recomendada en el momento de escribir esto.

Y esta es mi solución:

Cree un componente envuelto con enrutador desde react-router-dom:

import React from 'react';
import { withRouter } from 'react-router-dom';
import { GA_TRACKING_ID } from '../config';

class GoogleAnalytics extends React.Component {
    componentWillUpdate ({ location, history }) {
        const gtag = window.gtag;

        if (location.pathname === this.props.location.pathname) {
            // don't log identical link clicks (nav links likely)
            return;
        }

        if (history.action === 'PUSH' &&
            typeof(gtag) === 'function') {
            gtag('config', GA_TRACKING_ID, {
                'page_title': document.title,
                'page_location': window.location.href,
                'page_path': location.pathname
            });
        }
    }

    render () {
        return null;
    }
}

export default withRouter(GoogleAnalytics);

Simplemente agregue el componente dentro de su enrutador (creo que lo ideal sería después de cualquier ruta que coincidiera y cualquier componente de Switch, porque la función de análisis no debería tener prioridad sobre la representación de su sitio):

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import IndexPage from './IndexPage';
import NotFoundPage from './NotFoundPage';
import GoogleAnalytics from './GoogleAnalytics';

const App = () => (
    <Router>
        <Switch>
            <Route exact path="/" component={IndexPage} />
            <Route component={NotFoundPage} />
        </Switch>
        <GoogleAnalytics />
    </Router>
);

Como se dijo:

withRouter volverá a renderizar su componente cada vez que la ruta cambie con los mismos accesorios que los de renderizado

Entonces, cuando la ruta cambie, el GoogleAnalyticscomponente se actualizará, recibirá la nueva ubicación como accesorios y history.actionserá PUSHpara un nuevo elemento del historial o POPpara indicar que retrocede en el historial (lo que creo que no debería activar una vista de página, pero se puede ajustar el caso de declaraciones en componentWillUpdatecomo mejor le parezca (incluso se podría tratar componentDidUpdatecon el this.propslugar, pero estoy seguro de que es mejor)).

bozdoz
fuente
bozdoz ¿cómo agregaste la etiqueta global del sitio a tu página? ¿Acabas de añadir <script async src = " googletagmanager.com/gtag/js?id=GA_TRACKING_ID " > </… > a tu página html debajo de la etiqueta del cuerpo?
yo-yo
1
@ yo-yo Sí. Pero dentro de la etiqueta del cuerpo:<body> ... <script ...></script></body>
bozdoz
Se necesitaron algunos ajustes para el último React y React Router. Cambiar componentWillMounta componentDidMount. Cambie page_patha this.props.location.pathname. Envuelva los componentes de Switch y GoogleAnalytics en un <div>
mjhm
No estoy seguro de dónde está viendo componentWillMount, y no estoy seguro de en qué se page_pathdiferencia, pero intentaría incluir el componente Switch y GA en <React.Fragment>lugar de un div. ¡Gracias!
bozdoz
2
Hola @JoshuaRobinson, escribí en la parte inferior, "... Creo que no debería activar una vista de página, pero puedes ajustar ...". Esta pregunta trataba sobre la integración de Google Analytics con React Router, no sobre qué vistas debería registrar. Habiendo dicho eso, puedo ajustar mi componente, ya que Google lo rastreará de manera diferente en su extremo. Gracias.
bozdoz
19

Tenga en cuenta que si está utilizando el react-router-dompaquete de react-router-4puede manejar esto así:

import { Router, Route } from 'react-router-dom';
import { createBrowserHistory } from 'history';

const history = createBrowserHistory();
const initGA = (history) => {
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'YOUR_IDENTIFIER_HERE', 'auto');
  ga('send', 'pageview');

  history.listen((location) => {
    console.log("tracking page view: " + location.pathname);
    ga('send', 'pageview', location.pathname);
  });
};

initGA(history);

class App extends Component { //eslint-disable-line
  render() {
    return
      (<Router history={history} >
         <Route exact path="/x" component={x} />
         <Route exact path="/y" component={y} />
       </Router>)
  }
}

Tenga en cuenta que esto requiere que instale el historypaquete ( npm install history). Esto ya es una dependencia de react-router-dom, por lo que no agregará ningún peso de página aquí.

También tenga en cuenta: No es posible utilizar el componente BrowserRouter E instrumentar su seguimiento de GA de esta manera. Esto está bien porque el componente BrowserRouter es solo una envoltura muy delgada alrededor del objeto Router. Recreamos la funcionalidad BrowserRouter aquí con <Router history={history}>where const history = createBrowserHistory();.

Peter Berg
fuente
nunca llamas a initGA?
Muhammad Umer
@MuhammadUmer es cierto, lo acabo de arreglar
Peter Berg
¿Por qué no agrega el GA en su HTML estático? Yo te hice más 1. Porque creo que escuchar el objeto histórico es el camino correcto a seguir.
Vince V.
@VinceV. Posiblemente podría inicializar el historyobjeto dentro de su compilación y luego almacenar el historial en el windowobjeto y acceder a él en una etiqueta de secuencia de comandos en su, <head>pero creo que, en última instancia, terminaría haciendo que su canal de compilación sea más complicado. ¯_ (ツ) _ / ¯
Peter Berg
Si está utilizando el BrowserRoutercomponente, vea la respuesta a continuación que ofrece una solución alternativa.
Toshe
15

Sugeriría usar el excelente react-router-gapaquete que es extremadamente liviano y fácil de configurar, especialmente cuando se usa el BrowserRoutercontenedor.

Importar el componente:

import Analytics from 'react-router-ga';

Luego, simplemente agregue el <Analytics>dentro de su BrowserRouter:

<BrowserRouter>
    <Analytics id="UA-ANALYTICS-1">
        <Switch>
            <Route path="/somewhere" component={SomeComponent}/>
        </Switch>
    </Analytics>
</BrowserRouter>
A ella
fuente
Esta parece ser una solución súper simple si el usuario está interesado en rastrear solo las visitas a la página. ¡Muy delgado!
peyo
11

Me gusta cómo sugiere Mark Thomas Müller aquí :

En su index.js

import ReactGA from 'react-ga'

ReactGA.initialize('YourAnalyticsID')

ReactDOM.render(<App />, document.getElementById('root'))

Dónde están tus rutas:

import React, { Component } from 'react'
import { Router, Route } from 'react-router-dom'
import createHistory from 'history/createBrowserHistory'
import ReactGA from 'react-ga'

const history = createHistory()
history.listen(location => {
    ReactGA.set({ page: location.pathname })
    ReactGA.pageview(location.pathname)
})

export default class AppRoutes extends Component {
    componentDidMount() {
        ReactGA.pageview(window.location.pathname)
    }

    render() {
        return (
            <Router history={history}>
                <div>
                    <Route path="/your" component={Your} />
                    <Route path="/pages" component={Pages} />
                    <Route path="/here" component={Here} />
                </div>
            </Router>
        )
    }
}

Corto, escalable y simple :)

Jöcker
fuente
¿Por qué hay seguimiento, uno global, uno local?
Thellimist
10

Dado que react-router v5.1.0esto se puede resolver mucho más fácilmente con useLocation.

usePageTracking.js

import { useEffect} from "react";
import { useLocation } from "react-router-dom";
import ReactGA from "react-ga";

const usePageTracking = () => {
  const location = useLocation();

  useEffect(() => {
    ReactGA.initialize("UA-000000000-0");
    ReactGA.pageview(location.pathname + location.search);
  }, [location]);
};

export default usePageTracking;

App.js

const App = () => {
  usePageTracking();

  return (...);
};

Ver también:

Aquí hay una versión un poco más inteligente:

usePageTracking.js

import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import ReactGA from "react-ga";

const usePageTracking = () => {
  const location = useLocation();
  const [initialized, setInitialized] = useState(false);

  useEffect(() => {
    if (!window.location.href.includes("localhost")) {
      ReactGA.initialize("UA-000000000-0");
    }
    setInitialized(true);
  }, []);

  useEffect(() => {
    if (initialized) {
      ReactGA.pageview(location.pathname + location.search);
    }
  }, [initialized, location]);
};

export default usePageTracking;
este es mi diseño
fuente
No estoy seguro de que sea necesario con la última 'gtag'. Cuando navego, el depurador de ga parece registrar correctamente el evento push: Processing data layer push: {event: "gtm.historyChange-v2", gtm.historyChangeSource: "pushState", gtm.oldUrlFragment: "", gtm.newUrlFragment: "", gtm.oldHistoryState: null, gtm.newHistoryState: {key: "j5xoc4", state: undefined}, gtm.oldUrl: "https://site/", gtm.newUrl: "https://site/new-url?search-params", gtm.triggers: "1_36"}y se muestra una nueva vista de página en el tablero de ga
Dattaya
6

Siga siempre la forma recomendada por la biblioteca

En la documentación de React-GA, han agregado un componente de comunidad recomendado para usar con React Router: https://github.com/react-ga/react-ga/wiki/React-Router-v4-withTracker

Implementación

import withTracker from './withTracker';

ReactDOM.render(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <Route component={withTracker(App, { /* additional attributes */ } )} />
    </ConnectedRouter>
  </Provider>,
  document.getElementById('root'),
);

Código

import React, { Component, } from "react";
import GoogleAnalytics from "react-ga";

GoogleAnalytics.initialize("UA-0000000-0");

const withTracker = (WrappedComponent, options = {}) => {
  const trackPage = page => {
    GoogleAnalytics.set({
      page,
      ...options,
    });
    GoogleAnalytics.pageview(page);
  };

  // eslint-disable-next-line
  const HOC = class extends Component {
    componentDidMount() {
      // eslint-disable-next-line
      const page = this.props.location.pathname + this.props.location.search;
      trackPage(page);
    }

    componentDidUpdate(prevProps) {
      const currentPage =
        prevProps.location.pathname + prevProps.location.search;
      const nextPage =
        this.props.location.pathname + this.props.location.search;

      if (currentPage !== nextPage) {
        trackPage(nextPage);
      }
    }

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

  return HOC;
};

export default withTracker;
Paras
fuente
1
si utilizo SSR (representación del lado del servidor), el GA no conoce el título real de la página sin actualizar la página.
Francis Rodrigues
1
Puede cambiar el título en la montura usando React
Paras
¡Gracias por publicar!
Sailesh Kotha
de donde storeviene
user_78361084
¿De donde viene Providery de donde ConnectedRouterviene? Esta es una respuesta incompleta y debería ser
rechazada
2

Primero, en su index.js configure la función onUpdate para llamar a ga

import ga from 'ga.js';
onUpdate() {
  console.log('=====GA=====>', location.pathname);
  console.log('=====GA_TRACKING_CODE=====>', GA_TRACKING_CODE);
  ga("send", "pageview", location.pathname);
}

render() {
  return (
    <Router onUpdate={this.onUpdate.bind(this)}>...</Router>
  );
}

Y ga.js:

'use strict';
if(typeof window !== 'undefined' && typeof GA_TRACKING_CODE !== 'undefined') {
  (function(window, document, script, url, r, tag, firstScriptTag) {
    window['GoogleAnalyticsObject']=r;
    window[r] = window[r] || function() {
      (window[r].q = window[r].q || []).push(arguments)
    };
    window[r].l = 1*new Date();
    tag = document.createElement(script),
    firstScriptTag = document.getElementsByTagName(script)[0];
    tag.async = 1;
    tag.src = url;
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  })(
    window,
    document,
    'script',
    '//www.google-analytics.com/analytics.js',
    'ga'
  );

  var ga = window.ga;

  ga('create', GA_TRACKING_CODE, 'auto');

  module.exports = function() {
    return window.ga.apply(window.ga, arguments);
  };
} else {
  module.exports = function() {console.log(arguments)};
}
WeiYuan
fuente
¿Qué versión de enrutador se usa aquí?
Pavan
es para react router dom v2 o v3, no v4
Hugo Gresse
2

aquí hay una forma más sencilla de rastrear todas las rutas con algunas soluciones:

npm i --save history react-ga

crear un archivo history.js

import { createBrowserHistory } from "history"
import ReactGA from "react-ga"

ReactGA.initialize(process.env.REACT_APP_GA)

const history = createBrowserHistory()
history.listen((location) => {
    ReactGA.pageview(location.pathname)
})

// workaround for initial visit
if (window.performance && (performance.navigation.type === performance.navigation.TYPE_NAVIGATE)) {
    ReactGA.pageview("/")
}

export default history

y luego importarlo a donde está configurado su Router

import history from "./history"

...

class Route extends Component {
render() {
    return (
        <Router history={history}>
            <Switch>
              <Route path="/" exact component={HomePage} />
              ...
            </Switch>
        </Router>
    )
}

export default Route

Referencias:

Gustavo Gonzalez | medium.com

Historia | GitHub

fsilva
fuente
2

Sugiero usar la biblioteca de análisis de segmentos y seguir la guía de inicio rápido de React para realizar un seguimiento de las llamadas de página utilizando la biblioteca react-router . Puede permitir que el <Route />componente maneje cuando la página se procesa y se usa componentDidMountpara invocar pagellamadas. El siguiente ejemplo muestra una forma en que puede hacer esto:

    const App = () => (
      <div>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
        </Switch>
      </div>
    );

    export default App;
    export default class Home extends Component {
      componentDidMount() {
        window.analytics.page('Home');
      }

      render() {
        return (
          <h1>
            Home page.
          </h1>
        );
      }
    }

Soy el mantenedor de https://github.com/segmentio/analytics-react . Con Segment, podrá activar y desactivar diferentes destinos con solo tocar un interruptor si está interesado en probar varias herramientas de análisis (admitimos más de 250 destinos) sin tener que escribir ningún código adicional. 🙂

Guillermo
fuente
1

Si usa hash o historial del navegador, puede hacer:

import trackingHit from 'tracking';

import { Router, browserHistory } from 'react-router';
browserHistory.listen(trackingHit);
// OR
import { Router, hashHistory } from 'react-router';
hashHistory.listen(trackingHit);

donde ./tracking.es6

export default function(location) {
    console.log('New page hit', location.pathname);
    // Do your shizzle here
}
sidonaldson
fuente
0

implementación básica de react-ga con su index.js

var ReactGA = require('react-ga'); // require the react-ga module
ReactGA.initialize('Your-UA-ID-HERE'); // add your UA code 

function logPageView() { // add this function to your component
  ReactGA.set({ page: window.location.pathname + window.location.search });
  ReactGA.pageview(window.location.pathname + window.location.search);
}

React.render((
<Router history={createBrowserHistory()} onUpdate={logPageView} > // insert onUpdate props here
    <Route path="/" component={App}>
        <IndexRoute component={Home} onLeave={closeHeader}/>
        <Route path="/about" component={About} onLeave={closeHeader}/>
        <Route path="/gallery" component={Gallery} onLeave={closeHeader}/>
        <Route path="/contact-us" component={Contact} onLeave={closeHeader}>
            <Route path="/contact-us/:service" component={Contact} onLeave={closeHeader}/>
        </Route>
        <Route path="/privacy-policy" component={PrivacyPolicy} onLeave={closeHeader} />
        <Route path="/feedback" component={Feedback} onLeave={closeHeader} />
    </Route>
    <Route path="*" component={NoMatch} onLeave={closeHeader} />
</Router>), document.getElementById('root'));
Isaac Pak
fuente
@BigDong No sé qué es closeHeader. Tendría que hacerle esa pregunta al OP porque el código de renderización es suyo. Solo estoy mostrando cómo implementaría react-ga para su código (busque mis // comentarios)
Isaac Pak
0

Basado en sugerencias de @ david-l-walsh y @bozdoz

He creado un HOC que ejecute el window.ga('set','page','{currentUrl})y window.ga('send', 'pageview');función y se usa fácilemte directamente en la página del router ...

este es el HOC:

import React from 'react';
import { history } from '../../store'; // or wherever you createBrowserHistory(); invokation is

function withGAHistoryTrack(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
    }

    componentDidMount() {
      const { location } = history;
      const page = location.pathname + location.search;

      if (typeof window.ga === 'function') {
        window.ga('set', 'page', page);
        window.ga('send', 'pageview');
      }
    }

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

export default withGAHistoryTrack;

y se usa de esta manera en la página del enrutador:

<Route
 path={'yourPath'}
 component={withGAHistoryTrack(yourComponent)}
 exact
/>
Yuri Scarbaci
fuente
0

Para actualizar dinámicamente la URL en algún evento (como onClick, etc.), se puede usar lo siguiente:

 //Imports
 import ReactGA from "react-ga";
 import { createBrowserHistory } from "history";

 // Add following on some event, like onClick (depends on your requirement)
 const history = createBrowserHistory();
 ReactGA.initialize("<Your-UA-ID-HERE>");
 ReactGA.pageview(history.location.pathname);
Santosh Pillai
fuente