I have built a new site using Angular 2 as the front-end. As everything is done via push state, there are no page loads which typically trigger the Google Analytics code to send a page view to Google's servers.
我使用Angular 2作为前端构建了一个新站点。由于一切都是通过推送状态完成的,因此没有页面加载通常会触发Google Analytics代码将页面视图发送到Google的服务器。
How can I manually send page view events to Google so that I can track what users of my site are viewing?
如何手动将网页浏览事件发送给Google,以便我可以跟踪我网站的哪些用户正在查看?
3 个解决方案
#1
50
I managed to get this working by subscribing to changes on the router, checking that the route had actually changed (I was getting multiple events on some routes at times) and then sending the new path to Google.
我设法通过订阅路由器上的更改,检查路由实际已经改变(我有时在某些路由上获得多个事件)然后将新路径发送给Google来实现此功能。
app.component.ts
app.component.ts
import { ... } from '...';
// Declare ga function as ambient
declare var ga:Function;
@Component({ ... })
export class AppComponent {
private currentRoute:string;
constructor(_router:Router) {
// Using Rx's built in `distinctUntilChanged ` feature to handle url change c/o @dloomb's answer
router.events.distinctUntilChanged((previous: any, current: any) => {
// Subscribe to any `NavigationEnd` events where the url has changed
if(current instanceof NavigationEnd) {
return previous.url === current.url;
}
return true;
}).subscribe((x: any) => {
ga('set', 'page', x.url);
ga('send', 'pageview')
});
}
}
}
You also need to include the google analytics code in your main index file before loading your angular2 app so that the global ga
object exists, but you don't want to send the initial view twice. In order to do this, remove the following line from the GA script
您还需要在加载angular2应用程序之前在主索引文件中包含Google Analytics代码,以便全局ga对象存在,但您不希望将初始视图发送两次。为此,请从GA脚本中删除以下行
index.html
的index.html
<script>
(function(i,s,o,g,r,a,m){...})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-X', 'auto');
// Remove this line to avoid sending the first page view twice.
//ga('send', 'pageview');
</script>
<!--
Load your ng2 app after ga.
This style of deferred script loading doesn't guarantee this will happen
but you can use Promise's or what works for your particular project.
-->
<script defer type="text/javascript" src="/app.js"></script>
Using a third party library
使用第三方库
As an alternative to implementing GA yourself, the library Angulartics2 is also a popular tool for implementing GA tracking and also integrates with other analytics vendors as well.
作为自己实施GA的替代方案,Angulartics2库也是实现GA跟踪的流行工具,也可以与其他分析供应商集成。
#2
33
Expanding on Ian's answer. You can use Rx's built in features to handle the distinction between current and new routes.
扩展伊恩的答案。您可以使用Rx的内置功能来处理当前路由和新路由之间的区别。
import { NavigationEnd, Router } from '@angular/router';
declare var ga: any;
export class AppComponent {
constructor(public router: Router) {
router.events.distinctUntilChanged((previous: any, current: any) => {
if(current instanceof NavigationEnd) {
return previous.url === current.url;
}
return true;
}).subscribe((x: any) => {
console.log('router.change', x);
ga('send', 'pageview', x.url);
});
}
}
We are using the distinctUntilChanged operator to make the observer only emit items that are of type NavigationEnd and do not have the same route as the previously emitted item.
我们使用distinctUntilChanged运算符使观察者只发出NavigationEnd类型的项,并且没有与先前发出的项相同的路由。
#3
13
If you are running into this issue after August 2017 then you most probably should use gtag.js (Google Universal Analytics Global Site Tag) instead of the old analytics.js. I suggest you to check the difference between the both in Migrate from analytics.js to gtag.js page, as well as How gtag.js works in Single page applications before continuing.
如果您在2017年8月之后遇到此问题,那么您很可能应该使用gtag.js(Google Universal Analytics全球网站代码)而不是旧的analytics.js。我建议你在继续之前检查migrate from analytics.js和gtag.js页面之间的区别,以及gtag.js如何在单页面应用程序中工作。
When you get your code snippet from Google Analytics it looks like this:
当您从Google Analytics获取代码段时,它看起来像这样:
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= GOOGLE_ANALYTICS_ID %>"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '<%= GOOGLE_ANALYTICS_ID %>'); <!-- Remove that one -->
</script>
You need to remove the last line of the script and add the rest to your index.html
.
您需要删除脚本的最后一行并将其余部分添加到index.html。
Then you have to add the line you deleted from the script above to your code and add the page to track. Basically it's almost the same as the guys above suggested for analytics.js
but now you use the gtag.js
function.
然后,您必须将从上面脚本中删除的行添加到代码中,并将页面添加到跟踪中。基本上它与上面为analytics.js建议的人几乎相同,但现在你使用gtag.js函数。
For example if you want to track all pages you open here is the sample code:
例如,如果要跟踪您在此处打开的所有页面,请参阅示例代码:
import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import 'rxjs/add/operator/distinctUntilChanged';
// This still has to be declared
declare var gtag: Function;
@Component({
moduleId: module.id,
selector: 'my-app',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
})
export class AppComponent implements OnInit {
constructor(private router: Router) { }
ngOnInit() {
this.router.events.distinctUntilChanged((previous: any, current: any) => {
// Subscribe to any `NavigationEnd` events where the url has changed
if(current instanceof NavigationEnd) {
return previous.url === current.url;
}
return true;
}).subscribe((x: any) => {
gtag('config', '<%= GOOGLE_ANALYTICS_ID %>', {'page_path': x.url});
});
}
}
If you've read the documentation for the gtag.js
then you know that there could be tons of tracking options, but I focus on the most basic usage here.
如果你已经阅读了gtag.js的文档,那么你知道可能有大量的跟踪选项,但我会关注这里最基本的用法。
#1
50
I managed to get this working by subscribing to changes on the router, checking that the route had actually changed (I was getting multiple events on some routes at times) and then sending the new path to Google.
我设法通过订阅路由器上的更改,检查路由实际已经改变(我有时在某些路由上获得多个事件)然后将新路径发送给Google来实现此功能。
app.component.ts
app.component.ts
import { ... } from '...';
// Declare ga function as ambient
declare var ga:Function;
@Component({ ... })
export class AppComponent {
private currentRoute:string;
constructor(_router:Router) {
// Using Rx's built in `distinctUntilChanged ` feature to handle url change c/o @dloomb's answer
router.events.distinctUntilChanged((previous: any, current: any) => {
// Subscribe to any `NavigationEnd` events where the url has changed
if(current instanceof NavigationEnd) {
return previous.url === current.url;
}
return true;
}).subscribe((x: any) => {
ga('set', 'page', x.url);
ga('send', 'pageview')
});
}
}
}
You also need to include the google analytics code in your main index file before loading your angular2 app so that the global ga
object exists, but you don't want to send the initial view twice. In order to do this, remove the following line from the GA script
您还需要在加载angular2应用程序之前在主索引文件中包含Google Analytics代码,以便全局ga对象存在,但您不希望将初始视图发送两次。为此,请从GA脚本中删除以下行
index.html
的index.html
<script>
(function(i,s,o,g,r,a,m){...})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-X', 'auto');
// Remove this line to avoid sending the first page view twice.
//ga('send', 'pageview');
</script>
<!--
Load your ng2 app after ga.
This style of deferred script loading doesn't guarantee this will happen
but you can use Promise's or what works for your particular project.
-->
<script defer type="text/javascript" src="/app.js"></script>
Using a third party library
使用第三方库
As an alternative to implementing GA yourself, the library Angulartics2 is also a popular tool for implementing GA tracking and also integrates with other analytics vendors as well.
作为自己实施GA的替代方案,Angulartics2库也是实现GA跟踪的流行工具,也可以与其他分析供应商集成。
#2
33
Expanding on Ian's answer. You can use Rx's built in features to handle the distinction between current and new routes.
扩展伊恩的答案。您可以使用Rx的内置功能来处理当前路由和新路由之间的区别。
import { NavigationEnd, Router } from '@angular/router';
declare var ga: any;
export class AppComponent {
constructor(public router: Router) {
router.events.distinctUntilChanged((previous: any, current: any) => {
if(current instanceof NavigationEnd) {
return previous.url === current.url;
}
return true;
}).subscribe((x: any) => {
console.log('router.change', x);
ga('send', 'pageview', x.url);
});
}
}
We are using the distinctUntilChanged operator to make the observer only emit items that are of type NavigationEnd and do not have the same route as the previously emitted item.
我们使用distinctUntilChanged运算符使观察者只发出NavigationEnd类型的项,并且没有与先前发出的项相同的路由。
#3
13
If you are running into this issue after August 2017 then you most probably should use gtag.js (Google Universal Analytics Global Site Tag) instead of the old analytics.js. I suggest you to check the difference between the both in Migrate from analytics.js to gtag.js page, as well as How gtag.js works in Single page applications before continuing.
如果您在2017年8月之后遇到此问题,那么您很可能应该使用gtag.js(Google Universal Analytics全球网站代码)而不是旧的analytics.js。我建议你在继续之前检查migrate from analytics.js和gtag.js页面之间的区别,以及gtag.js如何在单页面应用程序中工作。
When you get your code snippet from Google Analytics it looks like this:
当您从Google Analytics获取代码段时,它看起来像这样:
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= GOOGLE_ANALYTICS_ID %>"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '<%= GOOGLE_ANALYTICS_ID %>'); <!-- Remove that one -->
</script>
You need to remove the last line of the script and add the rest to your index.html
.
您需要删除脚本的最后一行并将其余部分添加到index.html。
Then you have to add the line you deleted from the script above to your code and add the page to track. Basically it's almost the same as the guys above suggested for analytics.js
but now you use the gtag.js
function.
然后,您必须将从上面脚本中删除的行添加到代码中,并将页面添加到跟踪中。基本上它与上面为analytics.js建议的人几乎相同,但现在你使用gtag.js函数。
For example if you want to track all pages you open here is the sample code:
例如,如果要跟踪您在此处打开的所有页面,请参阅示例代码:
import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import 'rxjs/add/operator/distinctUntilChanged';
// This still has to be declared
declare var gtag: Function;
@Component({
moduleId: module.id,
selector: 'my-app',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
})
export class AppComponent implements OnInit {
constructor(private router: Router) { }
ngOnInit() {
this.router.events.distinctUntilChanged((previous: any, current: any) => {
// Subscribe to any `NavigationEnd` events where the url has changed
if(current instanceof NavigationEnd) {
return previous.url === current.url;
}
return true;
}).subscribe((x: any) => {
gtag('config', '<%= GOOGLE_ANALYTICS_ID %>', {'page_path': x.url});
});
}
}
If you've read the documentation for the gtag.js
then you know that there could be tons of tracking options, but I focus on the most basic usage here.
如果你已经阅读了gtag.js的文档,那么你知道可能有大量的跟踪选项,但我会关注这里最基本的用法。