如何为 React-Router 设置 Google Analytics?

IT技术 google-analytics reactjs react-router
2021-04-03 22:51:15

我正在尝试在我的 React 站点上设置 Google Analytics,并且遇到了一些软件包,但没有一个具有我在示例方面的设置。希望有人能对此有所了解。

我正在查看的包是react-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'));
6个回答

保留对历史对象的引用。IE

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');
});
还没有决定如何修复它,但这条信息可能也很有用:stackoverflow.com/questions/30052693/...(它解释了为什么归因在某些情况下可能无法正常工作并且还会引入高跳出率)。
2021-05-27 22:51:15
嗨大卫,你的例子是使用来自 ga 站点的常规 ga 代码还是使用 react-ga 包?谢谢。
2021-06-05 22:51:15
您不希望在发送命令中使用第三个参数。“虽然从技术上讲,页面浏览点击率的发送命令接受一个可选的页面字段作为第三个参数,但在跟踪单页应用程序时不建议以这种方式传递页面字段。这是因为通过发送命令传递的字段未在跟踪器上设置——它们仅适用于当前点击。如果您的应用程序发送任何非浏览量点击(例如事件或社交互动),不更新跟踪器将导致问题,因为这些点击将与跟踪器在创建时拥有的任何页面值相关联。 ”
2021-06-12 22:51:15
这不会考虑发送的事件或其他命中类型。他们仍然会在页面加载时引用 URL。相反,您需要在发送浏览量之前在跟踪器上设置新值,例如ga('set', 'page', location.pathname + location.search); ga('send', 'pageview');
2021-06-13 22:51:15

鉴于 google 分析已加载并使用跟踪 ID 进行初始化。

这是使用<Route>组件跟踪页面浏览量的react-router 版本 4 的解决方案

<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>)内渲染此组件

发生的情况是,每当 location 属性更改时,它都会导致重新渲染该组件(实际上不渲染任何内容),从而触发页面浏览。

在下面发布了另一个不涉及修改单个路由的 react-router-4 解决方案。可悲的是,这绝对是一种“选择你的毒药”类型的情况。
2021-05-27 22:51:15
React-router 4. 有什么不能做的吗?!
2021-06-03 22:51:15
这是否意味着转到“/”不会渲染任何内容?
2021-06-05 22:51:15
只需有另一条路线可以发出您想要的任何东西@DanaWoodman。这假设路线不在Switch
2021-06-10 22:51:15
这个人配得上诺贝尔奖,我们尝试了各种方法,但只有他一个人工作没有缺点。谢谢!
2021-06-17 22:51:15

由于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;
我找到的最好和优雅的解决方案,谢谢。考虑一下,要在 App.js 中调用 useLocation,您必须像这样在 index.js 中添加 <Router>: <Router><App /></Router> 在顶部导入路由器,使用 import { BrowserRouter as Router } from '反应路由器dom';
2021-05-27 22:51:15
我不确定最新的“gtag”是否有必要。当我导航时,ga 调试器似乎正确记录了推送事件: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 仪表板中显示了一个新的页面视图
2021-06-21 22:51:15

我正在使用 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 都会使用与渲染props相同的props重新渲染其组件

因此,当路线更改时,GoogleAnalytics组件将更新,它将接收新位置作为props,并且history.actionPUSH用于新的历史项目或POP通过历史向后发送信号(我认为这不应该触发页面视图,但是您可以根据需要调整 if 语句componentWillUpdate(您甚至可以尝试componentDidUpdate使用this.props,但我不确定哪个更好))。

最新的 React 和 React Router 需要进行一些调整。更改componentWillMountcomponentDidMount将 更改page_paththis.props.location.pathname将 Switch 和 GoogleAnalytics 组件包装在 <div> 中
2021-05-23 22:51:15
嘿@JoshuaRobinson,我在底部写道,“......我认为不应该触发页面浏览,但你可以调整......”。这个问题是关于将 Google Analytics 与 React Router 集成,而不是关于您应该记录哪些视图。话虽如此,我可能会调整我的组件,因为 Google 最终会对其进行不同的跟踪。谢谢。
2021-05-25 22:51:15
不确定您在哪里看到componentWillMount,也不确定有什么page_path不同,但我会尝试将 Switch 和 GA 组件包装在<React.Fragment>而不是div. 谢谢!
2021-05-27 22:51:15
@me-me 是的。但在 body 标签内:<body> ... <script ...></script></body>
2021-06-07 22:51:15
bozdoz 您是如何将全局站点标签添加到您的页面的。您是否刚刚将 <script async src=" googletagmanager.com/gtag/js?id=GA_TRACKING_ID" > </… > 添加到您的 html 页面的 body 标记下方?
2021-06-13 22:51:15

请注意,如果您使用的是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)。这已经是 react-router-dom 的依赖项,因此您不会在此处添加任何页面权重。

另请注意:不可能使用 BrowserRouter 组件并以这种方式检测您的 ga 跟踪。这是可以的,因为BrowserRouter 组件只是 Router 对象周围的一个非常薄的包装器。我们在这里使用<Router history={history}>where重新创建 BrowserRouter 功能const history = createBrowserHistory();

@MuhammadUmer 是的,只是修复了它
2021-05-24 22:51:15
你从不打电话给initGA?
2021-05-31 22:51:15
为什么不直接在静态 HTML 中添加 GA?我加1你。因为我认为听历史对象是正确的方法。
2021-06-03 22:51:15
如果您正在使用该BrowserRouter组件,请参阅下面提供替代解决方案的答案。
2021-06-04 22:51:15
@文斯。可以想象,您可以history在构建中初始化对象,然后在window对象上存储历史记录并在您的脚本标记中访问它,<head>但我认为这最终会使您的构建管道变得更加复杂。¯_(ツ)_/¯
2021-06-15 22:51:15