diff --git a/common/changes/@snowplow/browser-plugin-web-vitals/feat-web-vitals-bump_2025-03-06-01-39.json b/common/changes/@snowplow/browser-plugin-web-vitals/feat-web-vitals-bump_2025-03-06-01-39.json new file mode 100644 index 000000000..ba3f32246 --- /dev/null +++ b/common/changes/@snowplow/browser-plugin-web-vitals/feat-web-vitals-bump_2025-03-06-01-39.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@snowplow/browser-plugin-web-vitals", + "comment": "Update default external library version to v4. Add compatibility for future v5, which deprecates the FID metric.", + "type": "none" + } + ], + "packageName": "@snowplow/browser-plugin-web-vitals" +} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 5c270a2a7..3fb2b15ca 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1950,8 +1950,8 @@ importers: specifier: ^2.3.1 version: 2.8.1 web-vitals: - specifier: ~3.3.2 - version: 3.3.2 + specifier: ~4.2.4 + version: 4.2.4 devDependencies: '@ampproject/rollup-plugin-closure-compiler': specifier: ~0.27.0 @@ -8871,8 +8871,8 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} - web-vitals@3.3.2: - resolution: {integrity: sha512-qRkpmSeKfEWAzNhtX541xA8gCJ+pqCqBmUlDVkVDSCSYUvfvNqF+k9g8I+uyreRcDBdfiJrd0/aLbTy5ydo49Q==} + web-vitals@4.2.4: + resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==} webdriver@8.39.0: resolution: {integrity: sha512-Kc3+SfiH4ufyrIht683VT2vnJocx0pfH8rYdyPvEh1b2OYewtFTHK36k9rBDHZiBmk6jcSXs4M2xeFgOuon9Lg==} @@ -17179,7 +17179,7 @@ snapshots: web-streams-polyfill@3.3.3: {} - web-vitals@3.3.2: {} + web-vitals@4.2.4: {} webdriver@8.39.0: dependencies: diff --git a/common/config/rush/repo-state.json b/common/config/rush/repo-state.json index a353e535b..033ec651f 100644 --- a/common/config/rush/repo-state.json +++ b/common/config/rush/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "6f4a24fea0d73ed30b10703fd10b02f67710f7ba", + "pnpmShrinkwrapHash": "483ab7c144cc1201cfba40405c05ebf190586e79", "preferredVersionsHash": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f" } diff --git a/plugins/browser-plugin-web-vitals/package.json b/plugins/browser-plugin-web-vitals/package.json index f79069cd0..0e651b274 100644 --- a/plugins/browser-plugin-web-vitals/package.json +++ b/plugins/browser-plugin-web-vitals/package.json @@ -25,7 +25,7 @@ "@snowplow/browser-tracker-core": "workspace:*", "@snowplow/tracker-core": "workspace:*", "tslib": "^2.3.1", - "web-vitals": "~3.3.2" + "web-vitals": "~4.2.4" }, "devDependencies": { "@ampproject/rollup-plugin-closure-compiler": "~0.27.0", diff --git a/plugins/browser-plugin-web-vitals/src/index.ts b/plugins/browser-plugin-web-vitals/src/index.ts index 600291bcb..e7e86f72f 100644 --- a/plugins/browser-plugin-web-vitals/src/index.ts +++ b/plugins/browser-plugin-web-vitals/src/index.ts @@ -4,7 +4,7 @@ import { WEB_VITALS_SCHEMA } from './schemata'; import { attachWebVitalsPageListeners, createWebVitalsScript, webVitalsListener } from './utils'; const _trackers: Record = {}; -const WEB_VITALS_SOURCE = 'https://unpkg.com/web-vitals@3/dist/web-vitals.iife.js'; +const WEB_VITALS_SOURCE = 'https://unpkg.com/web-vitals@4/dist/web-vitals.iife.js'; let listenersAttached = false; interface WebVitalsPluginOptions { diff --git a/plugins/browser-plugin-web-vitals/src/types.ts b/plugins/browser-plugin-web-vitals/src/types.ts index 681b8a70f..74b5ba003 100644 --- a/plugins/browser-plugin-web-vitals/src/types.ts +++ b/plugins/browser-plugin-web-vitals/src/types.ts @@ -1,12 +1,18 @@ -import type { ReportCallback, Metric, WebVitalsGlobal, onCLS, onLCP, onFID, onFCP, onINP, onTTFB } from 'web-vitals'; +import type { MetricType, Metric, onCLS, onLCP, onFID, onFCP, onINP, onTTFB } from 'web-vitals'; -export interface WebVitals extends WebVitalsGlobal { - onCLS: typeof onCLS; - onFID: typeof onFID; - onLCP: typeof onLCP; - onFCP: typeof onFCP; - onINP: typeof onINP; - onTTFB: typeof onTTFB; +export interface WebVitals { + onCLS?: typeof onCLS; + onFID?: typeof onFID; + onLCP?: typeof onLCP; + onFCP?: typeof onFCP; + onINP?: typeof onINP; + onTTFB?: typeof onTTFB; } -export { Metric, ReportCallback }; +declare global { + interface Window { + webVitals?: WebVitals; + } +} + +export { Metric, MetricType }; diff --git a/plugins/browser-plugin-web-vitals/src/utils.ts b/plugins/browser-plugin-web-vitals/src/utils.ts index 31916bfee..0434e378b 100644 --- a/plugins/browser-plugin-web-vitals/src/utils.ts +++ b/plugins/browser-plugin-web-vitals/src/utils.ts @@ -1,5 +1,5 @@ import { LOG } from '@snowplow/tracker-core'; -import { ReportCallback, WebVitals } from './types'; +import { MetricType } from './types'; /** * Attach page listeners to collect the Web Vitals values @@ -51,22 +51,23 @@ export function createWebVitalsScript(webVitalsSource: string) { * @return {void} */ export function webVitalsListener(webVitalsObject: Record) { - function addWebVitalsMeasurement(metricSchemaName: string): ReportCallback { + function addWebVitalsMeasurement(metricSchemaName: string): (arg: MetricType) => void { return (arg) => { webVitalsObject[metricSchemaName] = arg.value; webVitalsObject.navigationType = arg.navigationType; }; } - if (!window.webVitals) { + + const webVitals = window.webVitals; + if (!webVitals) { LOG.warn('The window.webVitals API is currently unavailable. web_vitals events will not be collected.'); return; } - const webVitals = window.webVitals as WebVitals; - webVitals.onCLS(addWebVitalsMeasurement('cls')); - webVitals.onFID(addWebVitalsMeasurement('fid')); - webVitals.onLCP(addWebVitalsMeasurement('lcp')); - webVitals.onFCP(addWebVitalsMeasurement('fcp')); - webVitals.onINP(addWebVitalsMeasurement('inp')); - webVitals.onTTFB(addWebVitalsMeasurement('ttfb')); + webVitals.onCLS?.(addWebVitalsMeasurement('cls')); + webVitals.onFID?.(addWebVitalsMeasurement('fid')); + webVitals.onLCP?.(addWebVitalsMeasurement('lcp')); + webVitals.onFCP?.(addWebVitalsMeasurement('fcp')); + webVitals.onINP?.(addWebVitalsMeasurement('inp')); + webVitals.onTTFB?.(addWebVitalsMeasurement('ttfb')); } diff --git a/plugins/browser-plugin-web-vitals/test/web-vitals.test.ts b/plugins/browser-plugin-web-vitals/test/web-vitals.test.ts index 8536d5b19..9a7691652 100644 --- a/plugins/browser-plugin-web-vitals/test/web-vitals.test.ts +++ b/plugins/browser-plugin-web-vitals/test/web-vitals.test.ts @@ -5,7 +5,6 @@ import { BrowserTracker } from '@snowplow/browser-tracker-core'; declare var jsdom: JSDOM; -// @ts-expect-error jsdom.window.webVitals = {}; describe('Web Vitals plugin', () => {