Javascript 在Angular2中跟踪谷歌分析页面浏览量

Javascript 在Angular2中跟踪谷歌分析页面浏览量,javascript,google-analytics,angular,Javascript,Google Analytics,Angular,我用Angular 2作为前端构建了一个新站点。由于所有操作都是通过push state完成的,因此没有页面加载通常会触发Google Analytics代码向Google服务器发送页面视图 如何手动将页面查看事件发送到Google,以便跟踪我网站的用户正在查看的内容?我通过订阅路由器上的更改,检查路由是否已实际更改(我有时会在某些路由上获得多个事件),然后将新路径发送到Google,成功地实现了这一点 应用程序组件.ts import { ... } from '...'; // Decla

我用Angular 2作为前端构建了一个新站点。由于所有操作都是通过push state完成的,因此没有页面加载通常会触发Google Analytics代码向Google服务器发送页面视图


如何手动将页面查看事件发送到Google,以便跟踪我网站的用户正在查看的内容?

我通过订阅路由器上的更改,检查路由是否已实际更改(我有时会在某些路由上获得多个事件),然后将新路径发送到Google,成功地实现了这一点

应用程序组件.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')
        });
      }
    }
}
在加载angular2应用程序之前,您还需要在主索引文件中包含google analytics代码,以便全局
ga
对象存在,但您不希望发送两次初始视图。为此,请从GA脚本中删除以下行

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>

函数(i,s,o,g,r,a,m){…}(窗口,文档,'script','https://www.google-analytics.com/analytics.js","ga",;
ga(“创建”、“UA-XXXXXXXX-X”、“自动”);
//删除此行以避免发送两次第一页视图。
//ga(‘发送’、‘页面浏览’);

使用第三方库


作为自己实现GA的替代方案,该库也是实现GA跟踪的流行工具,并且还与其他分析供应商集成。

扩展Ian的答案。您可以使用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);
            });
        }
    }

我们使用distinctUntilChanged操作符使观察者仅发射NavigationEnd类型的项目,并且与之前发射的项目没有相同的路线。

如果您在2017年8月之后遇到此问题则您很可能应该使用(Google Universal Analytics Global Site Tag)而不是旧的。我建议您在页面中以及继续之前检查两者之间的差异

当您从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>

如果您已经阅读了
gtag.js
的文档,那么您知道可能有很多跟踪选项,但我在这里重点介绍了最基本的用法。

在Angular 6中,我建议使用app.component.ts:

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router'
import { Title } from '@angular/platform-browser';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {

  constructor(
    private router: Router,
    private titleService: Title
  ){ }

  ngOnInit() {
     this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        (<any>window).gtag('config', '<%= GOOGLE_ANALYTICS_ID %>', {
          'page_title' : this.titleService.getTitle(),
          'page_path': event.urlAfterRedirects
        });
      }
    });
  }

}
从'@angular/core'导入{Component,OnInit};
从'@angular/Router'导入{Router,NavigationEnd}
从“@angular/platform browser”导入{Title};
@组成部分({
选择器:'应用程序根',
templateUrl:“./app.component.html”,
样式URL:['./app.component.css']
})
导出类AppComponent{
建造师(
专用路由器:路由器,
私人产权服务:产权
){ }
恩戈尼尼特(){
this.router.events.subscribe(事件=>{
if(NavigationEnd的事件实例){

假设每个角度路线在
app.routing.ts
中都有自己的标题:

   {
    path: 'shop',
    component: ShopComponent,
    data: {
      title: ' == This is Shop Component Title =='
    },
    canActivate: [AuthGuard]
  },
前面提到的解决方案仍然会在Google Analytics Report上为每条路线显示相同的页面标题。为了使用相应的角度路线标题(而不是index.html
标记内容),请使用
app.component.ts

  this.router.events.subscribe(event => {

  if (event instanceof NavigationEnd) {
    (<any>window).ga('set', 'page', event.urlAfterRedirects);

    // ----------
    //use the following 3 lines of code to use
    //correnct titles for routes        
    // ----------

    let currentRoute = this.route.root;
    let title = this.getPageTitle(currentRoute);
    (<any>window).ga('set', 'title', title);

    (<any>window).ga('send', 'pageview');

  }
});

注意:此解决方案适用于Anguler 5及以下版本。在Angular 6中,您也可以使用

是否有任何方法可以避免在index.html中添加内联脚本?我认为Angular js背后的全部要点是保持js脚本的组织。Angular2本身并不组织脚本,但它可以与更新样式的脚本加载(如amd和commo)一起工作njs等。加载GA的方式取决于加载程序,以及它是否与全局声明的脚本(如GA)一起工作。这个答案几乎是一种“一刀切”的方法。我认为应该是
让newRoute=This.\u router.\u location.path()|'/'
而不是
让newRoute=This.\u location.path()| |“/”
@ianbelcher依据,您应该
ga('set','page',newRoute)
,然后
ga('send','pageview')
在Visual Basic代码中遇到一些错误:'type'(event:event)=>void'的参数不能赋值给type'(value:event)的参数=>void。参数“event”和“value”的类型不兼容。类型“event”不可分配给类型“event”。存在两种具有此名称的不同类型,但它们不相关。类型“NavigationStart”不可分配给类型“event”。类型“NavigationStart”中缺少属性“bubbles”。“我正在获取一个wright控制台。log(),但在控制台中,我看不到添加到我的分析scirpt中的ga('send','pageview')。这正常吗?您应该
ga('set','page',event.urlAfterRedirects);
然后
ga('send','pageview');
看到一些错误:'type参数'(event:event)=>void'不能分配给type参数'(value:event)=>void'。参数“event”和“value”的类型不兼容。类型“event”不可分配给类型“event”。存在两种具有此名称的不同类型,但它们不相关。新的简单方法
   {
    path: 'shop',
    component: ShopComponent,
    data: {
      title: ' == This is Shop Component Title =='
    },
    canActivate: [AuthGuard]
  },
  this.router.events.subscribe(event => {

  if (event instanceof NavigationEnd) {
    (<any>window).ga('set', 'page', event.urlAfterRedirects);

    // ----------
    //use the following 3 lines of code to use
    //correnct titles for routes        
    // ----------

    let currentRoute = this.route.root;
    let title = this.getPageTitle(currentRoute);
    (<any>window).ga('set', 'title', title);

    (<any>window).ga('send', 'pageview');

  }
});
getPageTitle = function (currentRoute: ActivatedRoute) {
  let data;
    do {
      const childrenRoutes = currentRoute.children;
      currentRoute = null;
      childrenRoutes.forEach(route => {

      if (route.outlet === 'primary') {
        currentRoute = route;
        data = route.snapshot.data;
      }
    });
  } while (currentRoute);
  return data.title;
};
this.router.events.subscribe(event => {
    if (event instanceof NavigationEnd) {
        ga('set','page', event.urlAfterRedirects);
        ga('send', 'pageview');
    }
});