UNPKG

@mezereon/tracking

Version:

Tracking for Mezereon Smart Search & Filter

195 lines (168 loc) 4.9 kB
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;