diff options
Diffstat (limited to 'app/assets/javascripts/tracking.js')
-rw-r--r-- | app/assets/javascripts/tracking.js | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js index 5d82d56f4ba..01de034417e 100644 --- a/app/assets/javascripts/tracking.js +++ b/app/assets/javascripts/tracking.js @@ -1,4 +1,16 @@ import { omitBy, isUndefined } from 'lodash'; +import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants'; +import { getExperimentData } from '~/experimentation/utils'; + +const standardContext = { ...window.gl?.snowplowStandardContext }; + +export const STANDARD_CONTEXT = { + schema: standardContext.schema, + data: { + ...(standardContext.data || {}), + source: 'gitlab-javascript', + }, +}; const DEFAULT_SNOWPLOW_OPTIONS = { namespace: 'gl', @@ -20,11 +32,17 @@ const createEventPayload = (el, { suffix = '' } = {}) => { let value = el.dataset.trackValue || el.value || undefined; if (el.type === 'checkbox' && !el.checked) value = false; + let context = el.dataset.trackContext; + if (el.dataset.trackExperiment) { + const data = getExperimentData(el.dataset.trackExperiment); + if (data) context = { schema: TRACKING_CONTEXT_SCHEMA, data }; + } + const data = { label: el.dataset.trackLabel, property: el.dataset.trackProperty, value, - context: el.dataset.trackContext, + context, }; return { @@ -51,25 +69,51 @@ const eventHandlers = (category, func) => { return handlers; }; +const dispatchEvent = (category = document.body.dataset.page, action = 'generic', data = {}) => { + // eslint-disable-next-line @gitlab/require-i18n-strings + if (!category) throw new Error('Tracking: no category provided for tracking.'); + + const { label, property, value } = data; + const contexts = [STANDARD_CONTEXT]; + + if (data.context) { + contexts.push(data.context); + } + + return window.snowplow('trackStructEvent', category, action, label, property, value, contexts); +}; + export default class Tracking { + static queuedEvents = []; + static initialized = false; + static trackable() { return !['1', 'yes'].includes( window.doNotTrack || navigator.doNotTrack || navigator.msDoNotTrack, ); } + static flushPendingEvents() { + this.initialized = true; + + while (this.queuedEvents.length) { + dispatchEvent(...this.queuedEvents.shift()); + } + } + static enabled() { return typeof window.snowplow === 'function' && this.trackable(); } - static event(category = document.body.dataset.page, action = 'generic', data = {}) { + static event(...eventData) { if (!this.enabled()) return false; - // eslint-disable-next-line @gitlab/require-i18n-strings - if (!category) throw new Error('Tracking: no category provided for tracking.'); - const { label, property, value, context } = data; - const contexts = context ? [context] : undefined; - return window.snowplow('trackStructEvent', category, action, label, property, value, contexts); + if (!this.initialized) { + this.queuedEvents.push(eventData); + return false; + } + + return dispatchEvent(...eventData); } static bindDocument(category = document.body.dataset.page, parent = document) { @@ -128,13 +172,15 @@ export function initUserTracking() { window.snowplow('newTracker', opts.namespace, opts.hostname, opts); document.dispatchEvent(new Event('SnowplowInitialized')); + Tracking.flushPendingEvents(); } export function initDefaultTrackers() { if (!Tracking.enabled()) return; window.snowplow('enableActivityTracking', 30, 30); - window.snowplow('trackPageView'); // must be after enableActivityTracking + // must be after enableActivityTracking + window.snowplow('trackPageView', null, [STANDARD_CONTEXT]); if (window.snowplowOptions.formTracking) window.snowplow('enableFormTracking'); if (window.snowplowOptions.linkClickTracking) window.snowplow('enableLinkClickTracking'); |