Search code examples
angulargoogle-analyticsangular-universalserver-side-rendering

How to add google analytics tracking with angular universal ssr


I was working on an angular universal SSR application and wanted to add Google Analytics tracking for page views but couldn't get it to work.

Most packages that are out there that I tried did not work with SSR because they tried to access the window/document directly.

Eventually I ended up with a fairly basic solution that I wanted to share.


Solution

  • By importing isPlatformBrowser you can specify code that you only want to execute on the client. Then you can append the appropriate script tags for google analytics tracking.

    import { isPlatformBrowser } from '@angular/common';
    import { Component, ElementRef, Inject, PLATFORM_ID, Renderer2 } from '@angular/core';
    import { environment } from '../../environments/environment';
    
    @Component({
      selector: 'app-google-analytics-gtag',
      template: '',
    })
    export class GoogleAnalyticsGTagComponent {
      trackingCode = environment.googleAnalyticsTrackingCode;
    
      constructor(
        @Inject(PLATFORM_ID) private readonly platformId: Object,
        private readonly renderer: Renderer2,
        private readonly el: ElementRef,
      ) {
        // BROWSER
        if (isPlatformBrowser(this.platformId)) {
          const script = this.renderer.createElement('script') as HTMLScriptElement;
          script.src = `//www.googletagmanager.com/gtag/js?id=${this.trackingCode}`;
          script.async = true;
          this.renderer.appendChild(this.el.nativeElement, script);
    
          const script2 = this.renderer.createElement('script') as HTMLScriptElement;
          const scriptBody = this.renderer.createText(`
            window.dataLayer = window.dataLayer || [];
            function gtag() {
              dataLayer.push(arguments);
            }
            gtag('js', new Date());
    
            gtag('config', '${this.trackingCode}');
          `);
          this.renderer.appendChild(script2, scriptBody);
          this.renderer.appendChild(this.el.nativeElement, script2);
        }
      }
    }