diff --git a/services/web/frontend/js/features/event-tracking/index.js b/services/web/frontend/js/features/event-tracking/index.js new file mode 100644 index 0000000000..48aaa33f2d --- /dev/null +++ b/services/web/frontend/js/features/event-tracking/index.js @@ -0,0 +1,75 @@ +import _ from 'lodash' +import * as eventTracking from '../../infrastructure/event-tracking' + +function isInViewport(element) { + const elTop = $(element).offset().top + const elBtm = elTop + $(element).outerHeight() + + const viewportTop = $(window).scrollTop() + const viewportBtm = viewportTop + $(window).height() + + return elBtm > viewportTop && elTop < viewportBtm +} + +function setupEventTracking(el) { + const key = el.getAttribute('event-tracking') + const action = el.getAttribute('event-tracking-action') || key + const label = el.getAttribute('event-tracking-label') || '' + const gaCategory = el.getAttribute('event-tracking-ga') + const sendMB = el.getAttribute('event-tracking-mb') + const trigger = el.getAttribute('event-tracking-trigger') + const sendOnce = el.getAttribute('event-tracking-send-once') + const segmentation = JSON.parse(el.getAttribute('event-segmentation') || '{}') + segmentation.page = window.location.pathname + + function submit() { + if (sendMB) { + if (sendOnce) { + eventTracking.sendMBOnce(key, segmentation) + } else { + eventTracking.sendMB(key, segmentation) + } + } + if (gaCategory) { + if (sendOnce) { + eventTracking.sendOnce(gaCategory, action, label) + } else { + eventTracking.send(gaCategory, action, label) + } + } + } + + let handler + let timer + let timeoutAmt = 500 + switch (trigger) { + case 'load': + submit() + break + case 'click': + el.addEventListener('click', () => submit()) + break + case 'hover': + if (el.getAttribute('event-hover-amt')) { + timeoutAmt = parseInt(el.getAttribute('event-hover-amt'), 10) + } + el.addEventListener('mouseenter', () => { + timer = setTimeout(() => submit(), timeoutAmt) + }) + el.addEventListener('mouseleave', () => clearTimeout(timer)) + break + case 'scroll': + handler = _.throttle(() => { + if (isInViewport(el)) { + submit() + window.removeEventListener('scroll', handler) + window.removeEventListener('resize', handler) + } + }, 500) + window.addEventListener('scroll', handler) + window.addEventListener('resize', handler) + break + } +} + +document.querySelectorAll('[event-tracking]').forEach(setupEventTracking) diff --git a/services/web/frontend/js/infrastructure/event-tracking.js b/services/web/frontend/js/infrastructure/event-tracking.js index 8e1e2629f6..3ea7b298cf 100644 --- a/services/web/frontend/js/infrastructure/event-tracking.js +++ b/services/web/frontend/js/infrastructure/event-tracking.js @@ -2,31 +2,38 @@ import sessionStorage from '../infrastructure/session-storage' const CACHE_KEY = 'mbEvents' +function alreadySent(key) { + const eventCache = sessionStorage.getItem(CACHE_KEY) || {} + return !!eventCache[key] +} +function markAsSent(key) { + const eventCache = sessionStorage.getItem(CACHE_KEY) || {} + eventCache[key] = true + sessionStorage.setItem(CACHE_KEY, eventCache) +} + export function send(category, action, label, value) { if (typeof window.ga === 'function') { window.ga('send', 'event', category, action, label, value) } } +export function sendOnce(category, action, label, value) { + if (alreadySent(category)) return + if (typeof window.ga !== 'function') return + + window.ga('send', 'event', category, action, label, value) + markAsSent(category) +} + export function sendMB(key, segmentation = {}) { sendBeacon(key, segmentation) } export function sendMBOnce(key, segmentation = {}) { - let eventCache = sessionStorage.getItem(CACHE_KEY) - - // Initialize as an empy object if the event cache is still empty. - if (eventCache == null) { - eventCache = {} - sessionStorage.setItem(CACHE_KEY, eventCache) - } - - const isEventInCache = eventCache[key] || false - if (!isEventInCache) { - eventCache[key] = true - sessionStorage.setItem(CACHE_KEY, eventCache) - sendMB(key, segmentation) - } + if (alreadySent(key)) return + sendMB(key, segmentation) + markAsSent() } export function sendMBSampled(key, body = {}, rate = 0.01) { diff --git a/services/web/frontend/js/marketing.js b/services/web/frontend/js/marketing.js index d1ab0dc361..b079a5dc33 100644 --- a/services/web/frontend/js/marketing.js +++ b/services/web/frontend/js/marketing.js @@ -3,5 +3,6 @@ import 'jquery' import 'bootstrap' import './features/form-helpers/hydrate-form' import './features/contact-form' +import './features/event-tracking' $('[data-ol-lang-selector-tooltip]').tooltip({ trigger: 'hover' })