Jak skonfigurować Google Analytics dla React-Router?


86

Próbuję skonfigurować Google Analytics w mojej witrynie React i natknąłem się na kilka pakietów, ale żaden z nich nie jest tak skonfigurowany, jak ja, jeśli chodzi o przykłady. Miał nadzieję, że ktoś może rzucić na to trochę światła.

Pakiet, na który patrzę, to: react-ga .

Moja metoda renderowania index.jswygląda tak.

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

4
Zamieszczona odpowiedź na react-router-4/ react-router-domponiżej, tutaj najlepsza odpowiedź dotyczy wcześniejszych wersji routera React i niestety nie będzie działać z wersją 4.
— Peter Berg,

Jak mogę to dodać za pomocą StaticRouter, gdy używam Reagowania SSR?
— Subhendu Kundu

Odpowiedzi:


85

Zachowaj odniesienie do obiektu historii. to znaczy

import { createBrowserHistory } from 'history';

var history = createBrowserHistory();

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

Następnie dodaj odbiornik, aby rejestrować każdą odsłonę. (Zakłada się, że obiekt został już skonfigurowany window.gaw zwykły sposób).

history.listen((location) => {
    window.ga('set', 'page', location.pathname + location.search);
    window.ga('send', 'pageview');
});

16
Nie będzie to uwzględniać wysyłanych zdarzeń ani innych typów trafień. Będą nadal odnosić się do adresu URL w czasie ładowania strony. Zamiast tego musisz ustawić nową wartość w module śledzącym przed wysłaniem odsłony strony, np ga('set', 'page', location.pathname + location.search); ga('send', 'pageview');.
— Philip Walton,

1
Cześć David, czy Twój przykład używa zwykłego kodu ga z witryny ga, czy też pakietu react-ga? Dzięki.
— John Fu

Nie zdecydowałem jeszcze, jak to naprawić, ale ta informacja może być również przydatna: stackoverflow.com/questions/30052693/ (wyjaśnia, dlaczego atrybucja może nie działać poprawnie w niektórych przypadkach, a także wprowadza wysokie współczynniki odrzuceń ).
— DeTeam

Nie chcesz trzeciego parametru w poleceniu wysyłania. „Chociaż z technicznego punktu widzenia polecenie wysyłania dla odwiedzin odsłony akceptuje opcjonalne pole strony jako trzeci parametr, przekazywanie pola strony w ten sposób nie jest zalecane w przypadku śledzenia aplikacji jednostronicowych. Dzieje się tak, ponieważ pola przekazane za pomocą polecenia wysyłania nie są ustawiane w module śledzącym. mają one zastosowanie tylko do aktualnego trafienia. Brak aktualizacji modułu śledzącego spowoduje problemy, jeśli Twoja aplikacja wyśle ​​jakiekolwiek działania niezwiązane z odsłoną (np. zdarzenia lub interakcje społecznościowe), ponieważ te trafienia będą powiązane z dowolną wartością strony, jaką posiadał moduł śledzący, gdy został utworzony. "
— Joshua Robinson,


30

Zakładając, że Google Analytics jest ładowane i inicjowane z identyfikatorem śledzenia.

Oto rozwiązanie dla React-router w wersji 4 wykorzystujące <Route>komponent do śledzenia wyświetleń strony.

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

Po prostu renderujesz ten komponent wewnątrz <Router>(ale nie jako bezpośrednie dziecko a <Switch>).

Dzieje się tak, że za każdym razem, gdy zmienia się właściwość lokalizacji, powoduje to ponowne renderowanie tego komponentu (a nie renderowanie niczego), który uruchamia odsłonę.


1
React-router 4. Czy jest coś, czego nie może zrobić ?!
— Anthony Cregan

1
Poniżej zamieściłem kolejne rozwiązanie react-router-4, które nie wymaga modyfikacji poszczególnych tras. Niestety jest to zdecydowanie sytuacja typu „wybierz swoją truciznę”.
— Peter Berg

1
Czy to nie znaczy, że przejście do „/” nic nie wyrenderuje?
— Dana Woodman

3
Po prostu wybierz inną trasę, która emituje wszystko, co chcesz @DanaWoodman. Zakłada się, że trasa nie jest wSwitch
— bozdoz

Czy spowoduje to śledzenie dwóch odsłon na stronie docelowej? Widząc, że GA automatycznie śledzi stronę docelową, wyzwalamy dla niej dodatkowe zdarzenie odsłony. A może GA to odfiltrowuje?
— ArneHugo

27

Używam React Router v4 i Google Analytics globalnego tagu witryny , który wydaje się być zalecany w chwili pisania tego.

A oto moje rozwiązanie:

Utwórz komponent opakowany w withRouter z 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);

Po prostu dodaj komponent do routera (uważam, że najlepiej po wszystkich trasach, które byłyby dopasowane, i dowolnych komponentach Switch, ponieważ funkcja analityczna nie powinna mieć pierwszeństwa przed renderowaniem witryny):

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

Jak wspomniano:

withRouter ponownie wyrenderuje swój komponent za każdym razem, gdy trasa zmieni się z tymi samymi właściwościami, co właściwości renderowania

Więc kiedy trasa się zmieni, GoogleAnalyticskomponent zostanie zaktualizowany, otrzyma nową lokalizację jako rekwizyty i history.actionbędzie albo PUSHdla nowego elementu historii, albo POPzasygnalizował cofnięcie się w historii (co myślę, że nie powinno wywołać wyświetlenia strony, ale można dostosować, jeśli oświadczenia componentWillUpdatezgodnie z potrzebami (można nawet spróbować componentDidUpdateze this.propszamiast, ale jestem pewien, co jest lepsze)).


bozdoz jak dodałeś globalny tag witryny do swojej strony. Czy właśnie dodałeś <script async src = " googletagmanager.com/gtag/js?id=GA_TRACKING_ID " > </… > do swojej strony html pod tagiem body?
— me-me

1
@ me-me Yes. Ale w tagu body:<body> ... <script ...></script></body>
— bozdoz

Potrzebnych było kilka poprawek dla najnowszego routera React i React. Zmień componentWillMountna componentDidMount. Zmień page_pathTO this.props.location.pathname. Owiń komponenty Switch i GoogleAnalytics w <div>
— mjhm

Nie jestem pewien, gdzie widzisz componentWillMount, i nie jestem pewien, jak się page_pathróżni, ale spróbuję owinąć komponent Switch i GA <React.Fragment>zamiast div. Dzięki!
— bozdoz

2
Hej @JoshuaRobinson, napisałem na dole: „... myślę, że nie powinienem uruchamiać wyświetlenia strony, ale możesz dostosować ...”. To pytanie dotyczyło integracji Google Analytics z React Router, a nie tego, które widoki należy rejestrować. Powiedziawszy to, mogę dostosować mój komponent, ponieważ Google będzie śledził go inaczej po ich końcu. Dzięki.
— bozdoz

19

Uwaga, jeśli korzystasz z react-router-dompakietu react-router-4, możesz sobie z tym poradzić w następujący sposób:

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

Zauważ, że wymaga to zainstalowania historypakietu ( npm install history). Jest to już zależność reakcja-router-dom, więc nie dodajesz tutaj żadnej wagi strony.

Uwaga: nie jest możliwe użycie komponentu BrowserRouter ORAZ instrumentu śledzenia ga w ten sposób. To jest w porządku, ponieważ komponent BrowserRouter jest po prostu bardzo cienką otoczką wokół obiektu Router. Odtworzyliśmy tutaj funkcjonalność BrowserRouter z <Router history={history}>miejscem, w którym const history = createBrowserHistory();.


nigdy nie dzwoniłeś do initGA?
— Muhammad Umer,

@MuhammadUmer prawda, właśnie to naprawiłem
— Peter Berg,

Dlaczego po prostu nie dodasz GA do statycznego kodu HTML? Dałem ci plus. Ponieważ uważam, że słuchanie obiektu historii jest właściwą drogą.
— Vince V.

@VinceV. Można sobie wyobrazić, że można zainicjować historyobiekt w swojej kompilacji, a następnie zapisać historię na windowobiekcie i uzyskać do niej dostęp w tagu skryptu w swoim, <head>ale myślę, że ostatecznie spowodowałoby to, że potok kompilacji byłby bardziej skomplikowany. ¯_ (ツ) _ / ¯
— Peter Berg

Jeśli używasz BrowserRouterkomponentu, zobacz odpowiedź poniżej, która oferuje alternatywne rozwiązanie.
— Toshe

14

Sugerowałbym użycie doskonałego react-router-gapakietu, który jest niezwykle lekki i łatwy w konfiguracji, szczególnie w przypadku korzystania z BrowserRouteropakowania.

Zaimportuj komponent:

import Analytics from 'react-router-ga';

Następnie po prostu dodaj <Analytics>w swoim BrowserRouter:

<BrowserRouter>
    <Analytics id="UA-ANALYTICS-1">
        <Switch>
            <Route path="/somewhere" component={SomeComponent}/>
        </Switch>
    </Analytics>
</BrowserRouter>

Wydaje się, że jest to bardzo proste rozwiązanie, jeśli użytkownik chce śledzić tylko wyświetlenia stron. Bardzo chudy!
— peyo

11

Podoba mi się to, co sugeruje tutaj Mark Thomas Müller :

W pliku index.js

import ReactGA from 'react-ga'

ReactGA.initialize('YourAnalyticsID')

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

Gdzie są twoje trasy:

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

Krótkie, skalowalne i proste :)


dlaczego jest śledzenie, jedno globalne, jedno lokalne?
— Thellimist

11

Ponieważ react-router v5.1.0można to rozwiązać o wiele łatwiej za pomocą 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 (...);
};

Zobacz też:

Oto nieco inteligentniejsza wersja:

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;

Nie jestem pewien, czy jest to konieczne w przypadku najnowszego „gtag”. Kiedy nawiguję, debugger ga wydaje się poprawnie rejestrować zdarzenie 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"}i nowy widok strony jest wyświetlany na pulpicie nawigacyjnym ga
— Dattaya,

6

Zawsze postępuj zgodnie z zaleceniami biblioteki

W dokumentacji React-GA dodali komponent społeczności zalecany do używania z React Router: https://github.com/react-ga/react-ga/wiki/React-Router-v4-withTracker

Realizacja

import withTracker from './withTracker';

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

Kod

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;

1
jeśli używam SSR (renderowanie po stronie serwera), GA nie zna rzeczywistego tytułu strony bez odświeżania strony.
— Francis Rodrigues,

1
Możesz zmienić tytuł na wierzchu za pomocą React
— Paras

Dzięki za wiadomość!
— Sailesh Kotha

skąd storepochodzi?
— user_78361084

Skąd pochodzi Provideri ConnectedRouterskąd? To jest niepełna odpowiedź i powinna zostać odrzucona
— user_78361084,

2

Najpierw w pliku index.js ustaw funkcję onUpdate, aby wywoł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>
  );
}

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

która wersja routera jest tutaj używana?
— Pavan

to jest dla routera reakcja dom v2 lub v3, a nie v4
— Hugo Gresse

2

oto najprostszy sposób śledzenia wszystkich ścieżek z pewnymi obejściami:

npm i --save history react-ga

utwórz plik 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

a następnie zaimportuj go do miejsca, w którym jest ustawiony plik 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

Bibliografia:

Gustavo Gonzalez | medium.com

Historia | GitHub


2

Proponuję skorzystać z biblioteki analitycznej segmentu i postępować zgodnie z przewodnikiem szybkiego startu React, aby śledzić wywołania stron za pomocą biblioteki React -router . Możesz zezwolić <Route />komponentowi na obsługę renderowania strony i używać go componentDidMountdo wywoływania pagepołączeń. Poniższy przykład pokazuje jeden sposób, w jaki możesz to zrobić:

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

Jestem opiekunem https://github.com/segmentio/analytics-react . Dzięki Segmentowi możesz włączać i wyłączać różne miejsca docelowe za pomocą przełącznika, jeśli chcesz wypróbować wiele narzędzi analitycznych (obsługujemy ponad 250 miejsc docelowych) bez konieczności pisania dodatkowego kodu. 🙂


1

Jeśli korzystasz z skrótu lub historii przeglądarki, możesz:

import trackingHit from 'tracking';

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

gdzie ./tracking.es6

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

0

podstawowa implementacja reakcji-ga z Twoim 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'));

@BigDong Nie wiem, co to jest closeHeader. Musiałbyś zadać OP to pytanie, ponieważ kod renderowania jest jego. Po prostu pokazuję, jak zaimplementowałbyś reakcję-ga dla jego kodu (poszukaj moich // komentarzy)
— Isaac Pak

0

Na podstawie sugestii @ david-l-walsh i @bozdoz

I stworzył hoc wykonać ten window.ga('set','page','{currentUrl})i window.ga('send', 'pageview');funkcję i jest w łatwy stosowany bezpośrednio na stronie routera ...

to jest 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;

i jest używany w ten sposób na stronie routera:

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

0

Aby dynamicznie aktualizować adres URL w niektórych zdarzeniach (takich jak onClick itp.), Można użyć:

 //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);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.