diff --git a/snowplow.js b/snowplow.js index 8f83f8ef95..cfca1a41f1 100644 --- a/snowplow.js +++ b/snowplow.js @@ -5,6 +5,8 @@ import { addGlobalContexts, enableActivityTracking, disableAnonymousTracking, + trackSelfDescribingEvent, + enableActivityTrackingCallback, } from '@snowplow/browser-tracker' import { LinkClickTrackingPlugin, @@ -25,6 +27,39 @@ import { reloadOnce } from './src/helpers/reloadOnce' import { isEmpty, pickBy } from 'lodash' import { SnowplowMediaPlugin } from '@snowplow/browser-plugin-media' +let aggregatedEvent = { + minXOffset: 0, + maxXOffset: 0, + minYOffset: 0, + maxYOffset: 0, + numEvents: 0, +} + +const sendAggregatedEvent = () => { + if (aggregatedEvent.numEvents > 0) { + trackSelfDescribingEvent({ + event: { + schema: 'iglu:com.snowplowanalytics/page_view_aggregated/jsonschema/1-0-0', + data: { + minXOffset: Math.max(0, Math.round(aggregatedEvent.minXOffset)), + maxXOffset: Math.max(0, Math.round(aggregatedEvent.maxXOffset)), + minYOffset: Math.max(0, Math.round(aggregatedEvent.minYOffset)), + maxYOffset: Math.max(0, Math.round(aggregatedEvent.maxYOffset)), + activeSeconds: aggregatedEvent.numEvents, + }, + }, + }) + } + // Reset + aggregatedEvent = { + minXOffset: 0, + maxXOffset: 0, + minYOffset: 0, + maxYOffset: 0, + numEvents: 0, + } +} + const createTrackerConfig = (cookieName) => { const appId = DOCS_SITE_URLS.includes(window.location.hostname) ? 'docs2' @@ -43,6 +78,7 @@ const createTrackerConfig = (cookieName) => { cookieDomain: `.${domain[1]}.${domain[0]}`, cookieName, cookieSameSite: 'Lax', + keepalive: true, contexts: { webPage: true, performanceTiming: true, @@ -64,16 +100,18 @@ const createTrackerConfig = (cookieName) => { const setupBrowserTracker = () => { newTracker( 'snplow5', - 'https://collector.snowplow.io', + // 'https://collector.snowplow.io', + 'com-snplow-sales-aws-prod1.collector.snplow.net', createTrackerConfig('_sp5_') ) - newTracker('biz1', 'https://c.snowplow.io', createTrackerConfig('_sp_biz1_')) + // newTracker('biz1', 'https://c.snowplow.io', createTrackerConfig('_sp_biz1_')) const selectedTabContext = () => { const data = pickBy({ cloud: localStorage.getItem('docusaurus.tab.cloud'), data_warehouse: localStorage.getItem('docusaurus.tab.warehouse'), }) + // @ts-ignore if (!_.isEmpty(data)) return { schema: @@ -84,11 +122,36 @@ const setupBrowserTracker = () => { addGlobalContexts([selectedTabContext]) enableLinkClickTracking() + enableActivityTracking({ heartbeatDelay: 10, minimumVisitLength: 10, }) // precise tracking for the unified log + enableActivityTrackingCallback({ + minimumVisitLength: 1, + heartbeatDelay: 1, + callback: function (event) { + const newMinX = + aggregatedEvent.numEvents === 0 + ? event.minXOffset + : Math.min(aggregatedEvent.minXOffset, event.minXOffset) + + const newMinY = + aggregatedEvent.numEvents === 0 + ? event.minYOffset + : Math.min(aggregatedEvent.minYOffset, event.minYOffset) + + aggregatedEvent = { + minXOffset: newMinX, + maxXOffset: Math.max(aggregatedEvent.maxXOffset, event.maxXOffset), + minYOffset: newMinY, + maxYOffset: Math.max(aggregatedEvent.maxYOffset, event.maxYOffset), + numEvents: aggregatedEvent.numEvents + 1, + } + }, + }) + enableButtonClickTracking() enableFormTracking() } @@ -96,6 +159,12 @@ const setupBrowserTracker = () => { if (ExecutionEnvironment.canUseDOM) { setupBrowserTracker() + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'hidden') { + sendAggregatedEvent() + } + }) + onPreferencesChanged((preferences) => { preferences.cookieOptions.forEach(({ id, isEnabled }) => { if (id === 'analytics') { @@ -108,7 +177,7 @@ if (ExecutionEnvironment.canUseDOM) { } else { const cookieKeys = document.cookie .split(';') - .reduce((ac, str) => [...ac, str?.split('=')[0].trim()], []) + .map((str) => str.split('=')[0].trim()) const snowplowCookies = cookieKeys.filter((cookieKey) => cookieKey.startsWith('_sp5_') ) @@ -126,6 +195,7 @@ if (ExecutionEnvironment.canUseDOM) { const module = { onRouteDidUpdate({ location, previousLocation }) { if (location.pathname !== previousLocation?.pathname) { + sendAggregatedEvent() // see https://github.com/facebook/docusaurus/pull/7424 regarding setTimeout setTimeout(() => { trackPageView()