48 votes

Suivi des pages vues par Google Analytics en Angular2

J'ai construit un nouveau site en utilisant Angular 2 comme frontal. Comme tout se fait par push state, il n'y a pas de chargement de page qui déclenche généralement le code de Google Analytics pour envoyer une page vue aux serveurs de Google.

Comment puis-je envoyer manuellement des événements de consultation de page à Google afin de pouvoir suivre ce que les utilisateurs de mon site consultent ?

57voto

Ian Belcher Points 2972

J'ai réussi à le faire fonctionner en m'abonnant aux changements sur le routeur, en vérifiant que l'itinéraire avait effectivement changé (je recevais parfois plusieurs événements sur certains itinéraires), puis en envoyant le nouveau chemin à 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')
        });
      }
    }
}

Vous devez également inclure le code de google analytics dans votre fichier d'index principal avant de charger votre application angular2 afin que le code global de google analytics soit activé. ga existe, mais vous ne voulez pas envoyer la vue initiale deux fois. Pour ce faire, supprimez la ligne suivante du script de 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>

Utilisation d'une bibliothèque tierce

Comme alternative à l'implémentation de GA par vous-même, la bibliothèque Angulartics2 est également un outil populaire pour la mise en œuvre du suivi GA et s'intègre également à d'autres fournisseurs d'analyses.

0 votes

Y a-t-il un moyen d'éviter d'ajouter un script en ligne à l'index.html ? Je pensais que le but d'Angular Js était de garder les script JS organisés.

0 votes

Angular2 lui-même n'organise pas les scripts mais il fonctionne avec des styles plus récents de chargement de scripts comme amd et commonjs etc. La façon dont vous chargez GA dépend de votre chargeur et s'il fonctionne avec des scripts déclarés globalement tels que ga. Cette réponse est plutôt une approche " taille unique ".

1 votes

Je crois que cela devrait être let newRoute = this._router._location.path() || '/'; au lieu de let newRoute = this._location.path() || '/'; @IanBelcher

33voto

MoleFole Points 224

En développant la réponse de Ian. Vous pouvez utiliser les fonctions intégrées de Rx pour gérer la distinction entre les routes actuelles et les nouvelles routes.

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

Nous utilisons l'opérateur distinctUntilChanged pour que l'observateur n'émette que les éléments qui sont de type NavigationEnd et qui n'ont pas la même route que l'élément précédemment émis.

0 votes

J'obtiens bien console.log(), mais dans la console je ne vois pas le ga('send', 'pageview') ; ajouté à mon scirpt analytique. Est-ce normal ?

1 votes

Vous devriez ga('set', 'page', event.urlAfterRedirects); et ensuite ga('send', 'pageview');

0 votes

Erreur : 'Argument of type '(event : Event) => void' is not assignable to parameter of type '(value : Event) => void'. Les types des paramètres 'event' et 'value' sont incompatibles. Le type 'Event' n'est pas assignable au type 'Event'. Deux types différents portant ce nom existent, mais ils ne sont pas liés.

24voto

nyxz Points 419

Si vous rencontrez ce problème après août 2017 alors vous devriez très probablement utiliser gtag.js (Google Universal Analytics Global Site Tag) au lieu de l'ancienne étiquette analytics.js . Je vous suggère de vérifier la différence entre les deux en Migrer de analytics.js vers gtag.js ainsi que la page Fonctionnement de gtag.js dans les applications monopages avant de poursuivre.

Lorsque vous obtenez votre extrait de code de Google Analytics, il ressemble à ceci :

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

Vous devez retirer la dernière ligne du script et ajouter le reste à votre index.html .

Ensuite, vous devez ajouter la ligne que vous avez supprimée du script ci-dessus à votre code et ajouter la page à la piste . Fondamentalement, c'est presque la même chose que ce que les gars ci-dessus ont suggéré pour analytics.js mais maintenant vous utilisez le gtag.js fonction.

Par exemple, si vous voulez suivre toutes les pages que vous ouvrez, voici un exemple de 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});
        });
    }
}

Si vous avez lu la documentation relative à l'option gtag.js alors vous savez qu'il peut y avoir des tonnes d'options de suivi, mais je me concentre ici sur l'utilisation la plus basique.

6voto

Cyril Blanchet Points 153

Dans Angular 6, je suggère pour le 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
        });
      }
    });
  }

}

Pour l'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>

Vous pouvez gérer le titre de vos pages avec le service Title fourni par Angular : https://angular.io/guide/set-document-title

0voto

Omer Gurarslan Points 326

En supposant que chaque route Angular a son propre titre dans le fichier app.routing.ts :

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

Les solutions mentionnées précédemment affichent toujours le même titre de page pour chaque itinéraire dans le rapport Google Analytics. Afin d'utiliser les titres de route Angular correspondants ( au lieu de index.html <title> tout le temps), utilisez le code ci-dessous dans la section 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');

  }
});

...où getPageTitle est la suivante :

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

Remarque : Cette solution s'applique à Anguler 5 et aux versions inférieures. Dans Angular 6, vous pouvez également utiliser TitreService

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X