[CST-6753] Maintain compatibility with version 3

This commit is contained in:
Giuseppe Digilio
2022-09-28 13:30:22 +02:00
parent f3f89b3dc1
commit 171ac62beb
4 changed files with 117 additions and 38 deletions

View File

@@ -1,4 +1,4 @@
import { Angulartics2GoogleTagManager } from 'angulartics2'; import { Angulartics2GoogleAnalytics, Angulartics2GoogleTagManager } from 'angulartics2';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { GoogleAnalyticsService } from './google-analytics.service'; import { GoogleAnalyticsService } from './google-analytics.service';
@@ -10,11 +10,13 @@ import { GOOGLE_ANALYTICS_KLARO_KEY } from '../shared/cookies/klaro-configuratio
describe('GoogleAnalyticsService', () => { describe('GoogleAnalyticsService', () => {
const trackingIdProp = 'google.analytics.key'; const trackingIdProp = 'google.analytics.key';
const trackingIdTestValue = 'mock-tracking-id'; const trackingIdV4TestValue = 'G-mock-tracking-id';
const trackingIdV3TestValue = 'UA-mock-tracking-id';
const innerHTMLTestValue = 'mock-script-inner-html'; const innerHTMLTestValue = 'mock-script-inner-html';
const srcTestValue = 'mock-script-src'; const srcTestValue = 'mock-script-src';
let service: GoogleAnalyticsService; let service: GoogleAnalyticsService;
let angularticsSpy: Angulartics2GoogleTagManager; let googleAnalyticsSpy: Angulartics2GoogleAnalytics;
let googleTagManagerSpy: Angulartics2GoogleTagManager;
let configSpy: ConfigurationDataService; let configSpy: ConfigurationDataService;
let klaroServiceSpy: jasmine.SpyObj<KlaroService>; let klaroServiceSpy: jasmine.SpyObj<KlaroService>;
let scriptElementMock: any; let scriptElementMock: any;
@@ -32,7 +34,10 @@ describe('GoogleAnalyticsService', () => {
}); });
beforeEach(() => { beforeEach(() => {
angularticsSpy = jasmine.createSpyObj('Angulartics2GoogleTagManager', [ googleAnalyticsSpy = jasmine.createSpyObj('Angulartics2GoogleAnalytics', [
'startTracking',
]);
googleTagManagerSpy = jasmine.createSpyObj('Angulartics2GoogleTagManager', [
'startTracking', 'startTracking',
]); ]);
@@ -40,7 +45,7 @@ describe('GoogleAnalyticsService', () => {
'getSavedPreferences': jasmine.createSpy('getSavedPreferences') 'getSavedPreferences': jasmine.createSpy('getSavedPreferences')
}); });
configSpy = createConfigSuccessSpy(trackingIdTestValue); configSpy = createConfigSuccessSpy(trackingIdV4TestValue);
scriptElementMock = { scriptElementMock = {
set src(newVal) { /* noop */ }, set src(newVal) { /* noop */ },
@@ -66,7 +71,7 @@ describe('GoogleAnalyticsService', () => {
GOOGLE_ANALYTICS_KLARO_KEY: true GOOGLE_ANALYTICS_KLARO_KEY: true
})); }));
service = new GoogleAnalyticsService(angularticsSpy, klaroServiceSpy, configSpy, documentSpy ); service = new GoogleAnalyticsService(googleAnalyticsSpy, googleTagManagerSpy, klaroServiceSpy, configSpy, documentSpy );
}); });
it('should be created', () => { it('should be created', () => {
@@ -90,7 +95,7 @@ describe('GoogleAnalyticsService', () => {
GOOGLE_ANALYTICS_KLARO_KEY: true GOOGLE_ANALYTICS_KLARO_KEY: true
})); }));
service = new GoogleAnalyticsService(angularticsSpy, klaroServiceSpy, configSpy, documentSpy); service = new GoogleAnalyticsService(googleAnalyticsSpy, googleTagManagerSpy, klaroServiceSpy, configSpy, documentSpy);
}); });
it('should NOT add a script to the body', () => { it('should NOT add a script to the body', () => {
@@ -100,7 +105,8 @@ describe('GoogleAnalyticsService', () => {
it('should NOT start tracking', () => { it('should NOT start tracking', () => {
service.addTrackingIdToPage(); service.addTrackingIdToPage();
expect(angularticsSpy.startTracking).toHaveBeenCalledTimes(0); expect(googleAnalyticsSpy.startTracking).toHaveBeenCalledTimes(0);
expect(googleTagManagerSpy.startTracking).toHaveBeenCalledTimes(0);
}); });
}); });
@@ -111,7 +117,7 @@ describe('GoogleAnalyticsService', () => {
klaroServiceSpy.getSavedPreferences.and.returnValue(of({ klaroServiceSpy.getSavedPreferences.and.returnValue(of({
[GOOGLE_ANALYTICS_KLARO_KEY]: true [GOOGLE_ANALYTICS_KLARO_KEY]: true
})); }));
service = new GoogleAnalyticsService(angularticsSpy, klaroServiceSpy, configSpy, documentSpy); service = new GoogleAnalyticsService(googleAnalyticsSpy, googleTagManagerSpy, klaroServiceSpy, configSpy, documentSpy);
}); });
it('should NOT add a script to the body', () => { it('should NOT add a script to the body', () => {
@@ -121,15 +127,16 @@ describe('GoogleAnalyticsService', () => {
it('should NOT start tracking', () => { it('should NOT start tracking', () => {
service.addTrackingIdToPage(); service.addTrackingIdToPage();
expect(angularticsSpy.startTracking).toHaveBeenCalledTimes(0); expect(googleAnalyticsSpy.startTracking).toHaveBeenCalledTimes(0);
expect(googleTagManagerSpy.startTracking).toHaveBeenCalledTimes(0);
}); });
}); });
describe('when google-analytics cookie preferences are not existing', () => { describe('when google-analytics cookie preferences are not existing', () => {
beforeEach(() => { beforeEach(() => {
configSpy = createConfigSuccessSpy(trackingIdTestValue); configSpy = createConfigSuccessSpy(trackingIdV4TestValue);
klaroServiceSpy.getSavedPreferences.and.returnValue(of({})); klaroServiceSpy.getSavedPreferences.and.returnValue(of({}));
service = new GoogleAnalyticsService(angularticsSpy, klaroServiceSpy, configSpy, documentSpy); service = new GoogleAnalyticsService(googleAnalyticsSpy, googleTagManagerSpy, klaroServiceSpy, configSpy, documentSpy);
}); });
it('should NOT add a script to the body', () => { it('should NOT add a script to the body', () => {
@@ -139,18 +146,19 @@ describe('GoogleAnalyticsService', () => {
it('should NOT start tracking', () => { it('should NOT start tracking', () => {
service.addTrackingIdToPage(); service.addTrackingIdToPage();
expect(angularticsSpy.startTracking).toHaveBeenCalledTimes(0); expect(googleAnalyticsSpy.startTracking).toHaveBeenCalledTimes(0);
expect(googleTagManagerSpy.startTracking).toHaveBeenCalledTimes(0);
}); });
}); });
describe('when google-analytics cookie preferences are set to false', () => { describe('when google-analytics cookie preferences are set to false', () => {
beforeEach(() => { beforeEach(() => {
configSpy = createConfigSuccessSpy(trackingIdTestValue); configSpy = createConfigSuccessSpy(trackingIdV4TestValue);
klaroServiceSpy.getSavedPreferences.and.returnValue(of({ klaroServiceSpy.getSavedPreferences.and.returnValue(of({
[GOOGLE_ANALYTICS_KLARO_KEY]: false [GOOGLE_ANALYTICS_KLARO_KEY]: false
})); }));
service = new GoogleAnalyticsService(angularticsSpy, klaroServiceSpy, configSpy, documentSpy); service = new GoogleAnalyticsService(googleAnalyticsSpy, googleTagManagerSpy, klaroServiceSpy, configSpy, documentSpy);
}); });
it('should NOT add a script to the body', () => { it('should NOT add a script to the body', () => {
@@ -160,18 +168,19 @@ describe('GoogleAnalyticsService', () => {
it('should NOT start tracking', () => { it('should NOT start tracking', () => {
service.addTrackingIdToPage(); service.addTrackingIdToPage();
expect(angularticsSpy.startTracking).toHaveBeenCalledTimes(0); expect(googleAnalyticsSpy.startTracking).toHaveBeenCalledTimes(0);
expect(googleTagManagerSpy.startTracking).toHaveBeenCalledTimes(0);
}); });
}); });
describe('when both google-analytics cookie and the tracking id are non-empty', () => { describe('when both google-analytics cookie and the tracking v4 id are non-empty', () => {
beforeEach(() => { beforeEach(() => {
configSpy = createConfigSuccessSpy(trackingIdTestValue); configSpy = createConfigSuccessSpy(trackingIdV4TestValue);
klaroServiceSpy.getSavedPreferences.and.returnValue(of({ klaroServiceSpy.getSavedPreferences.and.returnValue(of({
[GOOGLE_ANALYTICS_KLARO_KEY]: true [GOOGLE_ANALYTICS_KLARO_KEY]: true
})); }));
service = new GoogleAnalyticsService(angularticsSpy, klaroServiceSpy, configSpy, documentSpy); service = new GoogleAnalyticsService(googleAnalyticsSpy, googleTagManagerSpy, klaroServiceSpy, configSpy, documentSpy);
}); });
it('should create a script tag whose innerHTML contains the tracking id', () => { it('should create a script tag whose innerHTML contains the tracking id', () => {
@@ -183,10 +192,10 @@ describe('GoogleAnalyticsService', () => {
expect(documentSpy.createElement('script')).toBe(scriptElementMock); expect(documentSpy.createElement('script')).toBe(scriptElementMock);
expect(srcSpy).toHaveBeenCalledTimes(1); expect(srcSpy).toHaveBeenCalledTimes(1);
expect(srcSpy.calls.argsFor(0)[0]).toContain(trackingIdTestValue); expect(srcSpy.calls.argsFor(0)[0]).toContain(trackingIdV4TestValue);
expect(innerHTMLSpy).toHaveBeenCalledTimes(1); expect(innerHTMLSpy).toHaveBeenCalledTimes(1);
expect(innerHTMLSpy.calls.argsFor(0)[0]).toContain(trackingIdTestValue); expect(innerHTMLSpy.calls.argsFor(0)[0]).toContain(trackingIdV4TestValue);
}); });
it('should add a script to the body', () => { it('should add a script to the body', () => {
@@ -196,9 +205,46 @@ describe('GoogleAnalyticsService', () => {
it('should start tracking', () => { it('should start tracking', () => {
service.addTrackingIdToPage(); service.addTrackingIdToPage();
expect(angularticsSpy.startTracking).toHaveBeenCalledTimes(1); expect(googleAnalyticsSpy.startTracking).not.toHaveBeenCalled();
expect(googleTagManagerSpy.startTracking).toHaveBeenCalledTimes(1);
}); });
}); });
describe('when both google-analytics cookie and the tracking id v3 are non-empty', () => {
beforeEach(() => {
configSpy = createConfigSuccessSpy(trackingIdV3TestValue);
klaroServiceSpy.getSavedPreferences.and.returnValue(of({
[GOOGLE_ANALYTICS_KLARO_KEY]: true
}));
service = new GoogleAnalyticsService(googleAnalyticsSpy, googleTagManagerSpy, klaroServiceSpy, configSpy, documentSpy);
});
it('should create a script tag whose innerHTML contains the tracking id', () => {
service.addTrackingIdToPage();
expect(documentSpy.createElement).toHaveBeenCalledTimes(1);
expect(documentSpy.createElement).toHaveBeenCalledWith('script');
// sanity check
expect(documentSpy.createElement('script')).toBe(scriptElementMock);
expect(innerHTMLSpy).toHaveBeenCalledTimes(1);
expect(innerHTMLSpy.calls.argsFor(0)[0]).toContain(trackingIdV3TestValue);
});
it('should add a script to the body', () => {
service.addTrackingIdToPage();
expect(bodyElementSpy.appendChild).toHaveBeenCalledTimes(1);
});
it('should start tracking', () => {
service.addTrackingIdToPage();
expect(googleAnalyticsSpy.startTracking).toHaveBeenCalledTimes(1);
expect(googleTagManagerSpy.startTracking).not.toHaveBeenCalled();
}); });
}); });
});
});
}); });

View File

@@ -1,7 +1,7 @@
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { Inject, Injectable } from '@angular/core'; import { Inject, Injectable } from '@angular/core';
import { Angulartics2GoogleTagManager } from 'angulartics2'; import { Angulartics2GoogleAnalytics, Angulartics2GoogleTagManager } from 'angulartics2';
import { combineLatest } from 'rxjs'; import { combineLatest } from 'rxjs';
import { ConfigurationDataService } from '../core/data/configuration-data.service'; import { ConfigurationDataService } from '../core/data/configuration-data.service';
@@ -18,8 +18,8 @@ import { GOOGLE_ANALYTICS_KLARO_KEY } from '../shared/cookies/klaro-configuratio
export class GoogleAnalyticsService { export class GoogleAnalyticsService {
constructor( constructor(
// private angulartics: Angulartics2GoogleAnalytics, private googleAnalytics: Angulartics2GoogleAnalytics,
private angulartics: Angulartics2GoogleTagManager, private googleTagManager: Angulartics2GoogleTagManager,
private klaroService: KlaroService, private klaroService: KlaroService,
private configService: ConfigurationDataService, private configService: ConfigurationDataService,
@Inject(DOCUMENT) private document: any, @Inject(DOCUMENT) private document: any,
@@ -36,7 +36,9 @@ export class GoogleAnalyticsService {
const googleKey$ = this.configService.findByPropertyName('google.analytics.key').pipe( const googleKey$ = this.configService.findByPropertyName('google.analytics.key').pipe(
getFirstCompletedRemoteData(), getFirstCompletedRemoteData(),
); );
combineLatest([this.klaroService.getSavedPreferences(), googleKey$]) const preferences$ = this.klaroService.getSavedPreferences();
combineLatest([preferences$, googleKey$])
.subscribe(([preferences, remoteData]) => { .subscribe(([preferences, remoteData]) => {
// make sure user has accepted Google Analytics consents // make sure user has accepted Google Analytics consents
if (isEmpty(preferences) || isEmpty(preferences[GOOGLE_ANALYTICS_KLARO_KEY]) || !preferences[GOOGLE_ANALYTICS_KLARO_KEY]) { if (isEmpty(preferences) || isEmpty(preferences[GOOGLE_ANALYTICS_KLARO_KEY]) || !preferences[GOOGLE_ANALYTICS_KLARO_KEY]) {
@@ -55,6 +57,8 @@ export class GoogleAnalyticsService {
return; return;
} }
if (this.isGTagVersion(trackingId)) {
// add GTag snippet to page // add GTag snippet to page
const keyScript = this.document.createElement('script'); const keyScript = this.document.createElement('script');
keyScript.src = `https://www.googletagmanager.com/gtag/js?id=${trackingId}`; keyScript.src = `https://www.googletagmanager.com/gtag/js?id=${trackingId}`;
@@ -66,7 +70,24 @@ export class GoogleAnalyticsService {
this.document.body.appendChild(libScript); this.document.body.appendChild(libScript);
// start tracking // start tracking
this.angulartics.startTracking(); this.googleTagManager.startTracking();
} else {
// add trackingId snippet to page
const keyScript = this.document.createElement('script');
keyScript.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', '${trackingId}', 'auto');`;
this.document.body.appendChild(keyScript);
// start tracking
this.googleAnalytics.startTracking();
}
}); });
} }
private isGTagVersion(trackingId: string) {
return trackingId && trackingId.startsWith('G-');
}
} }

View File

@@ -15,13 +15,17 @@ import { AppModule } from '../../app/app.module';
import { ClientCookieService } from '../../app/core/services/client-cookie.service'; import { ClientCookieService } from '../../app/core/services/client-cookie.service';
import { CookieService } from '../../app/core/services/cookie.service'; import { CookieService } from '../../app/core/services/cookie.service';
import { AuthService } from '../../app/core/auth/auth.service'; import { AuthService } from '../../app/core/auth/auth.service';
import { Angulartics2RouterlessModule } from 'angulartics2'; import { Angulartics2GoogleTagManager, Angulartics2RouterlessModule } from 'angulartics2';
import { SubmissionService } from '../../app/submission/submission.service'; import { SubmissionService } from '../../app/submission/submission.service';
import { StatisticsModule } from '../../app/statistics/statistics.module'; import { StatisticsModule } from '../../app/statistics/statistics.module';
import { BrowserKlaroService } from '../../app/shared/cookies/browser-klaro.service'; import { BrowserKlaroService } from '../../app/shared/cookies/browser-klaro.service';
import { KlaroService } from '../../app/shared/cookies/klaro.service'; import { KlaroService } from '../../app/shared/cookies/klaro.service';
import { HardRedirectService } from '../../app/core/services/hard-redirect.service'; import { HardRedirectService } from '../../app/core/services/hard-redirect.service';
import { BrowserHardRedirectService, locationProvider, LocationToken } from '../../app/core/services/browser-hard-redirect.service'; import {
BrowserHardRedirectService,
locationProvider,
LocationToken
} from '../../app/core/services/browser-hard-redirect.service';
import { LocaleService } from '../../app/core/locale/locale.service'; import { LocaleService } from '../../app/core/locale/locale.service';
import { GoogleAnalyticsService } from '../../app/statistics/google-analytics.service'; import { GoogleAnalyticsService } from '../../app/statistics/google-analytics.service';
import { AuthRequestService } from '../../app/core/auth/auth-request.service'; import { AuthRequestService } from '../../app/core/auth/auth-request.service';
@@ -95,6 +99,10 @@ export function getRequest(transferState: TransferState): any {
provide: GoogleAnalyticsService, provide: GoogleAnalyticsService,
useClass: GoogleAnalyticsService, useClass: GoogleAnalyticsService,
}, },
{
provide: Angulartics2GoogleTagManager,
useClass: Angulartics2GoogleTagManager
},
{ {
provide: AuthRequestService, provide: AuthRequestService,
useClass: BrowserAuthRequestService, useClass: BrowserAuthRequestService,

View File

@@ -6,7 +6,7 @@ import { ServerModule, ServerTransferStateModule } from '@angular/platform-serve
import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { Angulartics2, Angulartics2GoogleTagManager } from 'angulartics2'; import { Angulartics2, Angulartics2GoogleAnalytics, Angulartics2GoogleTagManager } from 'angulartics2';
import { AppComponent } from '../../app/app.component'; import { AppComponent } from '../../app/app.component';
@@ -58,6 +58,10 @@ export function createTranslateLoader(transferState: TransferState) {
provide: Angulartics2, provide: Angulartics2,
useClass: Angulartics2Mock useClass: Angulartics2Mock
}, },
{
provide: Angulartics2GoogleAnalytics,
useClass: AngularticsProviderMock
},
{ {
provide: Angulartics2GoogleTagManager, provide: Angulartics2GoogleTagManager,
useClass: AngularticsProviderMock useClass: AngularticsProviderMock