angular and google analytics integration => ga is not a function

Ok, I didn't put the googleAnalytics script before the body, it was after. Now it works well. thanks to @WeissDev, it put me on the way when I saw that ga wasn't defined despite being in the window (weird). Anyway his solution works well too.


I've had a similar problem trying to integrate Google Analytics into my Angular 4 App.

What did the trick for me was to move the google analytics code from the AppComponent's constructor to the ngAfterViewInit() lifecycle hook to ensure that the view is fully initialized first.

Here's the code I got:

index.html (same as you):

<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', 'some code', 'auto');
</script>

app.component.ts:

import {AfterViewInit, Component, Inject, PLATFORM_ID} from '@angular/core';
import {isPlatformBrowser} from '@angular/common';
import {NavigationEnd, Router} from '@angular/router';

// declare google analytics
declare const ga: any;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {

  constructor(@Inject(PLATFORM_ID) private platformId: Object,
              private router: Router) {}


  ngAfterViewInit(): void {
    this.router.events.subscribe(event => {
      // I check for isPlatformBrowser here because I'm using Angular Universal, you may not need it
      if (event instanceof NavigationEnd && isPlatformBrowser(this.platformId)) {
        console.log(ga); // Just to make sure it's actually the ga function
        ga('set', 'page', event.urlAfterRedirects);
        ga('send', 'pageview');
      }
    });
  }
}

Let me know if this works for you as well. Have a nice day! :)


If @WeissDev answer don't work for you use setInterval to make sure its ready before using it.

  ngAfterViewInit() {
    this.initGoogleAnalyticsPageView()
  }

  private initGoogleAnalyticsPageView() {
    const interval = setInterval(() => {
      if ((window as any).ga && (window as any).ga.getAll) {
        this.router.events.subscribe(event => {
          const ga = (window as any).ga
          if (event instanceof NavigationEnd) {
            const tracker = ga.getAll()[0]
            tracker.set('page', event.urlAfterRedirects)
            tracker.send('pageview')
          }
        })
        clearInterval(interval)
      }
    }, 50)
  }