February 15, 2017
Tutorial: Angular 2 & Google Analytics with Event tracking
In this post, I’ll show you how to add Google Analytics to an Angular 2 project. There is really no need to use an extra library for including Analytics since the setup is really simple. I will use the Angular CLI to create a new project and add a sample routing between site-a and site-b. The pageviews will be tracked and transferred to Google Analytics. In addition, I’ll show how to submit evens to Analytics. For this purpose a service will be implemented. The full source code is published at Github. For each step there is a single commit, which is linked in the respective headline.
Preparations
I will start by creating a new project through the Angular CLI. If you already have a project then you can of course also use this.
1 2 |
ng new angular-analytics-example cd angular-analytics-example<br> |
Step 1: Add Typings for Google Analytics – (Code)
Since we want to use TypeScripts typing-features we have to install the required typings via npm.
1 |
npm install --save-dev @types/google.analytics |
Edit: There are currently some issues with those typings. Alternatively you can also declare ga yourself by adding this line to your code. You dont need the package @types/google.analytics then!
1 2 |
declare let ga: Function; |
Step 2: Add Example Routes – (Code)
Since the application is currently still empty, I will now create two new components (site-a and site-b). If you are working in an existing project, you can skip until step 4.
1 2 |
ng generate component site-a ng generate component site-b |
Step 3: Routing – (Code)
Now I must integrate the two created components with the routing. To do this, I first create the route configuration and then add the router-outlet to the AppComponent. Finally, the RouterModule must be imported in the AppModule. The route configuration will also be applied.
1 2 3 4 5 6 7 8 9 |
import {Routes} from "@angular/router"; import {SiteAComponent} from "./site-a/site-a.component"; import {SiteBComponent} from "./site-b/site-b.component"; export const appRoutes: Routes = [ {path: 'site-a', component: SiteAComponent}, {path: 'site-b', component: SiteBComponent}, {path: '**', redirectTo: '/site-a'} ]; |
1 |
<router-outlet></router-outlet> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { AppComponent } from './app.component'; import {SiteAComponent} from "./site-a/site-a.component"; import {SiteBComponent} from "./site-b/site-b.component"; import {RouterModule} from "@angular/router"; import {appRoutes} from "./app.routes"; @NgModule({ declarations: [ AppComponent, SiteAComponent, SiteBComponent ], imports: [ BrowserModule, FormsModule, HttpModule, RouterModule.forRoot(appRoutes), ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } |
Step 4: Add Google Analytics Tracking Code – (Code)
Now it’s time to include Analytics tracking code. Please note that we are in a single page application. Therefore, we must send the pageview manually. To do this, we add the tracking code to the index.html file and then remove the last line since it is responsible for transmitting the pageview.
To navigate at all, I have to add two links to my example, so that the view can be switched between site-a and site-b component. In order to be able to capture the pageviews manually, we will catch the router events in the AppComponent and forward them to Google Analytics.
Make sure to paste your own tracking code to the index.html and to remove the ga('send', 'pageview');
line!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!doctype html> <html> <head> <meta charset="utf-8"> <title>AngularAnalyticsEvent</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> </head> <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 from your tracking code // <- remove the last line like me </script> </body> </html> |
1 2 3 4 5 |
<p> site-a works! </p> <a routerLink="/site-b">to Site B</a> |
1 2 3 4 5 |
<p> site-b works! </p> <a routerLink="/site-a">to Site A</a> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import {Component} from "@angular/core"; import {Router, NavigationEnd} from "@angular/router"; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app works!'; constructor(public router: Router, public googleAnalyticsEventsService: GoogleAnalyticsEventsService) { this.router.events.subscribe(event => { if (event instanceof NavigationEnd) { ga('set', 'page', event.urlAfterRedirects); ga('send', 'pageview'); } }); } } |
That’s it already! Now the pageviews are sent to Google Analytics.
Step 5: Event Tracking with Angular – (Code)
In a real application, we can understand the user behavior even better if we submit some events to Google Analytics. In our example we will install a button. When the user clicks on it, an event is sent to Analytics. In order to make the re-usability possible, I have stored the required code in a service. We will add a button to our app components template and implement the method submitEvent in the related TypeScript code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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: eventCategory, eventLabel: eventLabel, eventAction: eventAction, eventValue: eventValue }); } } |
1 2 3 4 5 6 7 |
import {GoogleAnalyticsEventsService} from "./google-analytics-events.service"; // [...] providers: [ GoogleAnalyticsEventsService ], |
1 2 3 4 5 |
<router-outlet></router-outlet> <button (click)="submitEvent()"> Submit an Event </button> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import {Component} from "@angular/core"; import {Router, NavigationEnd} from "@angular/router"; import {GoogleAnalyticsEventsService} from "./google-analytics-events.service"; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app works!'; 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() { this.googleAnalyticsEventsService.emitEvent("testCategory", "testAction", "testLabel", 10); } } |
Congratulations, we have already realized an event tracking with Angular 2! Check if everything works as expected by using the real time overview in Google Analytics.
Working Page View Tracking:
Working Event Tracking:
Thank you, Can!
Most helpfull; works ike a charm!
Thanx the Code works …. I didnt try the event Catching yet
thank you sir absolutely helpful
Thanks for the post, it’s very useful.
Just one note, if you don’t use Angular CLI, it complains using wepback: “Cannot find name ‘ga’.”. It should be fine to include below code into the app component, and declare ga as ambient function.
…
// Declare ga function as ambient
declare let ga: Function;
…
Just add the reference path at the top of the file:
///
And into google-analytics-events.service.ts
add
declare let ga: Function;
I do not understand what you mean by adding the UA-ID of your tracking code
Where exactly does
declare let ga: Function;
go?This is awesome! Thanks 😀 works a treat.
Good one!
Thank you very much!
Would this work with angular 4?
Yes, It worked for me, I just had to declare “ga” to the app comp and the service
declare let ga: Function;
This tutorial also helped me to add Facebook pixels, thank you 🙂
You show the code in the body
But it would not work for me until I placed it where Google suggested
At the inside bottom of the head tag
Thanks for putting this online!
Thank you very much for this guide! Very helpful 🙂
BTW, Angular CLI will also trigger the “Cannot find name ‘ga’.” bug. The following line should be added *before* the deceleration (before @Component in app.component; before @Injectable in the service):
declare let ga: Function;
Thanks heaps mate, was getting disheartened when it wasnt playing ball.
works perfect. Thanks for the much needed solution
If you struggle, use
declare let ga: any;
Our Angular 4 application works fine on web. However when viewed on mobile, we get the below error on some mobiles.
Uncaught ReferenceError: ga is not defined
Thaks, but not working here:.
ERROR ReferenceError: ga is not defined
at GoogleAnalyticsService.webpackJsonp…/../../../../src/app/services/google-analytics/google-analytics.service.ts.GoogleAnalyticsService.emitEvent
any one can help me? please!
Good Share Can!!
Thanks @soywod too for ngOnDestroy & unsubscribe.
Quick question, how to add GA on some hyperlinks clicks in HTML files!
Thanks!
Hi,
Is there a way to have environment specific UA-ID’s in the snippet you have defined in index.html?
For instance ‘UA-XXXa’ for prod, and ‘UA-XXXb’ for dev.
It would be possible if you use angular cli where you have different environment files and you can define the ua-id there as variable.
However I would not recommend to do that. Since you have to duplicate many things in Analytics across all properties. Like Conversions, segments and so on. The correct approach is to use views in Google Analytics!
https://support.google.com/analytics/answer/1033162
Filter for localhost url for dev environment, prod url and so on.
I am unable to print the event in google analytics event console .though i am using the same code which is above mentioned in service file in angular 4 ,and also i would i like to thanks as my app is able to print the active components in analytics overview thanks a ton
Wow I haven’t tried it yet but it looks easy. You are a service to humanity.
One question: why is the “ga(‘create’ ..) call done in the index.html and not in the AppComponent? It seems that this way it will get executed before the object is constructed, but to preserve the order and make it more obvious why not just put the call in the AppComponent constructor?
Hello.
Thanks for this tutorial.
Followed through, but getting – ERROR Error: Uncaught (in promise): ReferenceError: ga is not defined
ReferenceError: ga is not defined when I check my console.
The angular CLI is not throwing any error though.
I am running Angular 4, and I have my application as a PWA.
Any help or suggestions would be gladly appreciated.
Thanks
Overall great tutorial and just using base angular. Nice!
Small remarks:
1. In step 4 remove public googleAnalyticsEventsService: GoogleAnalyticsEventsService from the constructor. It’s not yet needed there and little confusing.
2. As many stated Add -> declare const ga: Function; Everywhere you use the ga function to get it to build.
KR,
G
I am getting error in app.component.ts
” Cannot find name ‘ga’.
webpack: Failed to compile.”
Please suggest a resolution
Hi,
Just followed the example. But it seems Google changed the generated script into:
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag(‘js’, new Date());
gtag(‘config’, ‘UA-111111111-1’);
How to apply the ‘ga’ function?
Thanks in advanced.
Use the code from this site
https://developers.google.com/analytics/devguides/collection/analyticsjs/
and add your tracking ID
[…] Tutorial: Angular 2 & Google Analytics with Event tracking […]
Hi, want to help everybody, who have problem with ” ga is not defined “. It was because your web page change url to very early. Simple way to fix it – add setTimeout before call “ga function”
Hello,
Looks like at step 4, you present the step 4 as the final step because you do have a remark that says “That’s it already. Now the pages are sent to google”. But, in that step ( step 4) , you refer to the google analytics service which you are creating in step 5 and presenting as something optional. This confuses me big time.
In other words, the code up to step 4 should not work. The service code in step 5 is a must. and it must be part of step 4.
Am I getting this wrong?
Hi,
The Google Analytics typings actually works. Add this to the top of the file using
ga
:///
...
Please update the tutorial 😉
all my events are undefined in the real-time view
but as I log them I send the right data
public sendEvent(eventCategory: string,eventAction: string,eventLabel: string = null,eventValue: number = null) {
console.log(‘sending to ga ‘+eventCategory+’ ‘+eventAction+’ ‘+eventLabel+’ ‘+eventValue);
ga(‘send’, ‘event’, {
eventCategory: eventCategory,
eventLabel: eventLabel,
eventAction: eventAction,
eventValue: eventValue
});
}
thanks for sharing the information and code for google analytics tracking.
I want to track my other website posts and show the information of hits, visits, tracking information on my angular dashboard. I have google analytics and facebook tracking code and set the code on my website posts as well.
How to track the external links and show the data on angular application dashboard. this is my requirement.