UNPKG

@financial-times/o-tracking

Version:

Provides tracking for a product. Tracking requests are sent to the Spoor API.

93 lines (71 loc) 2.39 kB
import core from '../core.js'; import {getTrace} from '../../libs/get-trace.js'; import {assignIfUndefined, filterProperties} from '../utils.js'; // https://docs.google.com/spreadsheets/d/16d2-uDM8rhz1wSKOkoupcpPDRFQ8AtY1GxVJpt74vY4/edit?gid=1318706009#gid=1318706009 is the tracking spec for component events const TRACKING_ATTRIBUTES = [ 'componentContentId', 'type', 'subtype', 'component', 'custom', 'content' ]; const decorateEventData = (eventData, viewedEl, opts) => { const { trace, customContext } = getTrace(viewedEl); let context; if (opts.getContextData) { if (typeof opts.getContextData !== 'function') { throw new Error('opts.getContextData is not a function'); } const contextData = opts.getContextData(viewedEl); if (typeof contextData !== 'object') { throw new Error('opts.getContextData function should return {object}'); } context = filterProperties(contextData, TRACKING_ATTRIBUTES); } else { context = {}; } context.domPathTokens = trace; context.url = window.document.location.href || null; assignIfUndefined(customContext, context); eventData.context = context; }; /** * Listen for view events. * * @alias view#init * @param {object} opts - To set custom category[String], selector[String], getContextData[Function], intersectionObserverThreshold[Any] * @returns {undefined} */ const init = (opts = {}) => { if(!window.IntersectionObserver) { // eslint-disable-next-line no-console console.warn('o-tracking: Unable to track component view events as "window.IntersectionObserver" is not supported.'); return; } const selector = opts.selector || '[data-o-tracking-view]'; const elementsToTrack = [...document.querySelectorAll(selector)]; if (!elementsToTrack.length) { return; } function onChange (changes) { changes.forEach(change => { if(change.isIntersecting || change.intersectionRatio > 0) { const eventData = { action: opts.action || 'view', category: opts.category || 'component' }; const viewedEl = change.target; decorateEventData(eventData, viewedEl, opts); core.track(eventData); observer.unobserve(viewedEl); } }); } const observer = new IntersectionObserver(onChange, { threshold: opts.intersectionObserverThreshold || [ 1.0 ] }); elementsToTrack.forEach(el => observer.observe(el)); }; const view = { init }; export { view };