75 votes

Angular 4+ avec Google Analytics

J'essaie d'utiliser Google Analytics avec angular 4, mais je ne trouve pas de @type pour ga.js dans ts.

Pour une solution rapide, j'ai utilisé ceci dans chaque composant :

declare let ga: any;

Voici comment je l'ai résolu :

Créer une fonction pour charger le GA dynamiquement qui insère le GA script avec le trackingId et l'utilisateur actuels.

    loadGA(userId) {
        if (!environment.GAtrackingId) return;

        let scriptId = 'google-analytics';

        if (document.getElementById(scriptId)) {
            return;
        }

        var s = document.createElement('script') as any;
        s.type = "text/javascript";
        s.id = scriptId;
        s.innerText = "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');ga('create', { trackingId: '" + **environment.GAtrackingId** + "', cookieDomain: 'auto', userId: '" + **userId** + "'});ga('send', 'pageview', '/');";

        document.getElementsByTagName("head")[0].appendChild(s);
    }

Créez le service pour mettre en œuvre les méthodes dont vous aurez besoin.

import { Injectable } from '@angular/core';
import { environment } from '../../../environments/environment';

declare let ga: any;

@Injectable()
export class GAService {
    constructor() {
    }

    /**
     * Checks if the GA script was loaded.
     */
    private useGA() : boolean { 
        return environment.GAtrackingId && typeof ga !== undefined;
    }

    /**
     * Sends the page view to GA.
     * @param  {string} page The path portion of a URL. This value should start with a slash (/) character.
     */
    sendPageView(
        page: string
    ) {
        if (!this.useGA()) return;
        if (!page.startsWith('/')) page = `/${page}`;      
        ga('send', 'pageview', page);
    }

    /**
     * Sends the event to GA.
     * @param  {string} eventCategory Typically the object that was interacted with (e.g. 'Video')
     * @param  {string} eventAction The type of interaction (e.g. 'play')
     */
    sendEvent(
        eventCategory: string,
        eventAction: string
    ) { 
        if (!this.useGA()) return;
        ga('send', 'event', eventCategory, eventAction);
    }
}

Puis j'utilise enfin le service injecté dans le composant.

constructor(private ga: GAService) {}

ngOnInit() { this.ga.sendPageView('/join'); }

0 votes

C'est une question assez générale. Comme il existe de nombreuses façons de gérer les globaux tiers dans Angular, mais si vous voulez un module pour l'analyse. Essayez ceci : github.com/peaksandpies/universal-analytics

0 votes

Désolé pour la question générale, je comprends que nous avons plusieurs façons de gérer les globaux tiers, mais j'ai résolu ce type de problème avec les '@types' et angular injectionToken, alors pour ce cas, il serait préférable de trouver un '@type' avec le module d'exportation. Enfin, je vous remercie pour votre aide et je vais vérifier votre solution.

1 votes

Peut-être que si tu mettais à jour la question pour expliquer comment tu utilises ga et quels problèmes cela vous pose. Par exemple, l'utilisation de Function comme type signifie qu'il a une valeur de retour nulle. D'après mon expérience, il est préférable de laisser les variables externes de ce type en tant que define let ga: any; qui désactive en quelque sorte toute vérification de type. Ce qui rend le travail plus facile.

103voto

Laiso Points 1825

Tout d'abord, vous devez installer les caractères pour Google Analytics dans votre devDependencies

npm install --save-dev @types/google.analytics

Ajoutez ensuite votre code de suivi dans la base index.html et supprimez la dernière ligne comme indiqué ci-dessous :

<body>
  <app-root>Loading...</app-root>
  <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-XXXXXX-ID', 'auto');  // <- add the UA-ID 
                                           // <- remove the last line 
  </script>
</body>

L'étape suivante consiste à mettre à jour le constructeur de votre composant d'accueil pour le suivi des événements.

constructor(public router: Router) {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        ga('set', 'page', event.urlAfterRedirects);
        ga('send', 'pageview');
      }
    });
  }

Si vous souhaitez assurer le suivi d'un événement spécifique, vous pouvez également créer un service et l'injecter dans n'importe quel composant pour lequel vous souhaitez mettre en œuvre le suivi des événements.

// ./src/app/services/google-analytics-events-service.ts

import {Injectable} from "@angular/core";

@Injectable()
export class GoogleAnalyticsEventsService {

  public emitEvent(eventCategory: string,
                   eventAction: string,
                   eventLabel: string = null,
                   eventValue: number = null) {
    ga('send', 'event', { eventCategory, eventLabel, eventAction, eventValue });
  }
}

Ainsi, si vous souhaitez suivre un clic sur votre composant d'accueil par exemple, il vous suffit d'injecter l'élément GoogleAnalyticsEventsService et appeler le emitEvent() méthode.

Le code source du composant maison mis à jour :

constructor(public router: Router, public googleAnalyticsEventsService: GoogleAnalyticsEventsService) {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        ga('set', 'page', event.urlAfterRedirects);
        ga('send', 'pageview');
      }
    });
  }
  submitEvent() { // event fired from home.component.html element (button, link, ... )
    this.googleAnalyticsEventsService.emitEvent("testCategory", "testAction", "testLabel", 10);
  }

4 votes

Avec Angular 4, j'ai eu son erreur Cannot find name 'ga'. webpack: Failed to compile. dans le terminal pour ce code if (event instanceof NavigationEnd) { ga('set', 'page', event.urlAfterRedirects); ga('send', 'pageview'); }

6 votes

Essayez d'ajouter la déclaration dans votre composant : declare var ga: Function;

9 votes

Il ne faut pas npm install --save-dev @types/google.analytics répondre au besoin de declare var ga: Function; ?

60voto

user1364793 Points 97

Je suis surpris que personne ici n'ait mentionné Le gestionnaire de balises de Google (qui est la version du script que la console Google Analytics me sort depuis quelques années, chaque fois que j'ajoute une nouvelle identité).

Voici une solution que j'ai trouvée aujourd'hui, qui est une variante des solutions déjà mentionnées dans les autres réponses, en s'adaptant au Tag Manager script de Google. Je pense que ce serait utile pour les personnes qui ont migré de ga() a gtag() (une migration qui est recommandé pour autant que je sache).

service.analytique.ts

declare var gtag: Function;

@Injectable({
  providedIn: 'root'
})
export class AnalyticsService {

  constructor(private router: Router) {

  }

  public event(eventName: string, params: {}) {
    gtag('event', eventName, params);
  }

  public init() {
    this.listenForRouteChanges();

    try {

      const script1 = document.createElement('script');
      script1.async = true;
      script1.src = 'https://www.googletagmanager.com/gtag/js?id=' + environment.googleAnalyticsKey;
      document.head.appendChild(script1);

      const script2 = document.createElement('script');
      script2.innerHTML = `
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', '` + environment.googleAnalyticsKey + `', {'send_page_view': false});
      `;
      document.head.appendChild(script2);
    } catch (ex) {
      console.error('Error appending google analytics');
      console.error(ex);
    }
  }

  private listenForRouteChanges() {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        gtag('config', environment.googleAnalyticsKey, {
          'page_path': event.urlAfterRedirects,
        });
        console.log('Sending Google Analytics hit for route', event.urlAfterRedirects);
        console.log('Property ID', environment.googleAnalyticsKey);
      }
    });
  }
}

Conditions préalables :

  • Déclarez le service dans la section imports[] de votre fichier app.module.ts .
  • Dans votre app.component.ts (ou n'importe quel composant de niveau supérieur contenant l'option <router-outlet> dans son modèle), injecte le AnalyticsService et appelle this.analytics.init() le plus tôt possible (par exemple, ngOnInit)
  • Dans le fichier environment.ts (dans mon cas - environment.prod.ts), ajoutez l'ID Analytics comme suit googleAnalyticsKey: 'UA-XXXXXXX-XXXX'

1 votes

Merci beaucoup, je ne sais pas pourquoi personne ne mentionne gtag non plus. Très bonne solution, vous êtes une star !

2 votes

Merci pour cette solution. Une petite erreur cependant. La déclaration des services doit être modifiée comme ci-dessous. Déclarez le service dans la section providers[] de votre app.module.ts .

2 votes

@Shabith en fait providedIn remplace providers: [] dans le module, comme le recommande la pratique, à partir d'Angular 6+. . Personnellement, je préfère toujours la "propreté" de la providers approche, mais qui me le demande. :)

25voto

Artipixel Points 863

Chargement de google analytics, en utilisant des variables d'environnement, de manière asynchrone ;

(Fonctionne sur Angular 5)

(En utilisant la réponse de @Laiso)

google-analytics.service.ts

import {Injectable} from '@angular/core';
import {NavigationEnd, Router} from '@angular/router';
declare var ga: Function;

@Injectable()
export class GoogleAnalyticsService {

  constructor(public router: Router) {
    this.router.events.subscribe(event => {
      try {
        if (typeof ga === 'function') {
          if (event instanceof NavigationEnd) {
            ga('set', 'page', event.urlAfterRedirects);
            ga('send', 'pageview');
            console.log('%%% Google Analytics page view event %%%');
          }
        }
      } catch (e) {
        console.log(e);
      }
    });

  }

  /**
   * Emit google analytics event
   * Fire event example:
   * this.emitEvent("testCategory", "testAction", "testLabel", 10);
   * @param {string} eventCategory
   * @param {string} eventAction
   * @param {string} eventLabel
   * @param {number} eventValue
   */
  public emitEvent(eventCategory: string,
   eventAction: string,
   eventLabel: string = null,
   eventValue: number = null) {
    if (typeof ga === 'function') {
      ga('send', 'event', {
        eventCategory: eventCategory,
        eventLabel: eventLabel,
        eventAction: eventAction,
        eventValue: eventValue
      });
    }
  }

}

Dans app.component ou n'importe quel composant :

 // ... import stuff

 import { environment } from '../../../environments/environment';

 // ... declarations

 constructor(private googleAnalyticsService: GoogleAnalyticsService){
    this.appendGaTrackingCode();
 }

 private appendGaTrackingCode() {
    try {
      const script = document.createElement('script');
      script.innerHTML = `
        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

        ga('create', '` + environment.googleAnalyticsKey + `', 'auto');
      `;
      document.head.appendChild(script);
    } catch (ex) {
     console.error('Error appending google analytics');
     console.error(ex);
    }
  }

// Somewhere else we can emit a new ga event
this.googleAnalyticsService.emitEvent("testCategory", "testAction", "testLabel", 10);

2 votes

Le fichier google-analytics.service.ts est une bonne solution, mais notez qu'un des inconvénients du déplacement de la fonction appendGaTrackingCode() de l'index.html <head> recommandé vers l'app.component signifie que google analytics ne mesurera pas précisément les temps de chargement moyens des pages, puisqu'il ne lancera le minuteur qu'une fois le bundle javascript angulaire récupéré et exécuté.

0 votes

@user761574 C'est correct, mais seulement pour le premier chargement de l'application, en supposant que vous partagez ce service à travers votre application.

7voto

Filip Molcik Points 321

GoogleAnalyticsService

Vous pouvez créer service qui s'abonne aux évènements du routeur et l'injecter dans app.module.ts pour ne pas avoir à l'injecter dans chaque composant.

@Injectable()
export class GoogleAnalyticsService {

  constructor(router: Router) {
    if (!environment.production) return; // <-- If you want to enable GA only in production
    router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        ga('set', 'page', event.url);
        ga('send', 'pageview');
      }
    })
  }

Voici le tutoriel (mon blog) .

5voto

jalak vora Points 54

Pour éviter toute vérification du type, si ga est défini globalement au niveau de la fenêtre, vous pouvez simplement faire ce qui suit

 window["ga"]('send', {
    hitType: 'event',
    eventCategory: 'eventCategory',
    eventAction: 'eventAction'
    });

J'espère que cela vous aidera.

0 votes

@r3plica regarde ça.

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