diff --git a/README.md b/README.md index 5e59eaa..84bc073 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ By default `web-vitals-reporter` only rounds `metric.value` for known Web Vitals Use `mapMetric` to implement a custom metric mapping. For example: ```js +import { getCLS, getFID, getLCP } from 'web-vitals' import { createApiReporter } from 'web-vitals-reporter' const report = createApiReporter('/analytics', { @@ -176,6 +177,46 @@ getFID(report) getCLS(report) ``` +#### options.beforeSend(result) + +Use `beforeSend` to modify the final result before it's sent to the server. _Note_: The method should be **synchronous** because it's fired at the end of the session when the tab is closed. + +Example, compute metric score to pass [Core Web Vitals thresholds](https://web.dev/vitals/#core-web-vitals): + +```js +import { getCLS, getFID, getLCP } from 'web-vitals' +import { createApiReporter } from 'web-vitals-reporter' + +const report = createApiReporter('/analytics', { + beforeSend: (result) => { + const { LCP, FID, CLS } = result + if (!LCP || !FID || !CLS) return // Core Web Vitals are not supported + + // return extra attributes to merge into the final result + return { + LCPScore: LCP < 2500 ? 'good' : LCP < 4500 ? 'needs improvement' : 'poor' + FIDScore: FID < 100 ? 'good' : FID < 300 ? 'needs improvement' : 'poor' + CLSScore: CLS < 0.1 ? 'good' : CLS < 0.25 ? 'needs improvement' : 'poor' + } + }, +}) + +getLCP(report) +getFID(report) +getCLS(report) + +// Receive `POST /analytics` at the end of the session with: +{ + id: '1591874402350-8969370227936', + LCP: 1487, + LCPScore: 'good', + FID: 106, + FIDScore: 'needs improvement' + CLS: 1.5602, + CLSScore: 'poor' +} +``` + ### getDeviceInfo() It is a helper that returns device information (connection type, memory size, or the number of CPU cores). diff --git a/package.json b/package.json index 7355209..1a1a282 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ ], "size-limit": [ { - "limit": "800B", + "limit": "850B", "path": "./src/index.js" } ] diff --git a/src/index.js b/src/index.js index 28e3640..3ee0d5a 100644 --- a/src/index.js +++ b/src/index.js @@ -13,7 +13,7 @@ import { generateUniqueID } from 'web-vitals/dist/lib/generateUniqueID' * Use `onSend` to implement a custom logic. * * @param {string} url - * @param {{ initial?: object, mapMetric?: (metric: Metric, result: Result) => object, onSend?: (url: string, result: Result) => any }} [opts] + * @param {{ initial?: object, mapMetric?: (metric: Metric, result: Result) => Result, beforeSend?: (result: Result) => Result, onSend?: (url: string, result: Result) => any }} [opts] * @return {(metric: Metric) => void} */ @@ -25,7 +25,11 @@ export function createApiReporter(url, opts = {}) { const sendValues = () => { if (isSent) return // data is already sent if (!isCalled) return // no data collected - report({ name: 'duration', value: now() }) + + result.duration = now() + if (opts.beforeSend) { + result = { ...result, ...opts.beforeSend(result) } + } isSent = true if (opts.onSend) { opts.onSend(url, result) @@ -59,10 +63,8 @@ export function createApiReporter(url, opts = {}) { // Current solution: if LCP/CLS supported, use `onHidden` otherwise, use `pagehide` to fire the callback in the end. // // More details: https://github.com/treosh/web-vitals-reporter/issues/3 - const isLatestVisibilityChangeSupported = - typeof PerformanceObserver !== 'undefined' && - PerformanceObserver.supportedEntryTypes && - PerformanceObserver.supportedEntryTypes.indexOf('layout-shift') !== -1 + const supportedEntryTypes = (PerformanceObserver && PerformanceObserver.supportedEntryTypes) || [] + const isLatestVisibilityChangeSupported = supportedEntryTypes.indexOf('layout-shift') !== -1 if (isLatestVisibilityChangeSupported) { onHidden(({ isUnloading }) => {