Как настроить Google Analytics для React-Router?

86

Я пытаюсь настроить Google Analytics на своем сайте реагирования и натолкнулся на несколько пакетов, но ни один из них не имеет такой настройки, как у меня с точки зрения примеров. Надеялся, что кто-нибудь сможет пролить свет на это.

Я смотрю на пакет response-ga .

Мой метод рендеринга 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ниже, главный ответ здесь предназначен для более ранних версий response-router и, к сожалению, не будет работать с v4.
Питер Берг
Как мне добавить это с помощью StaticRouter, если я использую React SSR?
Субхенду Кунду

Ответы:

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? Благодарю.
Джон Фу
Еще не решил, как это исправить, но эта информация также может быть полезна: stackoverflow.com/questions/30052693/… (она объясняет, почему в некоторых случаях атрибуция может работать некорректно, а также приводит к высоким показателям отказов ).
DeTeam
Вам не нужен третий параметр в команде отправки. "Хотя технически команда send для обращений pageview принимает необязательное поле страницы в качестве третьего параметра, передача поля страницы таким образом не рекомендуется при отслеживании одностраничных приложений. Это связано с тем, что поля, переданные через команду 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>(но не как прямой дочерний элемент<Switch> ).

Что происходит, так это то, что всякий раз, когда свойство местоположения изменяется, оно вызывает повторный рендеринг этого компонента (фактически ничего не рендеринг), который запускает просмотр страницы.

эйхьюго
источник
1
React-router 4. Есть что-нибудь, чего он не может сделать ?!
Энтони Креган
1
Ниже опубликовано еще одно решение response-router-4, которое не требует изменения отдельных маршрутов. К сожалению, это определенно ситуация типа «выбери свой яд».
Питер Берг
1
Разве это не значит, что переход к "/" ничего не отрендерит?
Дана Вудман
3
Просто имейте другой маршрут, который испускает все, что вы хотите, @DanaWoodman. Предполагается, что маршрут не по маршрутуSwitch
bozdoz
Будет ли отслеживаться два просмотра целевой страницы? Видя, как GA автоматически отслеживает целевую страницу, и мы запускаем для нее дополнительное событие pageview. Или GA это отфильтровывает?
ArneHugo
27

Я использую React Router v4 и тег Google Analytics Global Site Tag , который я рекомендую на момент написания этой статьи.

И вот мое решение:

Создайте компонент, завернутый в 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);

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

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?
я-я
1
@ me-me Да. Но внутри тега тела:<body> ... <script ...></script></body>
bozdoz 01
Для последних версий React и React Router потребовалось несколько доработок. Измените componentWillMountна componentDidMount. Изменение page_pathTo this.props.location.pathname. Оберните компоненты Switch и GoogleAnalytics в <div>
mjhm
Не уверен, где вы видите componentWillMount, и не уверен, чем page_pathотличается, но я бы попытался обернуть Switch и компонент GA <React.Fragment>вместо файла div. Благодаря!
bozdoz 04
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}>where const history = createBrowserHistory();.

Питер Берг
источник
вы никогда не вызываете initGA?
Мухаммад Умер
@MuhammadUmer правда, только что исправил
Питер Берг
Почему бы вам просто не добавить GA в свой статический HTML? Я плюс тебе 1. Потому что я думаю, что слушать объект истории - правильный путь.
Винс В.
@VinceV. Вы могли бы инициализировать historyобъект в своей сборке, а затем сохранить историю windowобъекта и получить к нему доступ в теге скрипта в вашем, <head>но я думаю, что в конечном итоге это усложнит конвейер сборки. ¯_ (ツ) _ / ¯
Питер Берг
Если вы используете BrowserRouterкомпонент, см. Ответ ниже, в котором предлагается альтернативное решение.
Toshe
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>
        )
    }
}

Коротко, масштабируемо и просто :)

Jöcker
источник
почему существует отслеживание, одно глобальное, одно локальное?
Thellimist
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"}и на панели инструментов ga отображается новое представление страницы
Dattaya
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
Спасибо за публикацию!
Сайлеш Кота
откуда 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

Я предлагаю использовать библиотеку аналитики сегмента и следовать руководству по быстрому запуску React, чтобы отслеживать вызовы страниц с помощью библиотеки response-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

базовая реализация response-ga с вашим 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 для его кода (ищите мои // комментарии)
Исаак Пак
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);
Сантош Пиллаи
источник