diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 5320718087d..7c261ffa620 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,7 +1,6 @@ import { TestBed, ComponentFixture } from '@angular/core/testing'; import { AppComponent } from './app.component'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { RouterTestingModule } from '@angular/router/testing'; import { MediaChange, MediaObserver } from '@angular/flex-layout'; import { Observable, BehaviorSubject } from 'rxjs'; import { UtilService } from './services/util.service'; @@ -9,12 +8,13 @@ import { Announcement } from './domain/announcement'; import { ConfigService } from './services/config.service'; import { Config } from './domain/config'; import { environment } from '../environments/environment'; +import { provideRouter } from '@angular/router'; export class MockConfigService { private config$: BehaviorSubject = new BehaviorSubject(null); getAnnouncement(): Observable { - return Observable.create((observer) => { + return new Observable((observer) => { const announcement: Announcement = new Announcement(); announcement.visible = true; observer.next(announcement); @@ -25,6 +25,7 @@ export class MockConfigService { getConfig(): Observable { const config: Config = new Config(); config.googleAnalyticsId = 'UA-XXXXXX-1'; + config.googleTagManagerId = 'GTM-XXXXXXXX'; this.config$.next(config); return this.config$; } @@ -32,13 +33,16 @@ export class MockConfigService { getGoogleAnalyticsId(): string { return this.config$.getValue().googleAnalyticsId; } + + getGoogleTagManagerId(): string { + return this.config$.getValue().googleTagManagerId; + } } export class MockUtilService { getMobileMenuState(): Observable { - return Observable.create((observer) => { - const state: boolean = false; - observer.next(state); + return new Observable((observer) => { + observer.next(false); observer.complete(); }); } @@ -50,7 +54,7 @@ export class MockObservableMedia { } asObservable(): Observable { - return Observable.create((observer) => { + return new Observable((observer) => { observer.next(new MediaChange()); observer.complete(); }); @@ -64,13 +68,13 @@ describe('AppComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ + declarations: [AppComponent], providers: [ { provide: ConfigService, useClass: MockConfigService }, { provide: UtilService, useClass: MockUtilService }, - { provide: MediaObserver, useClass: MockObservableMedia } + { provide: MediaObserver, useClass: MockObservableMedia }, + provideRouter([]) ], - declarations: [AppComponent], - imports: [RouterTestingModule], schemas: [NO_ERRORS_SCHEMA] }); fixture = TestBed.createComponent(AppComponent); @@ -99,4 +103,11 @@ describe('AppComponent', () => { it(`should set Google Analytics tracking code`, () => { expect(component.googleAnalyticsId).toEqual('UA-XXXXXX-1'); }); + + it(`should set Google Tag manager tracking script`, () => { + const scriptElement = document.querySelector( + 'head > script[src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXXX"]' + ); + expect(scriptElement).toBeTruthy(); + }); }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 37f42d8c233..808b00ed04f 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -140,7 +140,11 @@ export class AppComponent { }); } - setGTagManager() { + private setGTagManager(): void { + const googleTagManagerId = this.configService.getGoogleTagManagerId(); + if (googleTagManagerId) { + this.activateGTM(window, document, 'script', 'dataLayer', googleTagManagerId); + } this.googleAnalyticsId = this.configService.getGoogleAnalyticsId(); if (this.googleAnalyticsId) { const gtagScript = this.document.createElement('script'); @@ -155,6 +159,17 @@ export class AppComponent { } } + private activateGTM(w, d, s, l, i): void { + w[l] = w[l] || []; + w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' }); + var f = d.getElementsByTagName(s)[0], + j = d.createElement(s), + dl = l != 'dataLayer' ? '&l=' + l : ''; + j.async = true; + j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; + f.parentNode.insertBefore(j, f); + } + fixScrollTop(ev: any) { const topElement = document.querySelector('.top-content'); if (!topElement) { diff --git a/src/app/domain/config.ts b/src/app/domain/config.ts index c067be2bee4..fb63eb9d760 100644 --- a/src/app/domain/config.ts +++ b/src/app/domain/config.ts @@ -1,6 +1,7 @@ export class Config { contextPath: string; googleAnalyticsId?: string; + googleTagManagerId?: string; googleClientId?: string; isGoogleClassroomEnabled?: boolean; microsoftClientId?: string; diff --git a/src/app/services/config.service.ts b/src/app/services/config.service.ts index 2bcda211b5e..071a839a3d4 100644 --- a/src/app/services/config.service.ts +++ b/src/app/services/config.service.ts @@ -19,14 +19,12 @@ export class ConfigService { retrieveConfig(): Observable { const headers = new HttpHeaders({ 'Cache-Control': 'no-cache' }); - return this.http - .get(this.userConfigUrl, { headers: headers }) - .pipe( - tap((config) => { - this.config$.next(config); - this.timeDiff = Date.now() - config.currentTime; - }) - ); + return this.http.get(this.userConfigUrl, { headers: headers }).pipe( + tap((config) => { + this.config$.next(config); + this.timeDiff = Date.now() - config.currentTime; + }) + ); } getContextPath() { @@ -45,6 +43,10 @@ export class ConfigService { return this.config$.getValue().googleAnalyticsId; } + getGoogleTagManagerId() { + return this.config$.getValue().googleTagManagerId; + } + getGoogleClientId() { return this.config$.getValue().googleClientId; }