Як налаштувати Google Analytics для React-Router?


86

Я намагаюся налаштувати Google Analytics на своєму сайті реагування і натрапив на кілька пакетів, але жоден з них не має такої настройки, яку я маю на прикладі. Сподівався, що хтось може пролити на це трохи світла.

Пакет, на який я розглядаю, - це реакція-га .

Мій метод візуалізації на моєму index.jsвиглядає так.

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
Опублікував відповідь для react-router-4/ react-router-domнижче, головна відповідь тут для попередніх версій React-Router і, на жаль, не працюватиме з v4.
Пітер Берг,

Як додати це за допомогою StaticRouter, оскільки я використовую SSR з реакцією?
Subhendu Kundu

Відповіді:


85

Зберігайте посилання на ваш об’єкт історії. тобто

import { createBrowserHistory } from 'history';

var history = createBrowserHistory();

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

Потім додайте слухача для запису кожного перегляду сторінки. (Це передбачає, що ви вже налаштували window.gaоб’єкт у звичний спосіб.)

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

16
Це не враховує події та інші типи звернень, які надсилаються. Вони все ще посилатимуться на URL-адресу під час завантаження сторінки. Натомість вам потрібно буде встановити нове значення на інструменті відстеження перед надсиланням перегляду сторінки, наприклад ga('set', 'page', location.pathname + location.search); ga('send', 'pageview');.
Філіп Уолтон,

1
Привіт, Девід, ти використовуєш приклад використання звичайного коду ga із сайту ga чи використовує пакет response-ga? Дякую.
John Fu

Ще не вирішив, як це виправити, але ця інформація також може бути корисною: stackoverflow.com/questions/30052693/… (вона пояснює, чому атрибуція може працювати некоректно в деяких випадках, а також вводить високі показники відмов ).
DeTeam

Ви не хочете третього параметра в команді send. "Хоча технічно команда send для звернень до перегляду сторінки приймає необов’язкове поле сторінки як третій параметр, передавати поле сторінки таким чином не рекомендується під час відстеження односторінкових додатків. Це пояснюється тим, що поля, передані за допомогою команди send, не встановлені на трекері— вони застосовуються лише до поточного звернення. Неоновлення трекера спричинить проблеми, якщо ваша програма надсилає будь-які звернення, не пов’язані з переглядом сторінки (наприклад, події чи соціальні взаємодії), оскільки ці звернення будуть пов’язані з будь-яким значенням сторінки, яку мав трекер під час його створення. "
Джошуа Робінсон,


30

Враховуючи, що Google Analytics завантажується та ініціалізується ідентифікатором відстеження.

Ось рішення для реакційного маршрутизатора версії 4, що використовує <Route>компонент для відстеження переглядів сторінки.

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

Ви просто візуалізуєте цей компонент всередині <Router>(але не як безпосередній дочірній елемент a <Switch>).

Що трапляється, що всякий раз, коли змінюється опис розташування, це викликає повторне відображення цього компонента (насправді нічого не відображаючи), що запускає перегляд сторінки.


1
React-router 4. Чи є щось, що він не може робити ?!
Ентоні Креган

1
Опублікував ще одне ще одне рішення-router-4-рішення, яке не передбачає зміни окремих маршрутів. На жаль, це точно ситуація типу "вибирай отруту".
Пітер Берг,

1
Чи не означає це, що перехід до "/" нічого не призведе?
Dana Woodman

3
Просто знайдіть інший маршрут, який випромінює все, що завгодно, @DanaWoodman. Це передбачає, що маршрут не вSwitch
bozdoz

Чи буде це відстежувати два перегляди сторінки на цільовій сторінці? Ми бачимо, як GA відстежує цільову сторінку автоматично, і ми запускаємо для неї додаткову подію перегляду сторінки. Або GA це фільтрує?
ArneHugo

27

Я використовую React Router v4 та Google Analytics глобальний тег сайту , який, здається, рекомендується під час написання цього.

І ось моє рішення:

Створіть компонент, загорнутий у withRouter з 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);

Просто додайте компонент у свій маршрутизатор (я вважаю, що в ідеалі після відповідних маршрутів та будь-яких компонентів комутатора, оскільки функція аналітики не повинна мати пріоритет над візуалізацією вашого сайту):

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

Як зазначено:

withRouter буде рендерити свій компонент щоразу, коли маршрут змінюється з тими ж реквізитами, що і рендеринг реквізиту

Отже, коли маршрут змінюється, GoogleAnalyticsкомпонент оновиться, він отримає нове розташування як реквізит і history.actionбуде або PUSHдля нового елемента історії, або POPдля сигналізації про перехід назад через історію (що, на мою думку, не повинно викликати перегляд сторінки, але ви можете налаштувати , якщо заяви в componentWillUpdateяк ви вважаєте за потрібне (ви можете навіть спробувати componentDidUpdateз this.propsзамість цього, але я не впевнений, що краще)).


bozdoz як Ви додали Глобальний тег сайту на свою сторінку. Ви щойно додали <script async src = " googletagmanager.com/gtag/js?id=GA_TRACKING_ID" > </… > на свою HTML-сторінку під тегом body?
me-me

1
@ me-me Так. Але всередині тегу body:<body> ... <script ...></script></body>
bozdoz

Для останнього React і React Router було потрібно кілька налаштувань. Змінити componentWillMountна componentDidMount. Змініть page_pathна this.props.location.pathname. Оберніть компоненти Switch і GoogleAnalytics в <div>
mjhm,

Не впевнений, де ви бачите componentWillMount, і не впевнений, чим page_pathвідрізняється, але я спробував би обернути компонент Switch і GA <React.Fragment>замість div. Дякую!
bozdoz

2
Привіт @JoshuaRobinson, я написав внизу, "... я думаю, не повинен викликати перегляд сторінки, але ти можеш налаштувати ...". Це питання стосувалось інтеграції Google Analytics з React Router, а не про те, які представлення даних слід реєструвати. Сказавши це, я можу налаштувати свій компонент, бачачи, як Google буде відстежувати його по-різному з їхнього боку. Дякую.
bozdoz

19

Зверніть увагу, якщо ви використовуєте react-router-domпакет від react-router-4вас, ви можете впоратися з цим так:

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

Зверніть увагу, що для цього потрібно встановити historyпакет ( npm install history). Це вже залежність від response-router-dom, тому ви не додаєте сюди жодної ваги сторінки.

Також зауважте: не можна використовувати компонент BrowserRouter І інструмент вашого відстеження ga таким чином. Це нормально, оскільки компонент BrowserRouter - це просто дуже тонка обгортка навколо об’єкта Router. Ми відтворюємо функціонал BrowserRouter тут, <Router history={history}>де і де const history = createBrowserHistory();.


ви ніколи не дзвоните в initGA?
Мухаммед Умер

@MuhammadUmer правда, щойно виправив
Пітер Берг,

Чому б вам просто не додати GA у ваш статичний HTML? Я вам поставив +1. Тому що я вважаю, що прослуховування об’єкта історії - це правильний шлях.
Вінс В.

@VinceV. Ви могли б ініціалізувати historyоб'єкт у вашій збірці, а потім зберігати історію на windowоб'єкті та отримувати доступ до нього у тезі сценарію у вашому, <head>але я думаю, що це врешті-решт зробить ваш конвеєр збірки більш складним. ¯_ (ツ) _ / ¯
Пітер Берг

Якщо ви використовуєте BrowserRouterкомпонент, див. Відповідь нижче, яка пропонує альтернативне рішення.
Тоше

14

Я б запропонував використовувати чудовий react-router-gaпакет, надзвичайно легкий і простий у налаштуванні, особливо при використанні BrowserRouterобгортки.

Імпортуйте компонент:

import Analytics from 'react-router-ga';

Потім просто додайте <Analytics>всередині вашого BrowserRouter:

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

Це видається надзвичайно простим рішенням, якщо користувач зацікавлений відстежувати лише перегляди сторінок. Дуже худий!
peyo

11

Мені подобається, як тут пропонує Марк Томас Мюллер :

У вашому index.js

import ReactGA from 'react-ga'

ReactGA.initialize('YourAnalyticsID')

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

Де знаходяться ваші маршрути:

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

Короткий, масштабований і простий :)


чому існує відстеження, один глобальний, один локальний?
Теліміст,

11

Оскільки react-router v5.1.0це можна вирішити набагато простіше за допомогою 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 (...);
};

Дивитися також:

Ось трохи розумніша версія:

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;

Я не впевнений, що це потрібно з останнім "gtag". Коли я переходжу, налагоджувач ga, здається, правильно записує подію 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"}і новий
приклад

6

Завжди дотримуйтесь рекомендацій бібліотеки

У документації React-GA вони додали компонент спільноти, рекомендований для використання з React Router: https://github.com/react-ga/react-ga/wiki/React-Router-v4-withTracker

Впровадження

import withTracker from './withTracker';

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

Код

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
якщо я використовую SSR (рендеринг на стороні сервера), GA не знає фактичного заголовка сторінки без оновлення сторінки.
Френсіс Родрігес

1
Ви можете змінити заголовок на монтуванні, використовуючи React
Paras

Дякуємо за публікацію!
Sailesh Kotha,

звідки береться store?
user_78361084

Звідки береться Providerі береться ConnectedRouter? Це неповна відповідь, тому її слід проголосувати проти
user_78361084

2

По-перше, у вашому index.js встановіть функцію onUpdate для виклику 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>
  );
}

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

яка версія маршрутизатора використовується тут?
Паван

це для реакційного маршрутизатора dom v2 або v3, а не v4
Hugo Gresse

2

ось найпростіший спосіб відстежити всі шляхи з деякими робочими шляхами:

npm i --save history react-ga

створити файл 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

а потім імпортуйте його туди, де встановлено ваш 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

Список літератури:

Густаво Гонсалес | medium.com

Історія | GitHub


2

Я пропоную використовувати бібліотеку аналітики Segment та слідувати посібнику швидкого запуску React для відстеження викликів сторінок за допомогою бібліотеки React -Router . Ви можете дозволити <Route />компоненту обробляти, коли сторінка відображається, і використовувати componentDidMountдля виклику pageвикликів. Наведений нижче приклад показує один із способів зробити це:

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

Я підтримую https://github.com/segmentio/analytics-react . За допомогою Segment ви зможете вмикати та вимикати різні пункти призначення, натискаючи перемикач, якщо вам цікаво спробувати кілька інструментів аналітики (ми підтримуємо понад 250+ напрямків) без необхідності писати будь-який додатковий код. 🙂


1

Якщо ви використовуєте хеш або історію браузера, ви можете зробити:

import trackingHit from 'tracking';

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

де ./tracking.es6

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

0

базова реалізація реагу-га з вашим 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 Я не знаю, що таке closeHeader. Вам доведеться поставити це питання оператору, оскільки код візуалізації є його. Я просто показую, як ви застосуєте response-ga для його коду (шукайте мої // коментарі)
Isaac Pak,

0

На основі пропозицій @ david-l-walsh та @bozdoz

Я створив HOC , які виконують window.ga('set','page','{currentUrl})і window.ga('send', 'pageview');функцію і Іс використовуються безпосередньо на сторінці маршрутизатора ...

це 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;

і використовується таким чином на сторінці маршрутизатора:

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

0

Для динамічного оновлення URL-адреси певної події (наприклад, onClick тощо) можна використовувати наступне:

 //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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.