it-swarm.com.de

Verfolgung von Google Analytics-Seitenansichten in Angular2

Ich habe eine neue Site mit Angular 2 als Frontend erstellt. Da alles über den Push-Status ausgeführt wird, werden keine Seiten geladen, die normalerweise dazu führen, dass der Google Analytics-Code eine Seitensicht an die Server von Google sendet.

Wie kann ich Seitenansichtsereignisse manuell an Google senden, damit ich verfolgen kann, welche Nutzer meiner Website angezeigt werden?

40
Ian Belcher

Es gelang mir, dies zu funktionieren, indem ich Änderungen am Router abonnierte, überprüfte, ob sich die Route tatsächlich geändert hatte (ich hatte manchmal mehrere Ereignisse auf einigen Routen erhalten) und schickte dann den neuen Pfad an 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')
        });
      }
    }
}

Sie müssen auch den Google Analytics-Code in Ihre Hauptindexdatei aufnehmen, bevor Sie die angle2-App laden, damit das globale ga-Objekt vorhanden ist. Sie möchten jedoch die ursprüngliche Ansicht nicht zweimal senden. Entfernen Sie dazu die folgende Zeile aus dem Skript 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>

Verwenden einer Drittanbieter-Bibliothek

Als Alternative zur Implementierung von GA selbst ist die Bibliothek Angulartics2 auch ein beliebtes Werkzeug für die Implementierung von GA - Tracking und lässt sich auch in andere Analyseanbieter integrieren.

50
Ian Belcher

Ians Antwort wird erweitert. Sie können die integrierten Funktionen von Rx verwenden, um zwischen aktuellen und neuen Routen zu unterscheiden.

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

Wir verwenden den distinctUntilChanged-Operator, damit der Observer nur Elemente vom Typ NavigationEnd ausgeben kann und nicht die gleiche Route wie das zuvor ausgegebene Element hat.

33
dloomb

Wenn Sie dieses Problem nach August 2017 haben, sollten Sie höchstwahrscheinlich gtag.js (globales Google Tag von Universal Analytics) anstelle des alten analytics.js verwenden. . Ich empfehle Ihnen, den Unterschied zwischen den beiden Seiten in Migration von analytics.js zu gtag.js sowie Wie gtag.js in Einseitenanwendungen funktioniert zu überprüfen, bevor Sie fortfahren.

Wenn Sie Ihr Code-Snippet von Google Analytics erhalten, sieht es folgendermaßen aus:

<!-- 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>

Sie müssen die letzte Zeile des Skripts entfernen und den Rest Ihrem index.html hinzufügen.

Dann müssen Sie die Zeile, die Sie aus dem Skript oben gelöscht haben, zu Ihrem Code hinzufügen und die Seite zu track hinzufügen. Im Grunde ist es fast das gleiche wie die Jungs, die oben für analytics.js vorgeschlagen wurden, aber jetzt verwenden Sie die gtag.js-Funktion.

Wenn Sie beispielsweise alle Seiten verfolgen möchten, die Sie hier öffnen, ist der Beispielcode:

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

Wenn Sie die Dokumentation für gtag.js gelesen haben, wissen Sie, dass es unzählige Tracking-Optionen gibt, aber ich konzentriere mich hier auf die grundlegendste Verwendung.

17
nyxz

In Angular 6 empfehle ich für die 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
        });
      }
    });
  }

}

Für die 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>

Sie können den Titel Ihrer Seiten mit dem Titelservice von Angular verwalten: https://angular.io/guide/set-document-title

1
Cyril Blanchet

Angenommen, jede Winkelroute hat ihren eigenen Titel in app.routing.ts:

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

Bisher erwähnte Lösungen zeigen immer noch den gleichen Seitentitel für jede Route in Google Analytics-Bericht an. Verwenden Sie den folgenden Code in <title>, um die entsprechenden Angular Route-Titel zu verwenden (anstelle von index.html app.component.ts-Tag-Inhalt)

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

  }
});

... wobei getPageTitle Methode wie folgt ist:

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

Hinweis: Diese Lösung gilt für Anguler 5 und darunter. In Angular 6 können Sie auch TitleService verwenden.

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