debian-mirror-gitlab/app/assets/javascripts/tracking.js

145 lines
4.3 KiB
JavaScript
Raw Normal View History

2020-05-24 23:13:21 +05:30
import { omitBy, isUndefined } from 'lodash';
2019-10-12 21:52:04 +05:30
2019-12-04 20:38:33 +05:30
const DEFAULT_SNOWPLOW_OPTIONS = {
namespace: 'gl',
hostname: window.location.hostname,
cookieDomain: window.location.hostname,
appId: '',
userFingerprint: false,
respectDoNotTrack: true,
forceSecureTracker: true,
eventMethod: 'post',
2021-01-03 14:25:43 +05:30
contexts: { webPage: true, performanceTiming: true },
2019-12-04 20:38:33 +05:30
formTracking: false,
linkClickTracking: false,
2021-01-29 00:20:46 +05:30
pageUnloadTimer: 10,
2019-12-04 20:38:33 +05:30
};
2020-05-24 23:13:21 +05:30
const createEventPayload = (el, { suffix = '' } = {}) => {
const action = el.dataset.trackEvent + (suffix || '');
2019-12-21 20:55:43 +05:30
let value = el.dataset.trackValue || el.value || undefined;
if (el.type === 'checkbox' && !el.checked) value = false;
const data = {
label: el.dataset.trackLabel,
property: el.dataset.trackProperty,
value,
context: el.dataset.trackContext,
};
2020-05-24 23:13:21 +05:30
return {
action,
data: omitBy(data, isUndefined),
};
};
const eventHandler = (e, func, opts = {}) => {
const el = e.target.closest('[data-track-event]');
if (!el) return;
const { action, data } = createEventPayload(el, opts);
func(opts.category, action, data);
2019-12-21 20:55:43 +05:30
};
const eventHandlers = (category, func) => {
const handler = opts => e => eventHandler(e, func, { ...{ category }, ...opts });
const handlers = [];
handlers.push({ name: 'click', func: handler() });
handlers.push({ name: 'show.bs.dropdown', func: handler({ suffix: '_show' }) });
handlers.push({ name: 'hide.bs.dropdown', func: handler({ suffix: '_hide' }) });
return handlers;
2019-10-12 21:52:04 +05:30
};
export default class Tracking {
2019-12-04 20:38:33 +05:30
static trackable() {
return !['1', 'yes'].includes(
window.doNotTrack || navigator.doNotTrack || navigator.msDoNotTrack,
);
}
2019-10-12 21:52:04 +05:30
static enabled() {
2019-12-04 20:38:33 +05:30
return typeof window.snowplow === 'function' && this.trackable();
2019-10-12 21:52:04 +05:30
}
2019-12-21 20:55:43 +05:30
static event(category = document.body.dataset.page, action = 'generic', data = {}) {
2019-10-12 21:52:04 +05:30
if (!this.enabled()) return false;
2020-04-22 19:07:51 +05:30
// eslint-disable-next-line @gitlab/require-i18n-strings
2019-10-12 21:52:04 +05:30
if (!category) throw new Error('Tracking: no category provided for tracking.');
2019-12-21 20:55:43 +05:30
const { label, property, value, context } = data;
const contexts = context ? [context] : undefined;
return window.snowplow('trackStructEvent', category, action, label, property, value, contexts);
2019-10-12 21:52:04 +05:30
}
2020-05-24 23:13:21 +05:30
static bindDocument(category = document.body.dataset.page, parent = document) {
if (!this.enabled() || parent.trackingBound) return [];
2019-10-12 21:52:04 +05:30
2020-05-24 23:13:21 +05:30
// eslint-disable-next-line no-param-reassign
parent.trackingBound = true;
2019-10-12 21:52:04 +05:30
2019-12-21 20:55:43 +05:30
const handlers = eventHandlers(category, (...args) => this.event(...args));
2020-05-24 23:13:21 +05:30
handlers.forEach(event => parent.addEventListener(event.name, event.func));
2019-12-21 20:55:43 +05:30
return handlers;
2019-10-12 21:52:04 +05:30
}
2020-05-24 23:13:21 +05:30
static trackLoadEvents(category = document.body.dataset.page, parent = document) {
if (!this.enabled()) return [];
const loadEvents = parent.querySelectorAll('[data-track-event="render"]');
loadEvents.forEach(element => {
const { action, data } = createEventPayload(element);
this.event(category, action, data);
});
return loadEvents;
}
2020-01-01 13:55:28 +05:30
static mixin(opts = {}) {
2019-12-21 20:55:43 +05:30
return {
2020-01-01 13:55:28 +05:30
computed: {
trackingCategory() {
const localCategory = this.tracking ? this.tracking.category : null;
return localCategory || opts.category;
},
trackingOptions() {
return { ...opts, ...this.tracking };
},
2019-12-21 20:55:43 +05:30
},
methods: {
2020-01-01 13:55:28 +05:30
track(action, data = {}) {
const category = data.category || this.trackingCategory;
const options = {
...this.trackingOptions,
...data,
};
Tracking.event(category, action, options);
2019-12-21 20:55:43 +05:30
},
},
2019-10-12 21:52:04 +05:30
};
}
}
2019-12-04 20:38:33 +05:30
export function initUserTracking() {
if (!Tracking.enabled()) return;
2019-12-21 20:55:43 +05:30
const opts = { ...DEFAULT_SNOWPLOW_OPTIONS, ...window.snowplowOptions };
2019-12-04 20:38:33 +05:30
window.snowplow('newTracker', opts.namespace, opts.hostname, opts);
2020-11-24 15:15:51 +05:30
document.dispatchEvent(new Event('SnowplowInitialized'));
}
export function initDefaultTrackers() {
if (!Tracking.enabled()) return;
2019-12-04 20:38:33 +05:30
window.snowplow('enableActivityTracking', 30, 30);
window.snowplow('trackPageView'); // must be after enableActivityTracking
2020-11-24 15:15:51 +05:30
if (window.snowplowOptions.formTracking) window.snowplow('enableFormTracking');
if (window.snowplowOptions.linkClickTracking) window.snowplow('enableLinkClickTracking');
2019-12-21 20:55:43 +05:30
Tracking.bindDocument();
2020-05-24 23:13:21 +05:30
Tracking.trackLoadEvents();
2019-12-04 20:38:33 +05:30
}