@mezereon/tracking
Version:
Tracking for Mezereon Smart Search & Filter
195 lines (168 loc) • 4.9 kB
JavaScript
import LZString from './lz-string';
import Tracking from './tracking';
let config = {
tracking: {
url: 'https://t.mezereon.net/t.png',
key: '',
log: false,
},
};
let mz = window.mz || {};
let queue = window.mz.q || [];
mz.getVisitId = window.mz.getVisitId = function () {
return mz.config.tracking.visitId || Tracking.getVisitId();
};
mz.getVisitorId = window.mz.getVisitorId = function () {
return mz.config.tracking.visitorId || Tracking.getVisitorId();
};
mz.getClientId = window.mz.getClientId = function () {
return mz.config.tracking.clientId || Tracking.getClientId();
};
mz.configure = function (options) {
for (let key in options) {
if (options.hasOwnProperty(key)) {
config[key] = options[key];
}
}
};
function displaySuccess() {
const div = document.createElement('div');
div.innerHTML = `<div style="z-index:99999;position:fixed;top:25px;left:25px;box-shadow: 5px 5px 15px 5px #aaa;padding:20px;background:#609a60; color:white;text-align:center;border-radius:5px; border: solid 1px #385638;">
<b style="font-size:2em">Mezereon Script Verified</b>
<div style="padding-top:5px;max-width: 300px;">This window was opened for JavaScript verification only and it can be closed.
</div>`;
document.body.appendChild(div);
}
function getUrlParameter(name) {
// eslint-disable-next-line no-useless-escape
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
const results = regex.exec(location.search);
return results === null
? ''
: decodeURIComponent(results[1].replace(/\+/g, ' '));
}
function log(message) {
if (config.tracking.log) {
console.log(message);
}
}
function isObject(item) {
return item && typeof item === 'object' && !Array.isArray(item);
}
function merge(target, ...sources) {
if (!sources.length) {
return target;
}
const source = sources.shift();
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} });
merge(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
}
}
return merge(target, ...sources);
}
function track(type, event) {
// Respect "Do Not Track" requests
if ('doNotTrack' in navigator && navigator.doNotTrack === '1') {
return;
}
// ignore prerendered pages
if (
'visibilityState' in document &&
document.visibilityState === 'prerender'
) {
return;
}
// merge with custom properties
config = merge(config, mz.config);
// merge with extra event properties
var final = {
key: config.tracking.key,
ts: new Date().getTime(),
visitId: mz.getVisitId(),
visitorId: mz.getVisitorId(),
clientId: mz.getClientId(),
body: event,
};
if (config.tracking.log) {
log('event=type:' + type + ',event:' + JSON.stringify(final));
}
send(type, final);
}
function send(type, event) {
if (config.tracking.url.includes('png')) {
sendImg(type, event);
} else {
sendAjax(type, event);
}
}
function sendAjax(type, event) {
var data = {
t: type,
p: LZString.compressToEncodedURIComponent(JSON.stringify(event)),
};
let xhr = new XMLHttpRequest();
xhr.open('POST', config.tracking.url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
if (config.headers) {
for (let header in config.headers) {
if (config.headers.hasOwnProperty(header)) {
xhr.setRequestHeader(header, config.headers[header]);
}
}
}
xhr.send(JSON.stringify(data));
}
function sendImg(type, event) {
let img = document.createElement('img');
// compress JSON
img.src =
config.tracking.url +
'?t=' +
type +
'&p=' +
LZString.compressToEncodedURIComponent(JSON.stringify(event));
img.addEventListener('load', function () {
// remove tracking img from DOM
document.body.removeChild(img);
});
// in case img.onload never fires, remove img after 1s & reset src attribute to cancel request
setTimeout(() => {
if (!img.parentNode) {
return;
}
img.src = '';
document.body.removeChild(img);
}, 1000);
// add to DOM to fire request
document.body.appendChild(img);
}
// override global object
mz.track = window.mz.track = function () {
var args = [].slice.call(arguments);
var t = args.shift();
track(t, args[0]);
};
// dequeue items
queue.forEach((i) => {
mz.track.apply(this, i);
});
// verify tracking if needed
const verify = getUrlParameter('mz_verify');
if (verify) {
const trackingKey = getUrlParameter('mz_tracking_key');
const searchKey = getUrlParameter('mz_search_key');
if (
mz.config.tracking.key === trackingKey &&
mz.config.search.key === searchKey
) {
displaySuccess();
}
}
export default mz;