mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
[CST-18964] add matomo integration
This commit is contained in:
13
package-lock.json
generated
13
package-lock.json
generated
@@ -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",
|
||||
|
@@ -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",
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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<string[]> = observableCombineLatest([hideGoogleAnalytics$, hideRegistrationVerification$]).pipe(
|
||||
map(([hideGoogleAnalytics, hideRegistrationVerification]) => {
|
||||
const hideMatomo$ = observableOf(!(environment.matomo?.trackerUrl && environment.matomo?.siteId));
|
||||
|
||||
const appsToHide$: Observable<string[]> = 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;
|
||||
}),
|
||||
);
|
||||
|
@@ -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'],
|
||||
|
16
src/app/statistics/matomo.service.spec.ts
Normal file
16
src/app/statistics/matomo.service.spec.ts
Normal file
@@ -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();
|
||||
});
|
||||
});
|
52
src/app/statistics/matomo.service.ts
Normal file
52
src/app/statistics/matomo.service.ts
Normal file
@@ -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();
|
||||
}
|
||||
};
|
||||
}
|
3
src/app/statistics/mock-matomo-tracker.ts
Normal file
3
src/app/statistics/mock-matomo-tracker.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export class MockMatomoTracker {
|
||||
trackSiteSearch = () => {};
|
||||
}
|
@@ -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",
|
||||
|
@@ -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",
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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 = {};
|
||||
}
|
||||
|
9
src/config/matomo-config.interface.ts
Normal file
9
src/config/matomo-config.interface.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Config } from './config.interface';
|
||||
|
||||
/**
|
||||
* Configuration interface for Matomo tracking
|
||||
*/
|
||||
export interface MatomoConfig extends Config {
|
||||
trackerUrl?: string;
|
||||
siteId?: string;
|
||||
}
|
@@ -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);
|
||||
|
@@ -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.
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user