openvibers/openvibe.live Commits
Real-user measurements skip automated browsers (navigator.webdriver, crawler and headless user agents, checked in the page only): the first samples were our own headless test runs (FCP 180 ms) (#223)
Changes
@@@ -6,6 +6,9 @@(function () {'use strict';if (!('PerformanceObserver' in window) || !navigator.sendBeacon) return;++ // Automated browsers are not visitors: crawlers that run scripts, headless test runs (ours included). Checked here++ // only; the user agent is never sent.++ if (navigator.webdriver || /bot|crawl|spider|slurp|headless|lighthouse|pagespeed|preview|phantom|puppeteer|playwright/i.test(navigator.userAgent || '')) return;const m = { fcp: 0, lcp: 0, cls: 0, inp: 0, tbt: 0, errs: [] };const watch = (type, fn, extra) => {try { new PerformanceObserver((list) => list.getEntries().forEach(fn)).observe(Object.assign({ type, buffered: true }, extra)); } catch (e) { /* not in this browser */ }@@@ -80,7 +80,9 @@ const { createRum, pageKind, deviceClass } = require('../server/web/rum');const app_js = fs.readFileSync(path.join(__dirname, '../public/js/app.js'), 'utf8');assert.ok(app_js.includes("if (Math.random() < 0.25 && window.ov) (window.requestIdleCallback || setTimeout)(() => ov.loadScript('/js/ov-rum.js'));"));const client = fs.readFileSync(path.join(__dirname, '../public/js/ov-rum.js'), 'utf8');-- assert.ok(client.includes("navigator.sendBeacon('/api/rum'") && !/cookie|localStorage|userAgent/i.test(client.replace(/\/\*[\s\S]*?\*\//g, '')), 'the beacon carries no identifier');++ assert.ok(client.includes("navigator.sendBeacon('/api/rum'") && !/cookie|localStorage/i.test(client.replace(/\/\*[\s\S]*?\*\//g, '')), 'the beacon carries no identifier');++ assert.ok(/navigator\.webdriver \|\| \/bot\|crawl\|spider[^/]*headless/.test(client), 'automated browsers (crawlers, headless runs) send nothing');++ assert.ok(!/userAgent[^)]*sendBeacon|JSON\.stringify\(\{[^}]*userAgent/.test(client), 'the user agent is checked, never sent');console.log('rum: all checks passed');})().catch((e) => { console.error(e); process.exit(1); });
@@ -6,6 +6,9 @@
@@ -6,6 +6,9 @@
(function () {
(function () {
'use strict';
'use strict';
if (!('PerformanceObserver' in window) || !navigator.sendBeacon) return;
if (!('PerformanceObserver' in window) || !navigator.sendBeacon) return;
+ // Automated browsers are not visitors: crawlers that run scripts, headless test runs (ours included). Checked here
+ // only; the user agent is never sent.
+ if (navigator.webdriver || /bot|crawl|spider|slurp|headless|lighthouse|pagespeed|preview|phantom|puppeteer|playwright/i.test(navigator.userAgent || '')) return;
const m = { fcp: 0, lcp: 0, cls: 0, inp: 0, tbt: 0, errs: [] };
const m = { fcp: 0, lcp: 0, cls: 0, inp: 0, tbt: 0, errs: [] };
const watch = (type, fn, extra) => {
const watch = (type, fn, extra) => {
try { new PerformanceObserver((list) => list.getEntries().forEach(fn)).observe(Object.assign({ type, buffered: true }, extra)); } catch (e) { /* not in this browser */ }
try { new PerformanceObserver((list) => list.getEntries().forEach(fn)).observe(Object.assign({ type, buffered: true }, extra)); } catch (e) { /* not in this browser */ }
@@ -80,7 +80,9 @@ const { createRum, pageKind, deviceClass } = require('../server/web/rum');
@@ -80,7 +80,9 @@ const { createRum, pageKind, deviceClass } = require('../server/web/rum');
const app_js = fs.readFileSync(path.join(__dirname, '../public/js/app.js'), 'utf8');
const app_js = fs.readFileSync(path.join(__dirname, '../public/js/app.js'), 'utf8');
assert.ok(app_js.includes("if (Math.random() < 0.25 && window.ov) (window.requestIdleCallback || setTimeout)(() => ov.loadScript('/js/ov-rum.js'));"));
assert.ok(app_js.includes("if (Math.random() < 0.25 && window.ov) (window.requestIdleCallback || setTimeout)(() => ov.loadScript('/js/ov-rum.js'));"));
const client = fs.readFileSync(path.join(__dirname, '../public/js/ov-rum.js'), 'utf8');
const client = fs.readFileSync(path.join(__dirname, '../public/js/ov-rum.js'), 'utf8');
- assert.ok(client.includes("navigator.sendBeacon('/api/rum'") && !/cookie|localStorage|userAgent/i.test(client.replace(/\/\*[\s\S]*?\*\//g, '')), 'the beacon carries no identifier');
+ assert.ok(client.includes("navigator.sendBeacon('/api/rum'") && !/cookie|localStorage/i.test(client.replace(/\/\*[\s\S]*?\*\//g, '')), 'the beacon carries no identifier');
+ assert.ok(/navigator\.webdriver \|\| \/bot\|crawl\|spider[^/]*headless/.test(client), 'automated browsers (crawlers, headless runs) send nothing');
+ assert.ok(!/userAgent[^)]*sendBeacon|JSON\.stringify\(\{[^}]*userAgent/.test(client), 'the user agent is checked, never sent');
console.log('rum: all checks passed');
console.log('rum: all checks passed');
})().catch((e) => { console.error(e); process.exit(1); });
})().catch((e) => { console.error(e); process.exit(1); });