Angular 4+ using Google Analytics

I'm trying to use the Google Analytics with angular 4, but i can't find any @type to ga.js in ts.

For a quick solution I used this in every component:

declare let ga: any;

Following how I resolved it:

Create a function to load the GA dynamically that inserts the GA script with current trackingId and user.

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

Create the service to implement the methods that you will need.

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

Then I finally use the service injected in component.

constructor(private ga: GAService) {}

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

First of all, you need to install typings for Google Analytics in your devDependencies

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

Then add your tracking code in the base index.html, and remove the last line as shown bellow:

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

The next step consists to update your home component constructor for event tracking.

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

If you want to track some specific event, you can also create a service and inject it into any component that you want to implement event tracking.

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

So if you want track a click on your home component for example, all you need to do is to inject the GoogleAnalyticsEventsService and call the emitEvent() method.

The updated home component source code:

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

Angular 4 Tutorial, In this tutorial, you're going to learn the fundamentals of Angular 4 in an easy and step-by-step way. Angular 4 released in March 2017 proves to be a major breakthrough and is the latest release from the Angular team after Angular2. Angular 4 is almost the same as Angular 2. It has a backward compatibility with Angular 2.

Angular 4 - Overview, Angular Certification Training - https://www.edureka.co/angular-training ) This Edureka "Angular Duration: 1:32:14 Posted: May 8, 2017 Angular 4 is a JavaScript framework for building web applications and apps in JavaScript, html, and TypeScript, which is a superset of JavaScript. Angular provides built-in features for animation, http service, and materials which in turn has features such as auto-complete, navigation, toolbar

Load google analytics, using environment vars, the async way;

(Works on Angular 5)

(Using @Laiso answer)

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


}
Inside app.component or whatever 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);

Angular 4 Tutorial: Angular 4 in 20 minutes, This first version of the framework known as AngularJS was launched in the year 2009. It laid the foundation of the present-day front-end� Angular 4 is backward compatible with Angular 2. Angular version 4.3 is a minor release, meaning that it contains no breaking changes and that it is a drop-in replacement for 4.x.x. Features in version 4.3 Introducing HttpClient, a smaller, easier to use, and more powerful library for making HTTP Requests.

GoogleAnalyticsService

You can create service that subscribes for router events and inject it in app.module.ts so you don't have to inject it in every component.

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

Here is tutorial (my blog).

Angular (web framework), Angular 4 Tutorial with angular 4, angular 4 introduction, angular, angular 4 installation, angular 4 history, angular 4 versions, components, directives, ngif� Angular 4 - Http Service - Http Service will help us fetch external data, post to it, etc. We need to import the http module to make use of the http service. Let us consider an example to

To avoid any type checking if ga is defined globally at window level then you could simply do

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

Hope it helps.

Angular 4 Tutorial For Beginners, SPA in web terminology stands for “Single-Page Application”. Before we take a deep-dive into Angular and know how to get started with one such� Angular 4 - Forms - In this chapter, we will see how forms are used in Angular 4. We will discuss two ways of working with forms - template driven form and model driven forms.

AngularJS vs Angular 2 vs Angular 4: What's the Difference?, Angular 4 has been released. In this article, Karsten Sitterberg and Thomas Kruse show all the innovations, give tips on migrating and take a� Angular 4 released in March 2017, with the framework's version aligned with the version number of the router it used. Angular 5 was released on November 1, 2017. Key improvements in Angular 5 include support for progressive Web apps, a build optimizer and improvements related to Material Design.

Angular 4 Tutorial, Introduction to the Angular Docslink. Angular is an application design framework and development platform for creating efficient and sophisticated single-page apps. These Angular docs help you learn and use the Angular framework and development platform, from your first application to optimizing complex single-page apps for enterprises.

Introduction to Angular 4 : A beginner's guide., An Angular application comprises a tree of components, in which each Angular component has a specific purpose and responsibility. Currently, the example app has three components: app-root (orange box) is the application shell.

Comments
  • Kind of broad question here. As there are many ways to handle third-party globals in Angular, but if you want a module for analytics. Give this a try: github.com/peaksandpies/universal-analytics
  • Sorry about the broad question, I understand that we have many ways to handle third-party globals, but I've been resolving this type of issue with the '@types' and angular injectionToken, then for this case it would be better to find a '@type' with export module. Finally thank you for your help and i will check your solution.
  • Maybe if you updated the question to explain how your using ga and what problems that is giving you. For example; using Function as the type means that it has a void return value. In my experience, outside variables like that are best left as define let ga: any; which kind of disables all type checking. Making it easier to work with.
  • Thanks @cgTag, I replaced the function type by any type and created a service to declare GA only once and now it looks good to me. As you requested, I updated the question to explain how I did it.
  • Is that a question or an answer?
  • with Angular 4, I got his error Cannot find name 'ga'. webpack: Failed to compile. in the terminal for this code if (event instanceof NavigationEnd) { ga('set', 'page', event.urlAfterRedirects); ga('send', 'pageview'); }
  • Try to add declaration inside your component: declare var ga: Function;
  • Shouldn't npm install --save-dev @types/google.analytics fix the need of declare var ga: Function;?
  • I solved the ReferenceError by adding an import statement: import {} from '@types/google.analytics';
  • Regarding the reference error, you could try removing the empty types array from my tsconfig.json file, which worked for me. From the docs: typescriptlang.org/docs/handbook/tsconfig-json.html ` Specify "types": [] to disable automatic inclusion of @types packages. So removing the empty array means that global declarations in @types packages will be automatically included without the need to specifically import them in any file.
  • Thanks a lot, I don't know why nobody mention gtag either. Very good solution, you're a star!