@digital-blueprint/lunchlottery-app
Version:
[GitHub Repository](https://github.com/digital-blueprint/lunchlottery-app) | [npmjs package](https://www.npmjs.com/package/@digital-blueprint/lunchlottery-app) | [Unpkg CDN](https://unpkg.com/browse/@digital-blueprint/lunchlottery-app/)
236 lines (211 loc) • 8.58 kB
JavaScript
import DBPLitElement from '@dbp-toolkit/common/dbp-lit-element';
import {LoginStatus} from '@dbp-toolkit/auth/src/util';
export class MatomoElement extends DBPLitElement {
constructor() {
super();
this.endpoint = '';
this.siteId = '';
this.isRunning = false;
this.lastEvent = [];
this.gitInfo = '';
this.auth = {};
this.analyticsEvent = {};
this.loginStatus = '';
}
static get properties() {
return {
...super.properties,
endpoint: {type: String},
siteId: {type: String, attribute: 'site-id'},
gitInfo: {type: String, attribute: 'git-info'},
auth: {type: Object},
analyticsEvent: {type: Object, attribute: 'analytics-event'},
};
}
update(changedProperties) {
changedProperties.forEach((oldValue, propName) => {
switch (propName) {
case 'auth':
{
const loginStatus = this.auth['login-status'];
if (this.loginStatus !== loginStatus) {
this.setupMatomo(loginStatus === LoginStatus.LOGGED_IN);
this.loginStatus = loginStatus;
}
}
break;
case 'analyticsEvent':
{
// ignore analyticsEvent without data
if (
this.analyticsEvent.category === undefined &&
this.analyticsEvent.message === undefined
) {
break;
}
console.log(
'MatomoElement(' +
this.isRunning +
') analyticsEvent: ' +
this.analyticsEvent.action +
', ' +
this.analyticsEvent.message,
);
const event = [
'trackEvent',
this.analyticsEvent.category,
this.analyticsEvent.action,
this.analyticsEvent.name,
this.analyticsEvent.value,
];
if (this.isRunning) {
this.pushEvent(event);
} else {
this.lastEvent = event;
}
}
break;
}
});
super.update(changedProperties);
}
render() {
return ``;
}
setupMatomo(loggedIn) {
if (loggedIn && !this.isRunning) {
if (this.siteId === '') {
console.log('site id missing, skipping matomo...');
return;
}
if (this.endpoint === '') {
console.log('endpoint missing, skipping matomo...');
return;
}
console.log('add matomo...');
this.pushEvent(['setCustomVariable', 1, 'GitCommit', this.gitInfo, 'visit']);
this.pushEvent(['enableHeartBeatTimer']);
this.pushEvent(['disableCookies']);
this.pushEvent(['trackPageView']);
this.pushEvent(['enableLinkTracking']);
const that = this;
(function (endpoint, siteId) {
that.pushEvent(['setTrackerUrl', endpoint + 'matomo.php']);
that.pushEvent(['setSiteId', siteId]);
var g = document.createElement('script');
var s = document.getElementsByTagName('script')[0];
g.type = 'text/javascript';
g.async = true;
g.defer = true;
g.src = endpoint + 'matomo.js';
s.parentNode.insertBefore(g, s);
})(this.endpoint, this.siteId);
// track changed locations
window.addEventListener('locationchanged', function (e) {
that.pushEvent(['setReferrerUrl', e.detail.referrerUrl]);
that.pushEvent(['setCustomUrl', location.href]);
// that.pushEvent(['setDocumentTitle', '']);
that.pushEvent(['trackPageView']);
// make Matomo aware of newly added content
const content = document.getElementById('content');
that.pushEvent(['MediaAnalytics::scanForMedia', content]);
that.pushEvent(['FormAnalytics::scanForForms', content]);
that.pushEvent(['trackContentImpressionsWithinNode', content]);
});
// track errors
window.addEventListener('error', function (e) {
that.pushEvent([
'trackEvent',
'Error',
e.error ? e.error.message + '\n' + e.error.stack : e.message,
]);
});
window.addEventListener('unhandledrejection', function (e) {
let name = e.reason;
// TypeError objects have no toJSON() method, so we can't serialize them by themselves
if (e.reason instanceof TypeError) {
const error = e.reason;
name = {
message: error.message,
name: error.name,
fileName: error.fileName,
lineNumber: error.lineNumber,
columnNumber: error.columnNumber,
stack: error.stack,
};
}
that.pushEvent(['trackEvent', 'UnhandledRejection', name]);
});
// https://developer.mozilla.org/en-US/docs/Web/API/Element/securitypolicyviolation_event
window.addEventListener('securitypolicyviolation', (e) => {
let attrs = [
'blockedURI',
'columnNumber',
'disposition',
'documentURI',
'effectiveDirective',
'lineNumber',
'originalPolicy',
'referrer',
'sample',
'sourceFile',
'statusCode',
'violatedDirective',
];
let payload = {};
for (let attr of attrs) {
payload[attr] = e[attr];
}
this.pushEvent(['trackEvent', 'SecurityPolicyViolation', JSON.stringify(payload)]);
});
this.isRunning = true;
if (this.lastEvent.length > 0) {
console.log(
'MatomoElement* (' +
this.isRunning +
'): ' +
this.lastEvent[1] +
', ' +
this.lastEvent[2],
);
that.pushEvent(this.lastEvent);
this.lastEvent = [];
}
return;
}
if (!loggedIn && this.isRunning) {
// TODO: remove those event listeners
console.log('remove matomo...');
this.isRunning = false;
}
}
/**
* Pushes an event array to Matomo
* See: https://matomo.org/docs/event-tracking/
*
* event[0]: Event Category
* event[1]: Event Action
* event[2]: Event Name
* event[3]: Event Value
*
* @param event
*/
pushEvent(event) {
window._paq = window._paq || [];
// add some special checks for "trackEvent"
if (event[0] === 'trackEvent') {
// make sure the event action is a non-empty string
// prevents: "Error while logging event: Parameters `category` and `action` must not be empty or filled with whitespaces"
if (event[1] === null || event[1] === '' || event[1] === undefined) {
event[1] = 'empty';
}
// make sure the event name is a non-empty string
if (event[2] === null || event[2] === '' || event[2] === undefined) {
event[2] = 'empty';
} else if (typeof event[2] === 'object') {
event[2] = JSON.stringify(event[2]);
}
}
window._paq.push(event);
}
}