Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@financial-times/n-tracking

Package Overview
Dependencies
Maintainers
18
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@financial-times/n-tracking - npm Package Compare versions

Comparing version 1.1.0-beta.1 to 1.1.0-beta.2

.github/settings.yml

270

dist/browser.js

@@ -166,2 +166,6 @@ import oTracking from '@financial-times/o-tracking';

const isContextComplete = (context) => {
return requiredMetrics.every((metric) => typeof context[metric] === 'number');
};
const realUserMonitoringForPerformance = () => {

@@ -177,13 +181,10 @@

const navigation = performance.getEntriesByType('navigation')[0];
const { type, domInteractive, domComplete } = navigation;
// Proceed only if the page load event is a "navigate".
// @see: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/type
if (type !== 'navigate') return;
if (navigation.type !== 'navigate') return;
const context = {
action: 'performance',
category: 'page',
domInteractive: Math.round(domInteractive),
domComplete: Math.round(domComplete),
domInteractive: Math.round(navigation.domInteractive),
domComplete: Math.round(navigation.domComplete),
};

@@ -199,2 +200,3 @@

let hasAlreadyBroadcast = false;
options.analyticsTracker = (({ metricName, duration, data }) => {

@@ -208,11 +210,16 @@ if (hasAlreadyBroadcast) return;

}
else if (metricName === 'navigationTiming') {
if (metricName === 'navigationTiming') {
context.timeToFirstByte = Math.round(data.timeToFirstByte);
}
// Broadcast only if all the metrics are present
const contextContainsAllRequiredMetrics = requiredMetrics.every(metric => !isNaN(context[metric]));
if (contextContainsAllRequiredMetrics) {
console.log({performanceMetrics:context}); // eslint-disable-line no-console
broadcast('oTracking.event', context);
if (isContextComplete(context)) {
console.log({ performanceMetrics: context }); // eslint-disable-line no-console
broadcast('oTracking.event', {
action: 'performance',
category: 'page',
context
});
hasAlreadyBroadcast = true;

@@ -225,2 +232,238 @@ }

// Create markers at each of these percentage points
const DEPTH_MARKERS = [25, 50, 75, 100];
const defaultOptions = {
onScroll: () => {},
target: 'body',
debug: false
};
class ScrollDepth {
constructor (options) {
this.options = { ...defaultOptions, ...options };
this.init();
}
init () {
const target = document.querySelector(this.options.target);
if (target && 'IntersectionObserver' in window) {
this.observer = new IntersectionObserver(this.handleIntersection.bind(this));
target.style.position = 'relative';
DEPTH_MARKERS.forEach((percentage) => {
const marker = document.createElement('div');
marker.className = 'n-tracking-scroll-depth-marker';
marker.style.position = 'absolute';
marker.style.top = `${percentage}%`;
marker.style.bottom = '0';
marker.style.width = '100%';
marker.style.zIndex = '-1';
marker.setAttribute('data-scroll-depth', percentage);
target.appendChild(marker);
this.observer.observe(marker);
});
}
}
handleIntersection (changes) {
changes.forEach((change) => {
if (change.isIntersecting || change.intersectionRatio > 0) {
const marker = change.target;
const scrollDepth = marker.getAttribute('data-scroll-depth');
this.options.onScroll(scrollDepth);
if (this.options.debug) {
console.log('ScrollDepth', { marker: scrollDepth }); // eslint-disable-line no-console
}
if (marker.parentNode) {
marker.parentNode.removeChild(marker);
}
this.observer.unobserve(marker);
}
});
};
}
// Automatically stop the attention timer after this time
const ATTENTION_INTERVAL = 15000;
// These events re/start the attention timer
const ATTENTION_EVENTS = [
'load',
'click',
'focus',
'scroll',
'mousemove',
'touchstart',
'touchend',
'touchcancel',
'touchleave'
];
// These events pause the attention timer
const ATTENTION_LOST_EVENTS = ['blur'];
// These events will trigger the exit callback
const PAGE_EXIT_EVENTS = ['beforeunload', 'unload', 'pagehide'];
const defaultOptions$1 = {
onExit: () => {},
debug: false
};
class AttentionTime {
constructor (options) {
this.options = { ...defaultOptions$1, ...options };
this.totalAttentionTime = 0;
this.hasExited = false;
this.init();
}
init () {
ATTENTION_EVENTS.forEach((event) => {
window.addEventListener(event, this.startAttention.bind(this));
});
ATTENTION_LOST_EVENTS.forEach((event) => {
window.addEventListener(event, this.endAttention.bind(this));
});
PAGE_EXIT_EVENTS.forEach((event) => {
window.addEventListener(event, this.handleExit.bind(this));
});
document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this));
const videoPlayers = document.querySelectorAll('video');
videoPlayers.forEach((element) => {
element.addEventListener('playing', this.startConstantAttention.bind(this));
element.addEventListener('pause', this.endConstantAttention.bind(this));
element.addEventListener('ended', this.endConstantAttention.bind(this));
});
}
startAttention (event) {
clearTimeout(this.attentionTimeout);
if (!this.startAttentionTime) {
this.startAttentionTime = Date.now();
}
this.attentionTimeout = setTimeout(
this.endAttention.bind(this, { type: 'timeout' }),
ATTENTION_INTERVAL
);
if (this.options.debug) {
console.log('AttentionTime start', { event: event.type }); // eslint-disable-line no-console
}
}
endAttention (event) {
if (this.startAttentionTime) {
clearTimeout(this.attentionTimeout);
this.totalAttentionTime = this.getAttentionTime();
this.startAttentionTime = null;
}
if (this.options.debug) {
console.log('AttentionTime end', { event: event.type, time: this.totalAttentionTime }); // eslint-disable-line no-console
}
}
startConstantAttention () {
this.constantAttentionInterval = setInterval(
this.startAttention.bind(this),
ATTENTION_INTERVAL
);
}
endConstantAttention (event) {
this.endAttention(event);
clearInterval(this.constantAttentionInterval);
}
getAttentionTime () {
let currentAttentionTime = 0;
if (this.startAttentionTime) {
currentAttentionTime = Math.round(
(Date.now() - this.startAttentionTime) / 1000
);
}
return this.totalAttentionTime + currentAttentionTime;
}
handleVisibilityChange (event) {
if (document.visibilityState === 'hidden') {
this.endAttention(event);
} else {
this.startAttention(event);
}
}
handleExit (event) {
if (this.hasExited) {
return;
}
this.endAttention(event);
if (this.options.debug) {
console.log('AttentionTime', { event: event.type, time: this.totalAttentionTime }); // eslint-disable-line no-console
}
this.options.onExit(this.totalAttentionTime);
this.hasExited = true;
}
}
// TODO: The tracking event data for the `page:interaction` and `page:scrolldepth`
// events is needlessly different. We should work with the data team to align it.
const pageAttention = (options = {}) => {
const onExit = (attentionTime) => {
broadcast('oTracking.event', {
category: 'page',
action: 'interaction',
context: {
attention: {
total: attentionTime
}
}
});
};
const attention = new AttentionTime({ ...options, onExit });
const onScroll = (scrollDepth) => {
broadcast('oTracking.event', {
category: 'page',
action: 'scrolldepth',
meta: {
percentagesViewed: scrollDepth,
attention: attention.getAttentionTime()
}
});
};
new ScrollDepth({ ...options, onScroll });
};
// TODO: implement and test trackers copied over from n-ui

@@ -230,3 +473,4 @@

__proto__: null,
realUserMonitoringForPerformance: realUserMonitoringForPerformance
realUserMonitoringForPerformance: realUserMonitoringForPerformance,
pageAttention: pageAttention
});

@@ -233,0 +477,0 @@

2

package.json

@@ -6,3 +6,3 @@ {

"browser": "dist/browser.js",
"version": "1.1.0-beta.1",
"version": "1.1.0-beta.2",
"license": "MIT",

@@ -9,0 +9,0 @@ "repository": "Financial-Times/n-tracking.git",

@@ -43,14 +43,2 @@ # @financial-times/n-tracking [![CircleCI](https://circleci.com/gh/Financial-Times/n-tracking/tree/master.svg?style=svg)](https://circleci.com/gh/Financial-Times/n-tracking/tree/master)

**Send real-user-monitoring (RUM) performance metrics**
```js
import * as nTracking from '@financial-times/n-tracking';
if (flags.get('realUserMonitoringForPerformance')) {
nTracking.trackers.realUserMonitoringForPerformance();
}
```
<div><img width="70%" src="https://user-images.githubusercontent.com/224547/71626767-c709c480-2be6-11ea-91a5-506972a3b4d7.png" /></div>
_Above: Real-user-monitoring performance metrics are sent to spoor-api._
### Server-side integration

@@ -79,5 +67,5 @@

### `trackers.customTrackerName()`
### `trackers.{tracker}()`
TODO: custom tracking events to be used across FT.com
There are several custom tracking features provided by this library. See the [docs folder](./docs) for more information about these.

@@ -84,0 +72,0 @@

// TODO: implement and test trackers copied over from n-ui
// https://github.com/Financial-Times/n-ui/tree/master/components/n-ui/tracking/ft/events
import { realUserMonitoringForPerformance } from './real-user-monitoring-for-performance';
export { realUserMonitoringForPerformance };
export * from './realUserMonitoringForPerformance';
export * from './pageAttention';

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc