From 2225c2e4287f1d74b7f16d155e9a06cd7b91661d Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Wed, 5 Feb 2025 11:37:00 +0100 Subject: [PATCH 1/3] [CST-18964] add matomo integration --- package-lock.json | 13 +++++ package.json | 1 + src/app/core/shared/search/search.service.ts | 9 +++- .../shared/cookies/browser-orejime.service.ts | 10 +++- .../shared/cookies/orejime-configuration.ts | 15 ++++++ src/app/statistics/matomo.service.spec.ts | 16 ++++++ src/app/statistics/matomo.service.ts | 52 +++++++++++++++++++ src/app/statistics/mock-matomo-tracker.ts | 3 ++ src/assets/i18n/en.json5 | 4 ++ src/assets/i18n/it.json5 | 7 +++ src/config/app-config.interface.ts | 2 + src/config/default-app-config.ts | 3 ++ src/config/matomo-config.interface.ts | 9 ++++ src/modules/app/browser-app.config.ts | 12 +++++ src/modules/app/browser-init.service.ts | 7 +++ src/modules/app/server-app.config.ts | 6 +++ 16 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 src/app/statistics/matomo.service.spec.ts create mode 100644 src/app/statistics/matomo.service.ts create mode 100644 src/app/statistics/mock-matomo-tracker.ts create mode 100644 src/config/matomo-config.interface.ts diff --git a/package-lock.json b/package-lock.json index b75ddc9ccf0..7c22e2d799f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,6 +66,7 @@ "ng2-file-upload": "5.0.0", "ng2-nouislider": "^2.0.0", "ngx-infinite-scroll": "^16.0.0", + "ngx-matomo-client": "^6.4.1", "ngx-pagination": "6.0.3", "ngx-skeleton-loader": "^9.0.0", "ngx-ui-switch": "^14.1.0", @@ -16935,6 +16936,18 @@ "@angular/forms": ">=10.0.0" } }, + "node_modules/ngx-matomo-client": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/ngx-matomo-client/-/ngx-matomo-client-6.4.1.tgz", + "integrity": "sha512-GRriCGW0ULCg9oSZw3ule+o9esELVVJTJ0Z99/zYKGjlyrrHLn5a1e0GSdgICubo59gP1cg9NwsOC0BH7oio9A==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^17.0.0 || ^18.0.0", + "@angular/core": "^17.0.0 || ^18.0.0" + } + }, "node_modules/ngx-pagination": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/ngx-pagination/-/ngx-pagination-6.0.3.tgz", diff --git a/package.json b/package.json index 9e72a4cc9da..0c8ddd5ac9d 100644 --- a/package.json +++ b/package.json @@ -153,6 +153,7 @@ "ng2-file-upload": "5.0.0", "ng2-nouislider": "^2.0.0", "ngx-infinite-scroll": "^16.0.0", + "ngx-matomo-client": "^6.4.1", "ngx-pagination": "6.0.3", "ngx-skeleton-loader": "^9.0.0", "ngx-ui-switch": "^14.1.0", diff --git a/src/app/core/shared/search/search.service.ts b/src/app/core/shared/search/search.service.ts index 60a2da6af1e..7afefd96598 100644 --- a/src/app/core/shared/search/search.service.ts +++ b/src/app/core/shared/search/search.service.ts @@ -1,6 +1,7 @@ /* eslint-disable max-classes-per-file */ import { Injectable } from '@angular/core'; import { Angulartics2 } from 'angulartics2'; +import { MatomoTracker } from 'ngx-matomo-client'; import { BehaviorSubject, combineLatest as observableCombineLatest, @@ -112,6 +113,7 @@ export class SearchService { private paginationService: PaginationService, private searchConfigurationService: SearchConfigurationService, private angulartics2: Angulartics2, + private matomoTracker: MatomoTracker, ) { this.searchDataService = new SearchDataService(); } @@ -367,7 +369,7 @@ export class SearchService { const appliedFilter = appliedFilters[i]; filters.push(appliedFilter); } - this.angulartics2.eventTrack.next({ + const searchTrackObject = { action: 'search', properties: { searchOptions: config, @@ -384,7 +386,10 @@ export class SearchService { filters: filters, clickedObject, }, - }); + }; + + this.matomoTracker.trackSiteSearch(config.query, config.scope, searchQueryResponse.pageInfo.totalElements, searchTrackObject); + this.angulartics2.eventTrack.next(searchTrackObject); } /** diff --git a/src/app/shared/cookies/browser-orejime.service.ts b/src/app/shared/cookies/browser-orejime.service.ts index a2c66f95004..ba4a61fa2cb 100644 --- a/src/app/shared/cookies/browser-orejime.service.ts +++ b/src/app/shared/cookies/browser-orejime.service.ts @@ -39,6 +39,7 @@ import { OrejimeService } from './orejime.service'; import { ANONYMOUS_STORAGE_NAME_OREJIME, getOrejimeConfiguration, + MATOMO_OREJIME_KEY, } from './orejime-configuration'; /** @@ -133,8 +134,10 @@ export class BrowserOrejimeService extends OrejimeService { ), ); - const appsToHide$: Observable = observableCombineLatest([hideGoogleAnalytics$, hideRegistrationVerification$]).pipe( - map(([hideGoogleAnalytics, hideRegistrationVerification]) => { + const hideMatomo$ = observableOf(!(environment.matomo?.trackerUrl && environment.matomo?.siteId)); + + const appsToHide$: Observable = observableCombineLatest([hideGoogleAnalytics$, hideRegistrationVerification$, hideMatomo$]).pipe( + map(([hideGoogleAnalytics, hideRegistrationVerification, hideMatomo]) => { const appsToHideArray: string[] = []; if (hideGoogleAnalytics) { appsToHideArray.push(this.GOOGLE_ANALYTICS_SERVICE_NAME); @@ -142,6 +145,9 @@ export class BrowserOrejimeService extends OrejimeService { if (hideRegistrationVerification) { appsToHideArray.push(CAPTCHA_NAME); } + if (hideMatomo) { + appsToHideArray.push(MATOMO_OREJIME_KEY); + } return appsToHideArray; }), ); diff --git a/src/app/shared/cookies/orejime-configuration.ts b/src/app/shared/cookies/orejime-configuration.ts index 8e99ff30b2c..76499fce7db 100644 --- a/src/app/shared/cookies/orejime-configuration.ts +++ b/src/app/shared/cookies/orejime-configuration.ts @@ -19,6 +19,10 @@ export const ANONYMOUS_STORAGE_NAME_OREJIME = 'orejime-anonymous'; export const GOOGLE_ANALYTICS_OREJIME_KEY = 'google-analytics'; +export const MATOMO_OREJIME_KEY = 'matomo'; + +export const MATOMO_COOKIE = 'dsMatomo'; + /** * Orejime configuration * For more information see https://github.com/empreinte-digitale/orejime @@ -134,6 +138,17 @@ export function getOrejimeConfiguration(_window: NativeWindowRef): any { HAS_AGREED_END_USER, ], }, + { + name: MATOMO_OREJIME_KEY, + purposes: ['statistical'], + required: false, + cookies: [ + MATOMO_COOKIE, + ], + callback: (consent: boolean) => { + _window?.nativeWindow.changeMatomoConsent(consent); + }, + }, { name: GOOGLE_ANALYTICS_OREJIME_KEY, purposes: ['statistical'], diff --git a/src/app/statistics/matomo.service.spec.ts b/src/app/statistics/matomo.service.spec.ts new file mode 100644 index 00000000000..4c84d26f446 --- /dev/null +++ b/src/app/statistics/matomo.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { MatomoService } from './matomo.service'; + +describe('MatomoService', () => { + let service: MatomoService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(MatomoService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/statistics/matomo.service.ts b/src/app/statistics/matomo.service.ts new file mode 100644 index 00000000000..d507bb0a505 --- /dev/null +++ b/src/app/statistics/matomo.service.ts @@ -0,0 +1,52 @@ +import { + inject, + Injectable, +} from '@angular/core'; +import { + MatomoInitializerService, + MatomoTracker, +} from 'ngx-matomo-client'; + +import { environment } from '../../environments/environment'; +import { NativeWindowService } from '../core/services/window.service'; +import { OrejimeService } from '../shared/cookies/orejime.service'; + +@Injectable({ + providedIn: 'root', +}) +export class MatomoService { + + matomoInitializer = inject(MatomoInitializerService); + matomoTracker = inject(MatomoTracker); + orejimeService = inject(OrejimeService); + _window = inject(NativeWindowService); + + init() { + if (this._window.nativeWindow) { + this._window.nativeWindow.changeMatomoConsent = this.changeMatomoConsent; + } + + if (environment.production) { + const preferences$ = this.orejimeService.getSavedPreferences(); + + preferences$.subscribe(preferences => { + this.changeMatomoConsent(preferences.matomo); + + if (environment.matomo?.siteId && environment.matomo?.trackerUrl) { + this.matomoInitializer.initializeTracker({ + siteId: environment.matomo.siteId, + trackerUrl: environment.matomo.trackerUrl, + }); + } + }); + } + } + + changeMatomoConsent = (consent: boolean) => { + if (consent) { + this.matomoTracker.setConsentGiven(); + } else { + this.matomoTracker.forgetConsentGiven(); + } + }; +} diff --git a/src/app/statistics/mock-matomo-tracker.ts b/src/app/statistics/mock-matomo-tracker.ts new file mode 100644 index 00000000000..cfd2ca29932 --- /dev/null +++ b/src/app/statistics/mock-matomo-tracker.ts @@ -0,0 +1,3 @@ +export class MockMatomoTracker { + trackSiteSearch = () => {}; +} diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 053e5133d9a..08c75b13b4b 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1630,6 +1630,10 @@ "cookies.consent.app.description.google-recaptcha": "We use google reCAPTCHA service during registration and password recovery", + "cookies.consent.app.title.matomo": "Matomo", + + "cookies.consent.app.description.matomo": "Allows us to track statistical data", + "cookies.consent.purpose.functional": "Functional", "cookies.consent.purpose.statistical": "Statistical", diff --git a/src/assets/i18n/it.json5 b/src/assets/i18n/it.json5 index 098e9752bc5..2d99a178a92 100644 --- a/src/assets/i18n/it.json5 +++ b/src/assets/i18n/it.json5 @@ -2029,6 +2029,13 @@ "cookies.consent.app.description.google-recaptcha": "Utilizziamo il servizio Google reCAPTCHA nelle fasi di registrazione e recupero password", + // "cookies.consent.app.title.matomo": "Matomo", + "cookies.consent.app.title.matomo": "Matomo", + + // "cookies.consent.app.description.matomo": "Allows us to track statistical data", + "cookies.consent.app.description.matomo": "Ci permette di tracciare i dati statistici", + + // "cookies.consent.purpose.functional": "Functional", "cookies.consent.purpose.functional": "Funzionale", diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index 7f5f0199582..a52cd6be358 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -24,6 +24,7 @@ import { InfoConfig } from './info-config.interface'; import { ItemConfig } from './item-config.interface'; import { LangConfig } from './lang-config.interface'; import { MarkdownConfig } from './markdown-config.interface'; +import { MatomoConfig } from './matomo-config.interface'; import { MediaViewerConfig } from './media-viewer-config.interface'; import { INotificationBoardOptions } from './notifications-config.interfaces'; import { QualityAssuranceConfig } from './quality-assurance.config'; @@ -66,6 +67,7 @@ interface AppConfig extends Config { search: SearchConfig; notifyMetrics: AdminNotifyMetricsRow[]; liveRegion: LiveRegionConfig; + matomo?: MatomoConfig; } /** diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index 3c5e0ef0dac..2ea08946fe4 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -19,6 +19,7 @@ import { InfoConfig } from './info-config.interface'; import { ItemConfig } from './item-config.interface'; import { LangConfig } from './lang-config.interface'; import { MarkdownConfig } from './markdown-config.interface'; +import { MatomoConfig } from './matomo-config.interface'; import { MediaViewerConfig } from './media-viewer-config.interface'; import { INotificationBoardOptions } from './notifications-config.interfaces'; import { QualityAssuranceConfig } from './quality-assurance.config'; @@ -599,4 +600,6 @@ export class DefaultAppConfig implements AppConfig { messageTimeOutDurationMs: 30000, isVisible: false, }; + + matomo: MatomoConfig = {}; } diff --git a/src/config/matomo-config.interface.ts b/src/config/matomo-config.interface.ts new file mode 100644 index 00000000000..95dc2672683 --- /dev/null +++ b/src/config/matomo-config.interface.ts @@ -0,0 +1,9 @@ +import { Config } from './config.interface'; + +/** + * Configuration interface for Matomo tracking + */ +export interface MatomoConfig extends Config { + trackerUrl?: string; + siteId?: string; +} diff --git a/src/modules/app/browser-app.config.ts b/src/modules/app/browser-app.config.ts index 213b9de2f7e..4173d60d5f9 100644 --- a/src/modules/app/browser-app.config.ts +++ b/src/modules/app/browser-app.config.ts @@ -29,6 +29,11 @@ import { Angulartics2GoogleTagManager, Angulartics2RouterlessModule, } from 'angulartics2'; +import { + provideMatomo, + withRouteData, + withRouter, +} from 'ngx-matomo-client'; import { commonAppConfig } from '../../app/app.config'; import { storeModuleConfig } from '../../app/app.reducer'; @@ -157,5 +162,12 @@ export const browserAppConfig: ApplicationConfig = mergeApplicationConfig({ provide: MathService, useClass: ClientMathService, }, + provideMatomo( + { + mode: 'deferred', + }, + withRouter(), + withRouteData(), + ), ], }, commonAppConfig); diff --git a/src/modules/app/browser-init.service.ts b/src/modules/app/browser-init.service.ts index 525067da3af..562c0e4d0dc 100644 --- a/src/modules/app/browser-init.service.ts +++ b/src/modules/app/browser-init.service.ts @@ -45,6 +45,7 @@ import { MenuService } from '../../app/shared/menu/menu.service'; import { ThemeService } from '../../app/shared/theme-support/theme.service'; import { Angulartics2DSpace } from '../../app/statistics/angulartics/dspace-provider'; import { GoogleAnalyticsService } from '../../app/statistics/google-analytics.service'; +import { MatomoService } from '../../app/statistics/matomo.service'; import { StoreAction, StoreActionTypes, @@ -85,6 +86,7 @@ export class BrowserInitService extends InitService { protected router: Router, private requestService: RequestService, private halService: HALEndpointService, + private matomoService: MatomoService, ) { super( @@ -124,6 +126,7 @@ export class BrowserInitService extends InitService { this.initI18n(); this.initAngulartics(); this.initGoogleAnalytics(); + this.initMatomo(); this.initRouteListeners(); this.themeService.listenForThemeChanges(true); this.trackAuthTokenExpiration(); @@ -173,6 +176,10 @@ export class BrowserInitService extends InitService { this.googleAnalyticsService.addTrackingIdToPage(); } + protected initMatomo(): void { + this.matomoService.init(); + } + /** * During an external authentication flow invalidate the * data in the cache. This allows the app to fetch fresh content. diff --git a/src/modules/app/server-app.config.ts b/src/modules/app/server-app.config.ts index 4cf9369ddd5..9f4bf5c50fe 100644 --- a/src/modules/app/server-app.config.ts +++ b/src/modules/app/server-app.config.ts @@ -28,6 +28,7 @@ import { Angulartics2GoogleAnalytics, Angulartics2GoogleGlobalSiteTag, } from 'angulartics2'; +import { MatomoTracker } from 'ngx-matomo-client'; import { commonAppConfig } from '../../app/app.config'; import { storeModuleConfig } from '../../app/app.reducer'; @@ -55,6 +56,7 @@ import { XSRFService } from '../../app/core/xsrf/xsrf.service'; import { AngularticsProviderMock } from '../../app/shared/mocks/angulartics-provider.service.mock'; import { Angulartics2Mock } from '../../app/shared/mocks/angulartics2.service.mock'; import { Angulartics2DSpace } from '../../app/statistics/angulartics/dspace-provider'; +import { MockMatomoTracker } from '../../app/statistics/mock-matomo-tracker'; import { ServerSubmissionService } from '../../app/submission/server-submission.service'; import { SubmissionService } from '../../app/submission/submission.service'; import { TranslateServerLoader } from '../../ngx-translate-loaders/translate-server.loader'; @@ -144,5 +146,9 @@ export const serverAppConfig: ApplicationConfig = mergeApplicationConfig({ provide: MathService, useClass: ServerMathService, }, + { + provide: MatomoTracker, + useClass: MockMatomoTracker, + }, ], }, commonAppConfig); From fd2120904c41a92d22101d958e9c3418a23283c3 Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Wed, 5 Feb 2025 17:05:18 +0100 Subject: [PATCH 2/3] [CST-18964] add tests --- .../core/shared/search/search.service.spec.ts | 4 ++ src/app/statistics/matomo.service.spec.ts | 70 ++++++++++++++++++- src/app/statistics/mock-matomo-tracker.ts | 1 + 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/app/core/shared/search/search.service.spec.ts b/src/app/core/shared/search/search.service.spec.ts index 64b305ff643..365523b9cf3 100644 --- a/src/app/core/shared/search/search.service.spec.ts +++ b/src/app/core/shared/search/search.service.spec.ts @@ -36,6 +36,8 @@ import { ViewMode } from '../view-mode.model'; import { SearchService } from './search.service'; import { SearchConfigurationService } from './search-configuration.service'; import anything = jasmine.anything; +import { MatomoTestingModule } from 'ngx-matomo-client/testing'; + @Component({ template: '', @@ -55,6 +57,7 @@ describe('SearchService', () => { TestBed.configureTestingModule({ imports: [ CommonModule, + MatomoTestingModule.forRoot(), RouterTestingModule.withRoutes([ { path: 'search', component: DummyComponent, pathMatch: 'full' }, ]), @@ -122,6 +125,7 @@ describe('SearchService', () => { TestBed.configureTestingModule({ imports: [ CommonModule, + MatomoTestingModule.forRoot(), RouterTestingModule.withRoutes([ { path: 'search', component: DummyComponent, pathMatch: 'full' }, ]), diff --git a/src/app/statistics/matomo.service.spec.ts b/src/app/statistics/matomo.service.spec.ts index 4c84d26f446..60cbffdfb9a 100644 --- a/src/app/statistics/matomo.service.spec.ts +++ b/src/app/statistics/matomo.service.spec.ts @@ -1,16 +1,84 @@ import { TestBed } from '@angular/core/testing'; +import { + MatomoInitializerService, + MatomoTracker, +} from 'ngx-matomo-client'; +import { MatomoTestingModule } from 'ngx-matomo-client/testing'; +import { of } from 'rxjs'; +import { environment } from '../../environments/environment'; +import { + NativeWindowRef, + NativeWindowService, +} from '../core/services/window.service'; +import { OrejimeService } from '../shared/cookies/orejime.service'; import { MatomoService } from './matomo.service'; describe('MatomoService', () => { let service: MatomoService; + let matomoTracker: jasmine.SpyObj; + let matomoInitializer: jasmine.SpyObj; + let orejimeService: jasmine.SpyObj; + let nativeWindowService: jasmine.SpyObj; beforeEach(() => { - TestBed.configureTestingModule({}); + matomoTracker = jasmine.createSpyObj('MatomoTracker', ['setConsentGiven', 'forgetConsentGiven']); + matomoInitializer = jasmine.createSpyObj('MatomoInitializerService', ['initializeTracker']); + orejimeService = jasmine.createSpyObj('OrejimeService', ['getSavedPreferences']); + nativeWindowService = jasmine.createSpyObj('NativeWindowService', [], { nativeWindow: {} }); + + TestBed.configureTestingModule({ + imports: [MatomoTestingModule.forRoot()], + providers: [ + { provide: MatomoTracker, useValue: matomoTracker }, + { provide: MatomoInitializerService, useValue: matomoInitializer }, + { provide: OrejimeService, useValue: orejimeService }, + { provide: NativeWindowService, useValue: nativeWindowService }, + ], + }); + service = TestBed.inject(MatomoService); }); it('should be created', () => { expect(service).toBeTruthy(); }); + + it('should set changeMatomoConsent on native window', () => { + orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true })); + service.init(); + expect(nativeWindowService.nativeWindow.changeMatomoConsent).toBe(service.changeMatomoConsent); + }); + + it('should initialize tracker with correct parameters in production', () => { + environment.production = true; + environment.matomo = { siteId: '1', trackerUrl: 'http://example.com' }; + orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true })); + + service.init(); + + expect(matomoTracker.setConsentGiven).toHaveBeenCalled(); + expect(matomoInitializer.initializeTracker).toHaveBeenCalledWith({ + siteId: '1', + trackerUrl: 'http://example.com', + }); + }); + + it('should not initialize tracker if not in production', () => { + environment.production = false; + + service.init(); + + expect(matomoInitializer.initializeTracker).not.toHaveBeenCalled(); + }); + + it('should call setConsentGiven when consent is true', () => { + service.changeMatomoConsent(true); + expect(matomoTracker.setConsentGiven).toHaveBeenCalled(); + }); + + it('should call forgetConsentGiven when consent is false', () => { + service.changeMatomoConsent(false); + expect(matomoTracker.forgetConsentGiven).toHaveBeenCalled(); + }); }); diff --git a/src/app/statistics/mock-matomo-tracker.ts b/src/app/statistics/mock-matomo-tracker.ts index cfd2ca29932..a58934380ac 100644 --- a/src/app/statistics/mock-matomo-tracker.ts +++ b/src/app/statistics/mock-matomo-tracker.ts @@ -1,3 +1,4 @@ export class MockMatomoTracker { trackSiteSearch = () => {}; + trackPageView = () => {}; } From 0bab79bea40b4ce637ec98e38822311ba6f29e25 Mon Sep 17 00:00:00 2001 From: Andrea Barbasso <´andrea.barbasso@4science.com´> Date: Fri, 21 Feb 2025 16:22:13 +0100 Subject: [PATCH 3/3] [CST-18694] add TypeDoc comments --- src/app/statistics/matomo.service.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/app/statistics/matomo.service.ts b/src/app/statistics/matomo.service.ts index d507bb0a505..553eba851fc 100644 --- a/src/app/statistics/matomo.service.ts +++ b/src/app/statistics/matomo.service.ts @@ -11,16 +11,32 @@ import { environment } from '../../environments/environment'; import { NativeWindowService } from '../core/services/window.service'; import { OrejimeService } from '../shared/cookies/orejime.service'; +/** + * Service to manage Matomo analytics integration. + * Handles initialization and consent management for Matomo tracking. + */ @Injectable({ providedIn: 'root', }) export class MatomoService { + /** Injects the MatomoInitializerService to initialize the Matomo tracker. */ matomoInitializer = inject(MatomoInitializerService); + + /** Injects the MatomoTracker to manage Matomo tracking operations. */ matomoTracker = inject(MatomoTracker); + + /** Injects the OrejimeService to manage cookie consent preferences. */ orejimeService = inject(OrejimeService); + + /** Injects the NativeWindowService to access the native window object. */ _window = inject(NativeWindowService); + /** + * Initializes the Matomo tracker if in production environment. + * Sets up the changeMatomoConsent function on the native window object. + * Subscribes to cookie consent preferences and initializes the tracker accordingly. + */ init() { if (this._window.nativeWindow) { this._window.nativeWindow.changeMatomoConsent = this.changeMatomoConsent; @@ -42,6 +58,10 @@ export class MatomoService { } } + /** + * Changes the Matomo consent status based on the given consent value. + * @param consent - A boolean indicating whether consent is given for Matomo tracking. + */ changeMatomoConsent = (consent: boolean) => { if (consent) { this.matomoTracker.setConsentGiven();