TypeScript - Angular 4+ folosind Google Analytics


Încerc să folosesc Google Analytics cu Angular 4, dar nu pot găsi niciun @type pentru ga.js în ts.

Pentru o soluție rapidă, am folosit asta în fiecare componentă:

declare let ga: any;

Urmând modul în care am rezolvat-o:

Creează o funcție pentru a încărca GA dinamic, care inserează scriptul GA cu trackingId-ul și utilizatorul curent.

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

Creează serviciul pentru a implementa metodele de care vei avea nevoie.

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

Apoi folosesc în sfârșit serviciul injectat în componentă.

constructor(private ga: GAService) {}

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

Răspuns #1

În primul rând, trebuie să instalezi tipurile pentru Google Analytics în devDependencies-urile tale

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

Apoi adaugă codul tău de urmărire în fișierul de bază index.html și elimină ultima linie așa cum este arătat mai jos:

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

Următorul pas constă în actualizarea constructorului componentei tale principale pentru urmărirea evenimentelor.

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

Dacă vrei să urmărești un anumit eveniment, poți de asemenea să creezi un serviciu și să-l injectezi în orice componentă în care vrei să implementezi urmărirea evenimentelor.

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

Deci, dacă vrei să urmărești un click pe componenta ta de acasă, de exemplu, tot ce trebuie să faci este să injectezi GoogleAnalyticsEventsService și să apelezi metoda emitEvent().

Codul sursă actualizat al componentei home:

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

Răspuns #2

Sunt surprins că nimeni aici nu a menționat încă Google Tag Manager (care este versiunea scriptului pe care consola Google Analytics mi-o generează în ultimii ani, ori de câte ori adaug o identitate nouă).

Iată o soluție la care m-am gândit astăzi, care este o variație a soluțiilor deja menționate în celelalte răspunsuri, adaptată scriptului Google Tag Manager. Cred că ar fi utilă pentru persoanele care au migrat de la ga() la gtag() (o migrare care este recomandată, după câte știu).

analytics.service.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);
      }
    });
  }
}

Cerințe prealabile:

  • Declarați serviciul în secțiunea imports[] a fișierului app.module.ts.
  • În fișierul tău app.component.ts (sau orice componentă de nivel superior care conține tag-ul <router-outlet> în șablonul său), injectează AnalyticsService și apelează this.analytics.init() cât mai devreme posibil (de exemplu, în ngOnInit)
  • În fișierul environment.ts (în cazul meu - environment.prod.ts), adăugați ID-ul Analytics ca googleAnalyticsKey: 'UA-XXXXXXX-XXXX'

Răspunsul #3

Încarcă Google Analytics, folosind variabilele de mediu, într-un mod asincron;

(Funcționează pe Angular 5)

(Folosind răspunsul lui @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
      });
    }
  }


}

În interiorul app.component sau al oricărui alt component:

 // ... 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);