web-dev-qa-db-ja.com

Angular2でのGoogle Analyticsページビューの追跡

Angular 2をフロントエンドとして使用して新しいサイトを構築しました。すべてがプッシュ状態を介して行われるため、通常はページビューを送信するGoogleアナリティクスコードをトリガーするページ読み込みはありません。 Googleのサーバー。

自分のサイトのどのユーザーが閲覧しているかを追跡できるように、ページビューイベントをGoogleに手動で送信するにはどうすればよいですか?

43
Ian Belcher

ルーターの変更をサブスクライブし、ルートが実際に変更されたことを確認して(一部のルートで複数のイベントを取得していた)、新しいパスをGoogleに送信することで、これを機能させることができました。

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')
        });
      }
    }
}

さらに、angular2アプリをロードする前に、メインのインデックスファイルにGoogleアナリティクスコードを含めて、グローバルgaオブジェクトが存在するようにする必要がありますが、初期ビューを2回送信する必要はありません。これを行うには、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>

サードパーティのライブラリを使用する

GA自分で実装する代わりに、ライブラリ Angulartics2 は、GA追跡を実装するための一般的なツールであり、他の分析ベンダーも同様です。

53
Ian Belcher

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型のアイテムのみを発行し、以前に発行されたアイテムと同じルートを持たないようにします。

33
dloomb

2017年8月以降にこの問題に直面している場合、おそらく gtag.js (Google Universal Analytics Global Siteタグ) analytics.js の代わりに。 analytics.jsからgtag.jsへの移行 ページと シングルページアプリケーションでのgtag.jsの動作 の両方の違いを確認することをお勧めします。

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>

スクリプトの最後の行を削除して、残りをindex.htmlに追加する必要があります。

次に、上記のスクリプトから削除した行をコードに追加し、トラックにページを追加する必要があります。基本的に、上記のanalytics.jsに対して提案されたものとほぼ同じですが、今はgtag.js関数を使用しています。

たとえば、ここで開くすべてのページを追跡する場合のサンプルコードは次のとおりです。

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});
        });
    }
}

gtag.jsのドキュメントを読んだ場合は、追跡オプションが多数ある可能性があることを知っていますが、ここでは最も基本的な使用法に焦点を当てています。

21
nyxz

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
        });
      }
    });
  }

}

Index.htmlの場合:

  <!-- 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());
  </script>

Angular: https://angular.io/guide/set-document-title によって提供されるタイトルサービスを使用して、ページのタイトルを管理できます。

2
Cyril Blanchet

すべてのAngular Routeはapp.routing.ts

   {
    path: 'shop',
    component: ShopComponent,
    data: {
      title: ' == This is Shop Component Title =='
    },
    canActivate: [AuthGuard]
  },

前述のソリューションでは、Googleアナリティクスレポートの各ルートに同じページタイトルが引き続き表示されます。対応するAngularルートタイトル(index.htmlの代わりに<title>タグコンテンツを常に)、以下のコードを使用して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');

  }
});

...ここでgetPageTitleメソッドは次のとおりです。

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;
};

注:このソリューションは、Anguler 5以下に適用されます。 Angular 6では、 TitleService を使用することもできます

0
Omer Gurarslan
this.router.events.subscribe(event => {
    if (event instanceof NavigationEnd) {
        ga('set','page', event.urlAfterRedirects);
        ga('send', 'pageview');
    }
});
0