Wie richte ich Google Analytics für React-Router ein?

82

Ich versuche, Google Analytics auf meiner Reaktionsseite einzurichten, und bin auf einige Pakete gestoßen, von denen jedoch keines die Art von Einrichtung hat, die ich anhand von Beispielen habe. Ich hatte gehofft, jemand könnte etwas Licht ins Dunkel bringen.

Das Paket, das ich mir ansehe, ist, reag-ga .

Meine Rendermethode auf meinem index.jssieht so aus.

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
quelle
4
Gepostet eine Antwort für react-router-4/ react-router-domunten, Top-Antwort hier ist für frühere Versionen von React-Router und funktioniert leider nicht mit v4.
Peter Berg
Wie füge ich dies mit StaticRouter hinzu, wenn ich React SSR verwende?
Subhendu Kundu

Antworten:

83

Behalten Sie einen Verweis auf Ihr Verlaufsobjekt. dh

import { createBrowserHistory } from 'history';

var history = createBrowserHistory();

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

Fügen Sie dann einen Listener hinzu, um jeden Seitenaufruf aufzuzeichnen. (Dies setzt voraus, dass Sie das window.gaObjekt bereits auf die übliche Weise eingerichtet haben.)

history.listen((location) => {
    window.ga('set', 'page', location.pathname + location.search);
    window.ga('send', 'pageview');
});
David L. Walsh
quelle
16
Dies berücksichtigt keine Ereignisse oder andere Trefferarten, die gesendet werden. Sie verweisen beim Laden der Seite weiterhin auf die URL. Stattdessen müssen Sie den neuen Wert im Tracker festlegen, bevor Sie den Seitenaufruf senden, z ga('set', 'page', location.pathname + location.search); ga('send', 'pageview');.
Philip Walton
1
Hallo David, verwendet Ihr Beispiel den regulären Ga-Code von der Ga-Site oder das React-Ga-Paket? Vielen Dank.
John Fu
Ich habe noch nicht entschieden, wie ich das Problem beheben soll, aber diese Information könnte auch nützlich sein: stackoverflow.com/questions/30052693/… (es erklärt, warum die Zuordnung in einigen Fällen möglicherweise nicht richtig funktioniert und führt auch zu hohen Absprungraten ).
DeTeam
Sie möchten keinen dritten Parameter für den Sendebefehl. "Während der Sendebefehl für Seitenzugriffstreffer technisch gesehen ein optionales Seitenfeld als dritten Parameter akzeptiert, wird das Übergeben des Seitenfelds auf diese Weise beim Verfolgen von Anwendungen für einzelne Seiten nicht empfohlen. Dies liegt daran, dass Felder, die über den Sendebefehl übergeben werden, nicht auf dem Tracker festgelegt sind. Sie gelten nur für den aktuellen Treffer. Wenn der Tracker nicht aktualisiert wird, treten Probleme auf, wenn Ihre Anwendung Treffer ohne Seitenaufruf sendet (z. B. Ereignisse oder soziale Interaktionen), da diese Treffer mit dem Seitenwert verknüpft sind, den der Tracker beim Erstellen hatte. ""
Joshua Robinson
29

Vorausgesetzt, Google Analytics wird geladen und mit einer Tracking-ID initialisiert.

Hier ist eine Lösung für React-Router Version 4, bei der die <Route>Komponente zum Verfolgen von Seitenaufrufen verwendet wird.

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

Sie rendern diese Komponente einfach innerhalb von <Router>(aber nicht als direktes untergeordnetes Element von a<Switch> ).

Was passiert, ist, dass jedes Mal, wenn sich die Standort-Requisite ändert, diese Komponente erneut gerendert wird (ohne etwas zu rendern), wodurch ein Seitenaufruf ausgelöst wird.

Heyhugo
quelle
1
React-Router 4. Gibt es etwas, was es nicht kann?!
Anthony Cregan
1
Weiter unten wurde eine weitere React-Router-4-Lösung veröffentlicht, bei der einzelne Routen nicht geändert werden müssen. Leider ist dies definitiv eine Situation vom Typ "Wähle dein Gift".
Peter Berg
1
Bedeutet das nicht, dass das Aufrufen von "/" nichts rendert?
Dana Woodman
3
Haben Sie einfach eine andere Route, die alles ausstrahlt, was Sie wollen @DanaWoodman. Dies setzt voraus, dass die Route nicht in aSwitch
bozdoz
Verfolgt dies zwei Seitenaufrufe auf der Zielseite? Da GA die Zielseite automatisch verfolgt, wird ein zusätzliches Seitenaufrufereignis ausgelöst. Oder filtert GA es heraus?
ArneHugo
26

Ich verwende React Router v4 und das Google Analytics Global Site Tag , das zum Zeitpunkt des Schreibens empfohlen zu sein scheint.

Und hier ist meine Lösung:

Erstellen Sie eine in withRouter eingeschlossene Komponente aus 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);

Fügen Sie einfach die Komponente in Ihrem Router hinzu (ich glaube, idealerweise nach übereinstimmenden Routen und Switch-Komponenten, da die Analysefunktion keine Priorität vor dem Rendern Ihrer Site haben sollte):

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

Wie erwähnt:

withRouter rendert seine Komponente jedes Mal neu, wenn sich die Route mit denselben Requisiten wie Render-Requisiten ändert

Wenn sich die Route ändert, wird die GoogleAnalyticsKomponente aktualisiert, erhält den neuen Speicherort als Requisiten und history.actionist entweder PUSHfür ein neues Verlaufselement oder POPals Signal dafür, dass der Verlauf rückwärts durchlaufen wird (was meiner Meinung nach keine Seitenansicht auslösen sollte, aber Sie können die if - Anweisungen in einstellen , componentWillUpdatewie Sie sehen , passen (Sie sogar versuchen könnte , componentDidUpdatemit this.propsstatt, aber ich bin nicht sicher , was besser ist)).

bozdoz
quelle
bozdoz wie haben Sie Global Site Tag zu Ihrer Seite hinzugefügt? Haben Sie gerade <script async src = " googletagmanager.com/gtag/js?id=GA_TRACKING_ID " > </ > zu Ihrer HTML-Seite unter dem Body-Tag hinzugefügt ?
Ich-Ich
1
@ me-me Ja. Aber innerhalb des Body-Tags:<body> ... <script ...></script></body>
Bozdoz
Für den neuesten React und React Router waren einige Verbesserungen erforderlich. Wechseln Sie componentWillMountzu componentDidMount. Ändern Sie das page_pathin this.props.location.pathname. Wickeln Sie die Switch- und GoogleAnalytics-Komponenten in einen <div>
mjhm
Ich bin mir nicht sicher, wo Sie es sehen componentWillMountund nicht sicher, wie page_pathunterschiedlich es ist, aber ich würde versuchen, Switch- und GA-Komponenten <React.Fragment>anstelle von a einzuschließen div. Vielen Dank!
Bozdoz
2
Hey @JoshuaRobinson, ich schrieb unten: "... Ich denke, ich sollte keine Seitenansicht auslösen, aber Sie können anpassen ...". Bei dieser Frage ging es um die Integration von Google Analytics in React Router und nicht darum, welche Ansichten Sie protokollieren sollten. Trotzdem kann ich meine Komponente anpassen, da Google sie am Ende anders nachverfolgen wird. Vielen Dank.
Bozdoz
19

Hinweis: Wenn Sie das react-router-domPaket von verwenden react-router-4, können Sie dies folgendermaßen behandeln:

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

Beachten Sie, dass Sie dazu das historyPaket installieren müssen (npm install history ) . Dies ist bereits eine Abhängigkeit von React-Router-Dom, sodass Sie hier keine Seitengewichtung hinzufügen.

Beachten Sie auch: Es ist nicht möglich, die BrowserRouter-Komponente zu verwenden UND Ihr Ga-Tracking auf diese Weise zu instrumentieren. Dies ist in Ordnung, da die BrowserRouter-Komponente nur ein sehr dünner Wrapper um das Router-Objekt ist. Wir erstellen die BrowserRouter-Funktionalität hier mit <Router history={history}>where neu const history = createBrowserHistory();.

Peter Berg
quelle
Sie rufen nie initGA an?
Muhammad Umer
@ MuhammadUmer wahr, gerade behoben
Peter Berg
Warum fügen Sie die GA nicht einfach in Ihr statisches HTML ein? Ich plus ich habe dich. Weil ich denke, dass das Abhören des Verlaufsobjekts der richtige Weg ist.
Vince V.
@VinceV. Es ist denkbar, dass Sie das historyObjekt in Ihrem Build initialisieren und dann den Verlauf auf dem windowObjekt speichern und in einem Skript-Tag in Ihrem darauf zugreifen, <head>aber ich denke, dies würde Ihre Build-Pipeline letztendlich komplizierter machen. ¯_ (ツ) _ / ¯
Peter Berg
Wenn Sie die BrowserRouterKomponente verwenden, finden Sie in der folgenden Antwort eine alternative Lösung.
Toshe
15

Ich würde vorschlagen, das hervorragende react-router-gaPaket zu verwenden, das extrem leicht und einfach zu konfigurieren ist, insbesondere wenn Sie das verwendenBrowserRouter Wrappers.

Importieren Sie die Komponente:

import Analytics from 'react-router-ga';

Dann fügen <Analytics>Sie einfach das in Ihrem BrowserRouter:

<BrowserRouter>
    <Analytics id="UA-ANALYTICS-1">
        <Switch>
            <Route path="/somewhere" component={SomeComponent}/>
        </Switch>
    </Analytics>
</BrowserRouter>
Zu ihr
quelle
Dies scheint eine supereinfache Lösung zu sein, wenn der Benutzer nur Seitenaufrufe verfolgen möchte. Sehr schlank!
Peyo
11

Mir gefällt, wie Mark Thomas Müller hier vorschlägt :

In Ihrer index.js

import ReactGA from 'react-ga'

ReactGA.initialize('YourAnalyticsID')

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

Wo Ihre Routen sind:

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

Kurz, skalierbar und einfach :)

Jöcker
quelle
Warum gibt es Tracking, ein globales, ein lokales?
Thellimist
10

Da react-router v5.1.0kann dies mit viel einfacher gelöst werden 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 (...);
};

Siehe auch:

Hier ist eine etwas intelligentere Version:

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;
Das ist mein Design
quelle
Ich bin mir nicht sicher, ob es mit dem neuesten 'gtag' notwendig ist. Wenn ich navigiere, scheint 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"}ga
debugger
6

Befolgen Sie immer den von der Bibliothek empfohlenen Weg

In der React-GA-Dokumentation wurde eine Community-Komponente hinzugefügt, die für die Verwendung mit React Router empfohlen wird: https://github.com/react-ga/react-ga/wiki/React-Router-v4-withTracker

Implementierung

import withTracker from './withTracker';

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

Code

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
quelle
1
Wenn ich SSR (serverseitiges Rendering) verwende, kennt der GA den Titel der tatsächlichen Seite nicht, ohne die Seite zu aktualisieren.
Francis Rodrigues
1
Sie können den Titel auf dem Mount mit React
Paras
Danke fürs Schreiben!
Sailesh Kotha
woher storekommen aus?
user_78361084
Woher kommt Providerund ConnectedRouterkommt? Dies ist eine unvollständige Antwort und sollte herabgestuft werden
user_78361084
2

Stellen Sie zunächst in Ihrer index.js die Funktion onUpdate so ein, dass ga aufgerufen wird

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

Und 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
quelle
Welche Router-Version wird hier verwendet?
Pavan
Es ist für React Router Dom v2 oder v3, nicht v4
Hugo Gresse
2

Hier ist die einfachste Möglichkeit, alle Pfade mit einigen Umgehungsmöglichkeiten zu verfolgen:

npm i --save history react-ga

Erstellen Sie eine Datei 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

und importieren Sie es dann dorthin, wo es eingestellt ist 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

Verweise:

Gustavo Gonzalez | medium.com

Geschichte | GitHub

fsilva
quelle
2

Ich schlage vor, die Segmentanalysebibliothek zu verwenden und der React-Kurzanleitung zu folgen , um Seitenaufrufe mithilfe der React -Router- Bibliothek zu verfolgen . Sie können die erlauben <Route />Komponente zu handhaben, wenn die Seite und die Nutzung macht componentDidMountaufzurufen pageAnrufe. Das folgende Beispiel zeigt eine Möglichkeit, wie Sie dies tun können:

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

Ich bin der Betreuer von https://github.com/segmentio/analytics-react . Mit Segment können Sie verschiedene Ziele durch Umlegen eines Schalters ein- und ausschalten, wenn Sie mehrere Analysetools ausprobieren möchten (wir unterstützen über 250 Ziele), ohne zusätzlichen Code schreiben zu müssen. 🙂

Wilhelm
quelle
1

Wenn Sie einen Hash- oder Browserverlauf verwenden, können Sie Folgendes tun:

import trackingHit from 'tracking';

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

wo ./tracking.es6

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

Grundlegende React-Ga-Implementierung mit Ihrer 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
quelle
@ BigDong Ich weiß nicht, was closeHeader ist. Sie müssten dem OP diese Frage stellen, da der Rendercode sein ist. Ich zeige nur, wie Sie React-Ga für seinen Code implementieren würden (siehe meine // Kommentare)
Isaac Pak
0

Basierend auf den Vorschlägen von @ david-l-walsh und @bozdoz

Ich habe eine HOC, der das Ausführen window.ga('set','page','{currentUrl})und window.ga('send', 'pageview');Funktion und ist easly direkt im Router - Seite verwendet ...

das ist das 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;

und wird auf der Routerseite folgendermaßen verwendet:

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

Zum dynamischen Aktualisieren der URL bei einem Ereignis (wie onClick usw.) kann Folgendes verwendet werden:

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