Injecting the Service into Our Pages

With the service initialized, we can now capture events on our pages.

As stated in the previous post, Google Analytics was designed to provide insights on user experience based on user interactions. It is not so much an Application Performance Monitor (APM) like Application Insights or New Relic (while it can provide some extremely basic metrics), but rather to assist internal teams with increasing conversion rates and improving customer acquisition (and retention). To this end, we can track those interactions and log them in Google Analytics. In this post, we’re not going to cover goal setting, funnels, metrics, etc. We’re simply going to track a few events. However, the following principles can be used to accomplish the same purpose.

Add Event Logging Method

For our pages to log an event to Google Analytics, we’ll need to expose the functionality in our GoogleAnalyticsService. Open your src/app/google-analytics.service.ts file and add the following function:

logEvent(event, category, label, value) {
  gtag('event', event, {
    event_category: category,
    event_label: label,
    value: value
  });

  console.log('gtag event captured...');
}

There’s really nothing special about this method. It simply takes a generic event, category, label, and value and then registers that information with Google Analytics.

You can see the full, completed source of google-analytics.service.ts here.

Quick and Dirty

If you remember from the “Setup” section from page 1, I created a few pages. On both First Page and Second Page I created a simple button, and I bound it to a click event.

<button (click)="click()">Click Me!</button>

View the source (for First Pagehere.

In my page’s TypeScript file, I’ve injected my GoogleAnalyticsService and, using the bound click event, I call the service’s logEvent method that we added in the previous section.

The following is the initial source for my first-page.component.ts:

import { Component, OnInit } from '@angular/core';
import { GoogleAnalyticsService } from '../google-analytics.service';

@Component({
  selector: 'app-first-page',
  templateUrl: './first-page.component.html',
  styleUrls: ['./first-page.component.scss']
})
export class FirstPageComponent implements OnInit {
  private _clickCnt = 0;

  constructor(protected $gaService: GoogleAnalyticsService) { }

  ngOnInit() {
  }

  click() {
    this.$gaService.logEvent('click', 'Button', 'First Page', ++this._clickCnt);
    console.log(`Button clicked ${this._clickCnt} times.`);
    console.log('Click for "First Page" sent!');
  }
}

The service is injected into my component (line 12) and it’s logEvent method is called when the user clicks the button (line 18).

Now, this approach works. BUT, I would have to inject the service into every component page.  A better approach would be to simply inject the GoogleAnalyticsService once, which is what the next section demonstrates.

A Better Approach

Instead of injecting the service on every page, it is sometimes much simpler to inject the service into a base page/component and then inherit from that component.

Let’s create our base component (e.g. ng g c base-component). This will create the necessary component file and its unit tests specification file. In the component file, we’ll pretty much scrub all the UI references and add our Google Analytics service:

import { Component, OnInit } from '@angular/core';
import { GoogleAnalyticsService } from '../google-analytics.service';

@Component({
  template: '',
})
export class BasePageComponent implements OnInit {

  constructor(protected $gaService: GoogleAnalyticsService) { }

  ngOnInit() {  }

}

Notice, we’ve removed the templateUrl and stylesUrls properties from the @Component attribute, and we’ve replaced them with an empty template property (which is required). (You can also delete the base-page.component.html and base-page.component.scss files if you’d like as they are no longer needed.) A copy of the base-page.component.ts file can be found in the repository.

Now, instead of injecting the service into each component, we’ll simple modify our page components to inherit from our base component. The following is First Page‘s final source code.

import { Component, OnInit } from '@angular/core';
import { BasePageComponent } from '../base-page/base-page.component';

@Component({
  selector: 'app-first-page',
  templateUrl: './first-page.component.html',
  styleUrls: ['./first-page.component.scss']
})
export class FirstPageComponent extends BasePageComponent implements OnInit {
  private _clickCnt = 0;

  ngOnInit() {
  }

  click() {
    this.$gaService.logEvent('click', 'Button', 'First Page', ++this._clickCnt);
    console.log(`Button clicked ${this._clickCnt} times.`);
    console.log('Click for "First Page" sent!');
  }
}

Notice, the changes:

  1. Instead of importing the GoogleAnalyticsService directly, we’re importing the BasePageComponent
  2. We’ve removed our component’s constructor (it’s no longer needed in this example)
  3. We’ve updated our FirstPageComponent class to extend BasePageComponent

The final version of the First Page‘s source can be found here.

(NOTE: As mentioned in the previous post, one downside of using Google Analytics is that the values for a specific event are summed in the daily reports. So, if the button on the page is clicked 3 times, the final event report will show 6 (1 for the first click + 2 for the second + 3 for the third) for the value. If you want to track values for individual users, sessions, clicks, etc., then you’ll need to configure metrics in Google Analytics.)

With your click event wired up, go ahead and run your application again (remember, with the --prod flag). You’ll then begin to see events being logged in realtime on your Google Analytics dashboard.

Conclusion

Like the previous post, we’ve added Google Analytics to our Angular application. However, in this post, we’ve accomplished that by creating and injecting a service. This is considered the better, “more Angular” way to perform this.

Again, for the full source code to this project, check out my GitHub blog demos repository.