ngx-google-analytics
ngx-google-analytics copied to clipboard
If I use the above method, I am getting the below error on page load -
If I use the above method, I am getting the below error on page load -
Empty tracking code for Google Analytics. Make sure to provide one when initializing NgxGoogleAnalyticsModule.
In the environment files for which I do not want to have GA, I have entered as blank i.e GA: ''
Any idea how to resolve the error?
Originally posted by @aman-koco in https://github.com/maxandriani/ngx-google-analytics/issues/37#issuecomment-775147121
I solved the conditional initialization issue by creating an AnalyticsService
to manage ngx-google-analytics
configuration after application bootstrap, per the recommendation on #37 and the coding hints on #40, combined with some searching on how to get a ComponentRef
to the bootstrap component:
analytics.service.ts
import { ComponentRef, Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { GoogleAnalyticsInitializer, GoogleAnalyticsRouterInitializer, GoogleAnalyticsService, GtagFn, NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN, NGX_GTAG_FN } from 'ngx-google-analytics';
import { IGoogleAnalyticsSettings } from 'ngx-google-analytics/lib/interfaces/i-google-analytics-settings';
import { environment } from '../environments/environment';
@Injectable({providedIn: 'root'})
export class AnalyticsService {
private isInitialized: boolean;
public constructor(
@Inject(NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN) private googleAnalyticsSettingsToken: IGoogleAnalyticsSettings,
@Inject(NGX_GTAG_FN) private googleTagFunction: GtagFn,
@Inject(DOCUMENT) private document: Document,
public googleAnalyticsService: GoogleAnalyticsService,
) {
}
public initializeGoogleAnalytics(bootstrapComponent: ComponentRef<unknown>) {
if (environment.production && !this.isInitialized) {
Promise.all([
GoogleAnalyticsInitializer(this.googleAnalyticsSettingsToken, this.googleTagFunction, document)(),
GoogleAnalyticsRouterInitializer({}, this.googleAnalyticsService)(bootstrapComponent),
]).then(() => {
this.isInitialized = true;
}).catch((error: any) => {
this.isInitialized = false;
});
}
}
}
app.module.ts:
import { APP_BOOTSTRAP_LISTENER, ComponentRef, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN } from 'ngx-google-analytics';
import { environment } from './core/environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AnalyticsService } from './core/services/analytics.service';
@NgModule({
// Providers: Services and Values available to the Angular dependency injector
providers: [
{
provide: NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN,
useValue: {
trackingCode: environment.GoogleAnalyticsCode,
},
},
{
provide: APP_BOOTSTRAP_LISTENER,
multi: true,
useFactory: (analyticsService: AnalyticsService) => {
return (component: ComponentRef<unknown>) => {
analyticsService.initializeGoogleAnalytics(component);
};
},
deps: [AnalyticsService],
},
],
// Declarations: Components, Pipes, Directives belonging to this module & thereby available to others in this module
declarations: [
AppComponent,
],
// Imports: Other Modules whose Declarations should be available to components in this module
imports: [
// …
BrowserModule,
AppRoutingModule,
],
// Bootstrap: initial component to load when initializing application
bootstrap: [AppComponent],
})
/** Angular root module */
export class AppModule {
public constructor(
) {
}
}
@KeithGillette The only down side is you can not make any call to GoogleAnalyticsService before call the initialize functions :/ Currently I have no time to make new features on this lib because I've applied to a Certification Program and I also have a full-time job.
I think your guys could implement a hidden property on ConfigurationToken w/ a Subject<'initialized'|'consent'|'initialize'>(); And then refactory GoogleAnalyticsService and initialization functions to listen this observable.
The GoogleAnalyticsService should also stack the commands if ga is not initialized and than call all stacked commands.
Yes, @maxandriani, I realized that limitation, so in my application, I added methods to the AnalyticsService
from my previous reply that proxy the GoogleAnalytics.event
and GoogleAnalytics.exception
methods that I want to use, but guard against calls if (!this.isInitialized)
.
The ngx-google-analytics
library refactoring you describe makes sense and would be a great enhancement to easily enable delayed initialization for the multiple use cases of disabling outside of production, getting user consent, and perhaps also including an app-generated userId
for authenticated sessions, which is something I'm trying to figure out how to do now …
I'm trying this code but it doesn't detect the change of routes. The Analytics dashboard only shows the first page and no longer updates. Can you help me?
@KeithGillette did you figure out how to set userId
?
@andriipaziuk — Not in any automated way. I am only logging sign_up
& login
GA actions via the proxied event
method (described in my previous reply), which is called in the response handlers for the methods that invoke our application's UserRegister
and UserSignIn
mutations, both of which return a user object containing an id, so those calls pass in User
as category
and the user id as label
.
@KeithGillette how do you call the initializeGoogleAnalytics
method of AnalyticsService
then?
@xCryzed — The code sample in my original reply to this thread shows how initializeGoogleAnalytics
is called in the AppModule
provider creation.
@KeithGillette yes but what if I want to initialize it only when the user consent to the cookies?
@xCryzed — Does issue #40 referenced in my original reply address your question?