Skip to content

Commit bb4d1a0

Browse files
committed
Add advanced Network and Device instrumentation
1 parent 97baf63 commit bb4d1a0

File tree

2 files changed

+25
-77
lines changed

2 files changed

+25
-77
lines changed

_includes/head.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
<meta charset=UTF-8>
33
<meta name=viewport content="width=device-width, minimum-scale=1.0">
44

5+
<script>
6+
(()=>{const e=document.documentElement,{connection:n}=navigator;window.obs=window.obs||{};const t=(window.obs&&window.obs.config)||{},o=!1!==t.observeChanges,c=t=>Number.isFinite(t)?Math.ceil(t/25)*25:null,r=t=>Number.isFinite(t)?t<75?"low":t<=275?"medium":"high":null,s=t=>Number.isFinite(t)?Math.ceil(t):null,i=()=>{const t=window.obs||{},o="number"==typeof t.downlinkBucket?t.downlinkBucket:null,c="low"===t.rttCategory,s="high"===t.rttCategory,i=null!=o&&o>=8,l=null!=o&&o<=5;t.connectionCapability=c&&i?"strong":s||l?"weak":"moderate";const a=!0===t.dataSaver||!0===t.batteryLow;t.conservationPreference=a?"conserve":"neutral";const d=!a&&"strong"===t.connectionCapability,u=a||"weak"===t.connectionCapability;t.deliveryMode=d?"rich":u?"lite":"cautious";t.canShowRichMedia="rich"===t.deliveryMode,t.shouldAvoidRichMedia="lite"===t.deliveryMode,["strong","moderate","weak"].forEach((t=>{e.classList.remove(`has-connection-capability-${t}`)})),e.classList.add(`has-connection-capability-${t.connectionCapability}`),["conserve","neutral"].forEach((t=>{e.classList.remove(`has-conservation-preference-${t}`)})),e.classList.add(`has-conservation-preference-${t.conservationPreference}`),["rich","cautious","lite"].forEach((t=>{e.classList.remove(`has-delivery-mode-${t}`)})),e.classList.add(`has-delivery-mode-${t.deliveryMode}`)},l=()=>{if(!n)return;const t=n,{saveData:o,rtt:l,downlink:a}=t;window.obs.dataSaver=!!o,e.classList.toggle("has-data-saver",!!o);const d=c(l);null!=d&&(window.obs.rttBucket=d);const u=r(l);u&&(window.obs.rttCategory=u,["low","medium","high"].forEach((t=>e.classList.remove(`has-latency-${t}`))),e.classList.add(`has-latency-${u}`));const b=s(a);if(null!=b){window.obs.downlinkBucket=b;const t=b<=5,o=b>=8;e.classList.toggle("has-bandwidth-low",t),e.classList.toggle("has-bandwidth-high",o)}"downlinkMax"in t&&(window.obs.downlinkMax=t.downlinkMax),i()},a=t=>{if(!t)return;const n=t,{level:o,charging:c}=n,l=Number.isFinite(o)?o<=.2:null;window.obs.batteryLow=l,e.classList.toggle("has-battery-low",!!l);const r=!!c;window.obs.batteryCharging=r,e.classList.toggle("has-battery-charging",r),i()};l(),o&&n?.addEventListener&&n.addEventListener("change",l),"getBattery"in navigator&&navigator.getBattery().then((e=>{a(e),o&&"function"==typeof e.addEventListener&&(e.addEventListener("levelchange",(()=>a(e))),e.addEventListener("chargingchange",(()=>a(e))))})).catch((()=>{}))})();
7+
</script>
8+
59
<title>{{ page.title }} {% if paginator and paginator.page > 1 %}Blog – Page {{ paginator.page }} {% endif %}– CSS Wizardry</title>
610

711
{% if page.layout != "feature" %}

_layouts/default.html

Lines changed: 21 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -107,85 +107,29 @@
107107
</script>
108108

109109
<script type=module>
110-
;(function(){
111110

112-
/**
113-
* Send high-fidelity network and device information back to SpeedCurve. We
114-
* can use this to better segment and bucket metrics-by-condition.
115-
*/
116-
117-
// Ensure SpeedCurve is up and running, otherwise, bail out.
118-
if (!window.LUX || typeof window.LUX.addData !== 'function') {
119-
console.warn('SpeedCurve not available: network detection aborted.');
120-
return;
121-
}
122-
123-
// Categorise and bucket high cardinality metrics.
124-
125-
// Convert battery to a number out of 100 and round up to the nearest 5%.
126-
function bucketBattery(level) {
127-
return level != null ? Math.min(100, Math.ceil(level * 100 / 5) * 5) : null;
128-
}
129-
130-
// Bucket RTT into 25ms increments.
131-
function bucketRTT(rtt) {
132-
return rtt != null ? Math.ceil(rtt / 25) * 25 : null;
133-
}
134-
135-
// Assign RTT its CrUX-defined category.
136-
function categoriseRTT(rtt) {
137-
if (rtt == null) return null;
138-
return rtt < 75 ? 'Low' : rtt <= 275 ? 'Medium' : 'High';
139-
}
140-
141-
// Bucket downlink into 5Mbps increments.
142-
function bucketDownlink(downlink) {
143-
return downlink != null ? Math.ceil(downlink / 5) * 5 : null;
144-
}
145-
146-
// If the battery is currently less than 20%, assign ‘Low Battery’ status.
147-
function isBatteryLow(level) {
148-
return level != null ? level <= 0.2 : null;
149-
}
150-
151-
// Grab data from the Network Information API.
152-
const netInfo = navigator.connection;
153-
154-
if (netInfo) {
155-
156-
window.LUX.addData('dataSaver', netInfo.saveData);
157-
158-
const rttBucket = bucketRTT(netInfo.rtt);
159-
window.LUX.addData('rttBucket', rttBucket);
160-
161-
const rttCategory = categoriseRTT(netInfo.rtt);
162-
window.LUX.addData('rttCategory', rttCategory);
163-
164-
const downlinkBucket = bucketDownlink(netInfo.downlink);
165-
window.LUX.addData('downlinkBucket', downlinkBucket);
166-
167-
if ('downlinkMax' in netInfo) {
168-
window.LUX.addData('downlinkMax', netInfo.downlinkMax);
111+
(() => {
112+
// Bail out if SpeedCurve is not available.
113+
if (!window.LUX || typeof window.LUX.addData !== 'function') return;
114+
115+
const obs = window.obs || Object.create(null);
116+
117+
// Keys we intend to send. Keep in sync with obs.js
118+
const keys = [
119+
'dataSaver',
120+
'rttBucket',
121+
'rttCategory',
122+
'downlinkBucket',
123+
'downlinkMax',
124+
'batteryLow',
125+
'batteryCharging',
126+
];
127+
128+
for (const key of keys) {
129+
if (Object.prototype.hasOwnProperty.call(obs, key)) {
130+
window.LUX.addData(key, obs[key]);
169131
}
170-
171132
}
172-
173-
// Grab data from the Battery Status API.
174-
if ('getBattery' in navigator) {
175-
176-
navigator.getBattery().then(function(batt) {
177-
const levelBucket = bucketBattery(batt.level);
178-
window.LUX.addData('batteryLevelBucket', levelBucket);
179-
180-
window.LUX.addData('batteryCharging', batt.charging);
181-
182-
const lowFlag = isBatteryLow(batt.level);
183-
window.LUX.addData('batteryLow', lowFlag);
184-
}).catch(function() {
185-
console.log('Battery API error or unsupported');
186-
});
187-
188-
}
189-
190133
})();
134+
191135
</script>

0 commit comments

Comments
 (0)