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
10
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 7.3.0 to 7.4.0

.toolkitrc.yml

81

dist/browser.js

@@ -181,3 +181,3 @@ import oTracking from '@financial-times/o-tracking';

// Flatten the seed string or build one from local entropy if needed.
var shortseed = mixkey(flatten(
mixkey(flatten(
use_entropy ? [seed, tostring(pool)] :

@@ -322,3 +322,3 @@ 0 in arguments ? seed : autoseed(), 3), key);

});
var seedRandom_1 = seedRandom.resetGlobal;
seedRandom.resetGlobal;

@@ -346,3 +346,3 @@ function seedIsInSample (seed, percent) {

const defaultSampleRate = 10;
const defaultSampleRate$1 = 10;

@@ -361,3 +361,3 @@ const isContextComplete = (context) => {

sampleRate = Number.isFinite(sampleRate) && sampleRate <= 100 && sampleRate >= 0 ? sampleRate : defaultSampleRate;
sampleRate = Number.isFinite(sampleRate) && sampleRate <= 100 && sampleRate >= 0 ? sampleRate : defaultSampleRate$1;

@@ -437,6 +437,68 @@ // Gather metrics for only a cohort of users.

var e,t,n,r,a=function(){return window.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0]},o=function(e){if("loading"===document.readyState)return "loading";var t=a();if(t){if(e<t.domInteractive)return "loading";if(0===t.domContentLoadedEventStart||e<t.domContentLoadedEventStart)return "dom-interactive";if(0===t.domComplete||e<t.domComplete)return "dom-content-loaded"}return "complete"},u=function(e){var t=e.nodeName;return 1===e.nodeType?t.toLowerCase():t.toUpperCase().replace(/^#/,"")},c=function(e,t){var n="";try{for(;e&&9!==e.nodeType;){var r=e,i=r.id?"#"+r.id:u(r)+(r.classList&&r.classList.value&&r.classList.value.trim()&&r.classList.value.trim().length?"."+r.classList.value.trim().replace(/\s+/g,"."):"");if(n.length+i.length>(t||100)-1)return n||i;if(n=n?i+">"+n:i,r.id)break;e=r.parentNode;}}catch(e){}return n},s=-1,f=function(){return s},d=function(e){addEventListener("pageshow",(function(t){t.persisted&&(s=t.timeStamp,e(t));}),!0);},l=function(){var e=a();return e&&e.activationStart||0},m=function(e,t){var n=a(),r="navigate";f()>=0?r="back-forward-cache":n&&(document.prerendering||l()>0?r="prerender":document.wasDiscarded?r="restore":n.type&&(r=n.type.replace(/_/g,"-")));return {name:e,value:void 0===t?-1:t,rating:"good",delta:0,entries:[],id:"v3-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},v=function(e,t,n){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){t(e.getEntries());}));}));return r.observe(Object.assign({type:e,buffered:!0},n||{})),r}}catch(e){}},p=function(e,t,n,r){var i,a;return function(o){t.value>=0&&(o||r)&&((a=t.value-(i||0))||void 0===i)&&(i=t.value,t.delta=a,t.rating=function(e,t){return e>t[1]?"poor":e>t[0]?"needs-improvement":"good"}(t.value,n),e(t));}},h=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}));},g=function(e){var t=function(t){"pagehide"!==t.type&&"hidden"!==document.visibilityState||e(t);};addEventListener("visibilitychange",t,!0),addEventListener("pagehide",t,!0);},T=function(e){var t=!1;return function(n){t||(e(n),t=!0);}},y=-1,E=function(){return "hidden"!==document.visibilityState||document.prerendering?1/0:0},S=function(e){"hidden"===document.visibilityState&&y>-1&&(y="visibilitychange"===e.type?e.timeStamp:0,b());},L=function(){addEventListener("visibilitychange",S,!0),addEventListener("prerenderingchange",S,!0);},b=function(){removeEventListener("visibilitychange",S,!0),removeEventListener("prerenderingchange",S,!0);},C=function(){return y<0&&(y=E(),L(),d((function(){setTimeout((function(){y=E(),L();}),0);}))),{get firstHiddenTime(){return y}}},w=function(e){document.prerendering?addEventListener("prerenderingchange",(function(){return e()}),!0):e();},M=[1800,3e3],x=function(e,t){t=t||{},w((function(){var n,r=C(),i=m("FCP"),a=v("paint",(function(e){e.forEach((function(e){"first-contentful-paint"===e.name&&(a.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-l(),0),i.entries.push(e),n(!0)));}));}));a&&(n=p(e,i,M,t.reportAllChanges),d((function(r){i=m("FCP"),n=p(e,i,M,t.reportAllChanges),h((function(){i.value=performance.now()-r.timeStamp,n(!0);}));})));}));},A=[.1,.25],F=function(e,t){!function(e,t){t=t||{},x(T((function(){var n,r=m("CLS",0),i=0,a=[],o=function(e){e.forEach((function(e){if(!e.hadRecentInput){var t=a[0],n=a[a.length-1];i&&e.startTime-n.startTime<1e3&&e.startTime-t.startTime<5e3?(i+=e.value,a.push(e)):(i=e.value,a=[e]);}})),i>r.value&&(r.value=i,r.entries=a,n());},u=v("layout-shift",o);u&&(n=p(e,r,A,t.reportAllChanges),g((function(){o(u.takeRecords()),n(!0);})),d((function(){i=0,r=m("CLS",0),n=p(e,r,A,t.reportAllChanges),h((function(){return n()}));})),setTimeout(n,0));})));}((function(t){!function(e){if(e.entries.length){var t=e.entries.reduce((function(e,t){return e&&e.value>t.value?e:t}));if(t&&t.sources&&t.sources.length){var n=(r=t.sources).find((function(e){return e.node&&1===e.node.nodeType}))||r[0];if(n)return void(e.attribution={largestShiftTarget:c(n.node),largestShiftTime:t.startTime,largestShiftValue:t.value,largestShiftSource:n,largestShiftEntry:t,loadState:o(t.startTime)})}}var r;e.attribution={};}(t),e(t);}),t);},P={passive:!0,capture:!0},B=new Date,D=function(r,i){e||(e=i,t=r,n=new Date,q(removeEventListener),k());},k=function(){if(t>=0&&t<n-B){var i={entryType:"first-input",name:e.type,target:e.target,cancelable:e.cancelable,startTime:e.timeStamp,processingStart:e.timeStamp+t};r.forEach((function(e){e(i);})),r=[];}},R=function(e){if(e.cancelable){var t=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,t){var n=function(){D(e,t),i();},r=function(){i();},i=function(){removeEventListener("pointerup",n,P),removeEventListener("pointercancel",r,P);};addEventListener("pointerup",n,P),addEventListener("pointercancel",r,P);}(t,e):D(t,e);}},q=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(t){return e(t,R,P)}));},H=[100,300],N=function(n,i){i=i||{},w((function(){var a,o=C(),u=m("FID"),c=function(e){e.startTime<o.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),a(!0));},s=function(e){e.forEach(c);},f=v("first-input",s);a=p(n,u,H,i.reportAllChanges),f&&g(T((function(){s(f.takeRecords()),f.disconnect();}))),f&&d((function(){var o;u=m("FID"),a=p(n,u,H,i.reportAllChanges),r=[],t=-1,e=null,q(addEventListener),o=c,r.push(o),k();}));}));},O=function(e,t){N((function(t){!function(e){var t=e.entries[0];e.attribution={eventTarget:c(t.target),eventType:t.name,eventTime:t.startTime,eventEntry:t,loadState:o(t.startTime)};}(t),e(t);}),t);},ee=[2500,4e3],te={},ne=function(e,t){!function(e,t){t=t||{},w((function(){var n,r=C(),i=m("LCP"),a=function(e){var t=e[e.length-1];t&&t.startTime<r.firstHiddenTime&&(i.value=Math.max(t.startTime-l(),0),i.entries=[t],n());},o=v("largest-contentful-paint",a);if(o){n=p(e,i,ee,t.reportAllChanges);var u=T((function(){te[i.id]||(a(o.takeRecords()),o.disconnect(),te[i.id]=!0,n(!0));}));["keydown","click"].forEach((function(e){addEventListener(e,(function(){return setTimeout(u,0)}),!0);})),g(u),d((function(r){i=m("LCP"),n=p(e,i,ee,t.reportAllChanges),h((function(){i.value=performance.now()-r.timeStamp,te[i.id]=!0,n(!0);}));}));}}));}((function(t){!function(e){if(e.entries.length){var t=a();if(t){var n=t.activationStart||0,r=e.entries[e.entries.length-1],i=r.url&&performance.getEntriesByType("resource").filter((function(e){return e.name===r.url}))[0],o=Math.max(0,t.responseStart-n),u=Math.max(o,i?(i.requestStart||i.startTime)-n:0),s=Math.max(u,i?i.responseEnd-n:0),f=Math.max(s,r?r.startTime-n:0),d={element:c(r.element),timeToFirstByte:o,resourceLoadDelay:u-o,resourceLoadTime:s-u,elementRenderDelay:f-s,navigationEntry:t,lcpEntry:r};return r.url&&(d.url=r.url),i&&(d.lcpResourceEntry=i),void(e.attribution=d)}}e.attribution={timeToFirstByte:0,resourceLoadDelay:0,resourceLoadTime:0,elementRenderDelay:e.value};}(t),e(t);}),t);};
// 1% of users
const defaultSampleRate = 1;
const dataFromCWV = (metric) => {
if (metric.name === 'LCP') {
return {
name: metric.name,
lcp: metric.value,
lcpDelta: metric.delta,
element: metric.attribution.largestShiftTarget
};
}
if (metric.name === 'FID') {
return {
name: metric.name,
fid: metric.value,
fidDelta: metric.delta,
element: metric.attribution.eventTarget
};
}
if (metric.name === 'CLS') {
return {
name: metric.name,
cls: metric.value,
clsDelta: metric.delta,
element: metric.attribution.largestShiftTarget
};
}
};
const realUserMonitoringWithAttribution = ({ sampleRate } = {}) => {
const broadcastCWV = (data) => {
broadcast('oTracking.event', {
action: 'performance-attribution',
category: 'page',
...dataFromCWV(data),
});
};
// Check browser support.
// @see https://developer.mozilla.org/en-US/docs/Web/API/PerformanceLongTaskTiming
if (!'PerformanceLongTaskTiming' in window) return;
const spoorId = getSpoorId();
const proportionToSample = sampleRate || defaultSampleRate;
// Gather metrics for only a cohort of users.
if (!seedIsInSample(spoorId, proportionToSample)) return;
// Proceed only if the page load event is a "navigate".
// @see: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/type
// When testing, you will need to open a new browser window and paste the URL in i.e. simply reloading the page will not work.
const navigation = performance.getEntriesByType('navigation') && performance.getEntriesByType('navigation')[0];
if (!navigation || navigation.type !== 'navigate') return;
F(broadcastCWV, { reportAllChanges: true });
O(broadcastCWV);
ne(broadcastCWV);
};
// Create markers at each of these percentage points
const DEPTH_MARKERS = [25, 50, 75, 100];
const defaultOptions = {
const defaultOptions$1 = {
onScroll: () => {},

@@ -449,3 +511,3 @@ target: 'body',

constructor (options) {
this.options = { ...defaultOptions, ...options };
this.options = { ...defaultOptions$1, ...options };

@@ -524,3 +586,3 @@ this.init();

const defaultOptions$1 = {
const defaultOptions = {
onExit: () => {},

@@ -532,3 +594,3 @@ debug: false

constructor (options) {
this.options = { ...defaultOptions$1, ...options };
this.options = { ...defaultOptions, ...options };

@@ -715,7 +777,6 @@ this.totalAttentionTime = 0;

var index = /*#__PURE__*/Object.freeze({
__proto__: null,
realUserMonitoringForPerformance: realUserMonitoringForPerformance,
realUserMonitoringWithAttribution: realUserMonitoringWithAttribution,
pageAttention: pageAttention,

@@ -722,0 +783,0 @@ textCopying: textCopying

14

dist/server.js

@@ -5,6 +5,8 @@ 'use strict';

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var React = _interopDefault(require('react'));
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
// For a list of all the properties available see the app context schema:

@@ -45,9 +47,11 @@ // <https://github.com/Financial-Times/dotcom-page-kit/blob/HEAD/packages/dotcom-server-app-context/schema.md>

if (/\bcore\b/.test(document.documentElement.className)) {
// eslint-disable-next-line no-var
var currentScript = document.scripts[document.scripts.length - 1];
// eslint-disable-next-line no-var
var img = new Image();
img.alt = "";
img.alt = '';
img.src = currentScript.getAttribute('data-pixel-src');
}
}
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("script", {
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("script", {
// To pass this information to the client-side

@@ -58,3 +62,3 @@ "data-pixel-src": pixel + encodedTrackingData.replace(placeholder, 'core-experience'),

}
}), /*#__PURE__*/React.createElement("noscript", null, /*#__PURE__*/React.createElement("img", {
}), /*#__PURE__*/React__default["default"].createElement("noscript", null, /*#__PURE__*/React__default["default"].createElement("img", {
src: pixel + encodedTrackingData.replace(placeholder, 'no-js'),

@@ -61,0 +65,0 @@ alt: ""

@@ -50,1 +50,22 @@ # Real user performance metrics

https://docs.google.com/document/d/1jG9f2DHs1AH-5kiV2cscpcheOckPM5EbzGA17uEGm9M/edit#
## With attribution
The above approach has a few issues: Firstly it takes the first bunch of events and sends them, whereas you want to capture the last events if possible.
Secondly, it doesn't tell us _why_ these values are what they are.
The workaround is to provide a more comprehensive real user monitoring option, which can be used simultaneously with the previous option.
The workaround utilises Web vital [attribution](https://www.npmjs.com/package/web-vitals#send-attribution-data) to these events, which helps determine what causes the scores, and can send multiple events of the same type per user.
To use this, alongside the previous option:
```js
import * as nTracking from '@financial-times/n-tracking';
if (flags.get('realUserMonitoringForPerformance')) {
nTracking.trackers.realUserMonitoringForPerformance();
nTracking.trackers.realUserMonitoringWithAttribution();
}
```

@@ -6,10 +6,9 @@ {

"browser": "dist/browser.js",
"version": "7.3.0",
"version": "7.4.0",
"license": "MIT",
"repository": "Financial-Times/n-tracking.git",
"scripts": {
"clean": "rm -rf ./dist",
"build": "npm run clean && rollup -c",
"prepare": "npm run build",
"test": "jest --config jest.config.js"
"build": "dotcom-tool-kit build:local",
"test": "dotcom-tool-kit test:local",
"start": "dotcom-tool-kit run:local"
},

@@ -20,13 +19,20 @@ "devDependencies": {

"@babel/preset-env": "^7.5.5",
"@financial-times/n-gage": "^8.3.2",
"@dotcom-tool-kit/babel": "^3.1.6",
"@dotcom-tool-kit/component": "^4.1.0",
"@dotcom-tool-kit/eslint": "^3.2.0",
"@dotcom-tool-kit/husky-npm": "^4.2.0",
"@dotcom-tool-kit/jest": "^3.4.0",
"@dotcom-tool-kit/lint-staged-npm": "^3.2.0",
"@financial-times/eslint-config-next": "^7.1.0",
"@rollup/plugin-commonjs": "^11.0.2",
"@rollup/plugin-node-resolve": "^7.1.1",
"babel-jest": "^25.0.0",
"babel-jest": "^27.5.1",
"check-engine": "^1.10.1",
"dotcom-tool-kit": "^3.4.0",
"eslint-plugin-react": "^7.14.3",
"jest": "^25.0.0",
"jest-environment-jsdom-fifteen": "^1.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jsdom": "^15.1.0",
"react": "^16.9.0",
"rollup": "^1.31.0",
"rollup": "^2.71.1",
"rollup-plugin-babel": "^4.3.3",

@@ -53,5 +59,4 @@ "seed-random": "^2.2.0"

"hooks": {
"commit-msg": "secret-squirrel-commitmsg",
"pre-commit": "secret-squirrel",
"pre-push": "make verify -j3"
"commit-msg": "dotcom-tool-kit git:commitmsg",
"pre-commit": "dotcom-tool-kit git:precommit"
}

@@ -61,3 +66,6 @@ },

"node": "18.16.0"
},
"lint-staged": {
"**/*.js": "dotcom-tool-kit format:staged test:staged --"
}
}
export * from './realUserMonitoringForPerformance';
export * from './realUserMonitoringWithAttribution';
export * from './pageAttention';
export * from './textCopying';

@@ -8,3 +8,3 @@ import React from 'react';

export function CoreTracking({ appContext }) {
export function CoreTracking ({ appContext }) {
// We only need the basics as the full data cannot be assembled

@@ -30,7 +30,9 @@ // on the server without the client-side JS.

// NOTE: This function will be stringified and embedded so use ES5 only!
function coreExperience() {
function coreExperience () {
if (/\bcore\b/.test(document.documentElement.className)) {
// eslint-disable-next-line no-var
var currentScript = document.scripts[document.scripts.length - 1];
// eslint-disable-next-line no-var
var img = new Image();
img.alt = ""
img.alt = '';
img.src = currentScript.getAttribute('data-pixel-src');

@@ -37,0 +39,0 @@ }

Sorry, the diff of this file is not supported yet

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