Reputation: 1389
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'); }
Upvotes: 75
Views: 73872
Reputation: 317
This solution seems to be the easiest:
After installing the types with:
npm install --save-dev @types/google.analytics
Update tsconfig.json
to use them:
// tsconfig.json
{
types: ["google.analytics"]
}
Upvotes: 1
Reputation: 6503
index.html file
<head>
.........
<script async src="https://www.googletagmanager.com/gtag/js?id=Google-Tracking-ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
</script>
......
</head>
AppComponent
import { Component, OnInit } from '@angular/core';
import {NavigationEnd, Router} from '@angular/router';
import {environment} from '../environments/environment';
// tslint:disable-next-line:ban-types
declare let gtag: Function;
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'angular-app';
constructor(public router: Router) {
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
gtag('config', Google-Tracking-ID, {'page_path': event.urlAfterRedirects});
}
});
}
}
Upvotes: 0
Reputation: 17
Do you have include the type in "types" compilerOptions of tsconfig.app.json?
I had the same problem and solved it including "google.analytics" (see, not "@ types/google.analytics") in tsconfig.app.json
Upvotes: -2
Reputation: 2943
You might be helped
app.component.ts
declare let gtag: Function;
this.router.events.subscribe(event => {
if(event instanceof NavigationEnd) {
gtag('config', '*****', {'page_path': event.urlAfterRedirects});
}
});
Upvotes: 0
Reputation: 8701
I'm surprised nobody here mentioned Google's Tag Manager yet (which is the version of the script that the Google Analytics console outputs for me in the last few years, whenever I add a new identity).
Here's a solution that I came up with today, which is a variation of the solutions already mentioned in the other answers, adapter to Google's Tag Manager script. I think it would be useful for people who migrated from ga()
to gtag()
(a migration that is recommended as far as I know).
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);
}
});
}
}
Prerequisites:
app.module.ts
.<router-outlet>
tag in its template), inject the AnalyticsService and call this.analytics.init()
as early as possible (e.g. ngOnInit)googleAnalyticsKey: 'UA-XXXXXXX-XXXX'
Upvotes: 60
Reputation: 83
I suggest embedding the Segment script into your index.html
and extend analytics library onto the window
object:
declare global {
interface Window { analytics: any; }
}
Then add tracking calls onto the (click)
event handler:
@Component({
selector: 'app-signup-btn',
template: `
<button (click)="trackEvent()">
Signup with Segment today!
</button>
`
})
export class SignupButtonComponent {
trackEvent() {
window.analytics.track('User Signup');
}
}
I’m the maintainer of https://github.com/segmentio/analytics-angular. I recommend checking it out if you want to solve this problem by using one singular API to manage your customer data, and be able to integrate into any other analytics tool (we support over 250+ destinations) - without writing any additional code. 🙂
Upvotes: 1
Reputation: 89
Personally I've found it quite easy simply:
<app-root>
in index.html (as shown above)In my app.component.ts
I've added this:
import {Component, OnInit} from '@angular/core';
import {NavigationEnd, Router} from '@angular/router';
import {Angulartics2GoogleAnalytics} from 'angulartics2/ga';
import {filter} from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(private ga: Angulartics2GoogleAnalytics,
private router: Router) {
}
ngOnInit() {
this.router.events
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe((event: NavigationEnd) =>
this.ga.pageTrack(event.urlAfterRedirects));
}
}
It's not much different to the above, but makes it much easier for testing.
Upvotes: 4
Reputation: 1041
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');
}
})
}
Upvotes: 7
Reputation: 2650
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);
}
Upvotes: 103
Reputation: 149
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.
Upvotes: 5
Reputation: 1244
(Works on Angular 5)
(Using @Laiso answer)
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
});
}
}
}
// ... 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);
Upvotes: 25