如何为 React-Router 设置 Google Analytics?
Posted
技术标签:
【中文标题】如何为 React-Router 设置 Google Analytics?【英文标题】:How to set up Google Analytics for React-Router? 【发布时间】:2016-04-22 13:09:18 【问题描述】:我正在尝试在我的 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'));
【问题讨论】:
在下面发布了react-router-4
/react-router-dom
的答案,这里的最佳答案是针对早期版本的 react-router,不幸的是,它不适用于 v4。
当我使用 React s-s-r 时,如何使用 StaticRouter 添加它?
【参考方案1】:
保留对历史对象的引用。即
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');
);
【讨论】:
这不会考虑发送的事件或其他命中类型。他们仍然会在页面加载时引用 URL。相反,您需要在发送综合浏览量之前在跟踪器上设置新值,例如ga('set', 'page', location.pathname + location.search); ga('send', 'pageview');
.
嗨,David,您的示例是使用来自 ga 站点的常规 ga 代码还是使用 react-ga 包?谢谢。
尚未决定如何修复它,但这条信息也可能有用:***.com/questions/30052693/…(它解释了为什么归因在某些情况下可能无法正常工作,并且还会引入高反弹率-费率)。
您不希望发送命令中的第三个参数。 “虽然从技术上讲,页面浏览命中的发送命令接受可选页面字段作为第三个参数,但在跟踪单页应用程序时不建议以这种方式传递页面字段。这是因为通过发送命令传递的字段未在跟踪器上设置 -它们仅适用于当前点击。如果您的应用程序发送任何非综合浏览点击(例如事件或社交互动),则不更新跟踪器将导致问题,因为这些点击将与跟踪器在创建时所具有的任何页面值相关联。 "
developers.google.com/analytics/devguides/collection/…【参考方案2】:
由于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 (...);
;
另见:
https://reactrouter.com/web/api/Hooks/uselocation https://github.com/react-ga/react-ga/issues/122这是一个更智能的版本:
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 调试器似乎正确记录了推送事件: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 仪表板中显示了一个新的页面视图
我找到的最好最优雅的解决方案,谢谢。只是考虑一下,要在 App.js 中调用 useLocation,您必须像这样在 index.js 中添加 鉴于谷歌分析已加载并使用跟踪 ID 进行初始化。
这里是 react-router 版本 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>
的直接子代)。
发生的情况是,每当 location 属性发生变化时,它都会重新渲染该组件(实际上并不渲染任何内容),从而触发网页浏览。
【讨论】:
React-router 4. 有什么不能做的吗?! 在下面发布了另一个不涉及修改单个路由的 react-router-4 解决方案。可悲的是,这绝对是一种“选择你的毒药”类型的情况。 这不是说去“/”不会渲染吗? 只有另一条路线可以发出你想要的任何东西@DanaWoodman。这假设路线不在Switch
这个人应该获得诺贝尔奖,我们已经尝试了各种方式,但这是唯一一个没有缺点的人。谢谢!【参考方案4】:
我正在使用 React Router v4 和 Google Analytics Global Site Tag,在撰写本文时似乎是推荐的。
这是我的解决方案:
从react-router-dom
创建一个包裹在withRouter 中的组件:
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
中的 if 语句(您甚至可以尝试使用 componentDidUpdate
和 this.props
代替,但我不确定哪个是更好))。
【讨论】:
bozdoz 您是如何将全局站点标签添加到您的页面的。您是否刚刚将 @me-me 是的。但在正文标签内:<body> ... <script ...></script></body>
最新的 React 和 React Router 需要进行一些调整。将componentWillMount
更改为componentDidMount
。将page_path
更改为this.props.location.pathname
。将 Switch 和 GoogleAnalytics 组件包装在 中
不确定您在哪里看到 componentWillMount
,也不确定 page_path
有何不同,但我会尝试将 Switch 和 GA 组件包装在 <React.Fragment>
中,而不是 div
。谢谢!
嘿@JoshuaRobinson,我在底部写道,“......我认为不应该触发页面视图,但你可以调整......”。这个问题是关于将 Google Analytics 与 React Router 集成,而不是关于应该记录哪些视图。话虽如此,我可能会调整我的组件,因为 Google 会以不同的方式跟踪它。谢谢。【参考方案5】:
请注意,如果您使用来自 react-router-4
的 react-router-dom
包,您可以这样处理:
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 component 只是路由器对象的一个非常薄的包装器。我们在这里使用<Router history=history>
重新创建 BrowserRouter 功能,其中const history = createBrowserHistory();
。
【讨论】:
你从不调用initGA? @MuhammadUmer 是的,刚刚修好了 为什么不在静态 HTML 中添加 GA?我加了你。因为我认为听历史对象是正确的方法。 @VinceV。您可以想象在您的构建中初始化history
对象,然后将历史记录存储在window
对象上并在您的<head>
的脚本标签中访问它,但我认为这最终会使您的构建管道更加复杂。 ¯_(ツ)_/¯
如果您使用的是 BrowserRouter
组件,请参阅下面提供替代解决方案的答案。【参考方案6】:
我建议使用出色的 react-router-ga
包,它非常轻巧且易于配置,尤其是在使用 BrowserRouter
包装器时。
导入组件:
import Analytics from 'react-router-ga';
然后只需在您的BrowserRouter
中添加<Analytics>
:
<BrowserRouter>
<Analytics id="UA-ANALYTICS-1">
<Switch>
<Route path="/somewhere" component=SomeComponent/>
</Switch>
</Analytics>
</BrowserRouter>
【讨论】:
如果用户只想跟踪页面浏览量,这似乎是一个超级简单的解决方案。很瘦!【参考方案7】:我喜欢 Mark Thomas Müller 的建议 here:
在你的 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>
)
简短、可扩展且简单:)
【讨论】:
为什么会有跟踪,一个全局,一个本地?【参考方案8】:始终遵循图书馆推荐的方式
在 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;
【讨论】:
如果我使用 s-s-r(服务器端渲染),GA 不刷新页面不知道实际页面的标题。 您可以使用 React 更改挂载时的标题 感谢发帖!store
来自哪里?
Provider
和 ConnectedRouter
来自哪里?这是一个不完整的答案,应该被否决【参考方案9】:
这是一种通过一些变通方法跟踪所有路径的最简单方法:
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
参考资料:
Gustavo Gonzalez | medium.com
History | GitHub
【讨论】:
【参考方案10】:首先,在你的 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【参考方案11】:我建议使用 Segment 分析库并按照 React quickstart guide 使用 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 的维护者。如果您有兴趣尝试多种分析工具(我们支持超过 250 多个目的地),而无需编写任何额外代码,您可以通过 Segment 来打开和关闭不同的目的地。 ?
【讨论】:
此库已被弃用【参考方案12】:如果您使用哈希或浏览器历史记录,您可以这样做:
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
【讨论】:
【参考方案13】:用你的 index.js 实现基本的 react-ga
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 是什么。你必须问 OP 这个问题,因为渲染代码是他的。我只是在展示如何为他的代码实现 react-ga(查找我的 // cmets)【参考方案14】:基于@david-l-walsh 和@bozdoz 的建议
我创建了一个执行 window.ga('set','page','currentUrl)
和 window.ga('send', 'pageview');
函数的 HOC,并且可以直接在路由器页面中轻松使用...
这是 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
/>
【讨论】:
【参考方案15】:对于某些事件(如 onClick 等)动态更新 url,可以使用以下方法:
//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);
【讨论】:
以上是关于如何为 React-Router 设置 Google Analytics?的主要内容,如果未能解决你的问题,请参考以下文章
如何为项目使用不同版本的 google-play-services 库
在 Typescript 项目中实现 react-router PrivateRoute