jiti-meet/react/features/analytics/handlers/MatomoHandler.ts

170 lines
4.9 KiB
TypeScript
Raw Normal View History

2020-04-28 11:23:04 +00:00
/* global _paq */
2022-09-06 12:51:50 +00:00
import { getJitsiMeetGlobalNS } from '../../base/util/helpers';
2020-04-28 11:23:04 +00:00
2022-09-06 12:51:50 +00:00
import AbstractHandler, { IEvent } from './AbstractHandler';
2020-04-28 11:23:04 +00:00
/**
* Analytics handler for Matomo.
*/
export default class MatomoHandler extends AbstractHandler {
2022-09-06 12:51:50 +00:00
_userProperties: Object;
2020-04-28 11:23:04 +00:00
/**
* Creates new instance of the Matomo handler.
*
* @param {Object} options -
* @param {string} options.matomoEndpoint - The Matomo endpoint.
* @param {string} options.matomoSiteID - The site ID.
*/
2022-09-06 12:51:50 +00:00
constructor(options: any) {
2020-04-28 11:23:04 +00:00
super(options);
this._userProperties = {};
if (!options.matomoEndpoint) {
throw new Error(
'Failed to initialize Matomo handler: no endpoint defined.'
);
}
if (!options.matomoSiteID) {
throw new Error(
'Failed to initialize Matomo handler: no site ID defined.'
);
}
this._enabled = true;
this._initMatomo(options);
}
/**
* Initializes the _paq object.
*
* @param {Object} options -
* @param {string} options.matomoEndpoint - The Matomo endpoint.
* @param {string} options.matomoSiteID - The site ID.
* @returns {void}
*/
2022-09-06 12:51:50 +00:00
_initMatomo(options: any) {
// @ts-ignore
2020-04-28 11:23:04 +00:00
const _paq = window._paq || [];
2022-09-06 12:51:50 +00:00
// @ts-ignore
2020-04-28 11:23:04 +00:00
window._paq = _paq;
_paq.push([ 'trackPageView' ]);
_paq.push([ 'enableLinkTracking' ]);
(function() {
// add trailing slash if needed
const u = options.matomoEndpoint.endsWith('/')
? options.matomoEndpoint
: `${options.matomoEndpoint}/`;
// configure the tracker
_paq.push([ 'setTrackerUrl', `${u}matomo.php` ]);
_paq.push([ 'setSiteId', options.matomoSiteID ]);
// insert the matomo script
const d = document,
g = d.createElement('script'),
s = d.getElementsByTagName('script')[0];
g.type = 'text/javascript';
g.async = true;
g.defer = true;
g.src = `${u}matomo.js`;
2022-09-06 12:51:50 +00:00
s.parentNode?.insertBefore(g, s);
2020-04-28 11:23:04 +00:00
})();
}
/**
* Extracts the integer to use for a Matomo event's value field
* from a lib-jitsi-meet analytics event.
*
* @param {Object} event - The lib-jitsi-meet analytics event.
* @returns {number} - The integer to use for the 'value' of a Matomo
* event, or NaN if the lib-jitsi-meet event doesn't contain a
* suitable value.
* @private
*/
2022-09-06 12:51:50 +00:00
_extractValue(event: IEvent) {
2020-04-28 11:23:04 +00:00
const value = event && event.attributes && event.attributes.value;
// Try to extract an integer from the 'value' attribute.
2022-09-06 12:51:50 +00:00
return Math.round(parseFloat(value ?? ''));
2020-04-28 11:23:04 +00:00
}
/**
* Sets the permanent properties for the current session.
*
* @param {Object} userProps - The permanent properties.
* @returns {void}
*/
2022-09-06 12:51:50 +00:00
setUserProperties(userProps: any = {}) {
2020-04-28 11:23:04 +00:00
if (!this._enabled) {
return;
}
const visitScope = [ 'user_agent', 'callstats_name', 'browser_name' ];
// add variables in the 'page' scope
Object.keys(userProps)
.filter(key => visitScope.indexOf(key) === -1)
.forEach((key, index) => {
2022-09-06 12:51:50 +00:00
// @ts-ignore
2020-04-28 11:23:04 +00:00
_paq.push([
'setCustomVariable',
1 + index,
key,
userProps[key],
'page'
]);
});
// add variables in the 'visit' scope
Object.keys(userProps)
.filter(key => visitScope.indexOf(key) !== -1)
.forEach((key, index) => {
2022-09-06 12:51:50 +00:00
// @ts-ignore
2020-04-28 11:23:04 +00:00
_paq.push([
'setCustomVariable',
1 + index,
key,
userProps[key],
'visit'
]);
});
}
/**
* This is the entry point of the API. The function sends an event to
* the Matomo endpoint. The format of the event is described in
* analyticsAdapter in lib-jitsi-meet.
*
* @param {Object} event - The event in the format specified by
* lib-jitsi-meet.
* @returns {void}
*/
2022-09-06 12:51:50 +00:00
sendEvent(event: IEvent) {
2020-04-28 11:23:04 +00:00
if (this._shouldIgnore(event)) {
return;
}
const value = this._extractValue(event);
2022-09-06 12:51:50 +00:00
const matomoEvent: Array<string|number|undefined> = [ 'trackEvent', 'jitsi-meet', this._extractName(event) ];
2020-04-28 11:23:04 +00:00
if (!isNaN(value)) {
matomoEvent.push(value);
}
2022-09-06 12:51:50 +00:00
// @ts-ignore
2020-04-28 11:23:04 +00:00
_paq.push(matomoEvent);
}
}
const globalNS = getJitsiMeetGlobalNS();
globalNS.analyticsHandlers = globalNS.analyticsHandlers || [];
globalNS.analyticsHandlers.push(MatomoHandler);