Skip to content
This repository has been archived by the owner on Mar 14, 2024. It is now read-only.

Commit

Permalink
Add web vitals library (#3553)
Browse files Browse the repository at this point in the history
* Adds web-vitals and greater analytics tracking

* Add attribution

* Linting fixes

* More linting

* Fix Navigation Type

* Add JSON to prod build too

* Linting fixes

* Fix types

* Review feedback

* Updated plugin-json comment
  • Loading branch information
tunetheweb authored Aug 26, 2022
1 parent 9a9c8a1 commit 69957ba
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ module.exports = {
parserOptions: {
sourceType: 'module',
},
globals: {
ga: true,
},
env: {
browser: true,
node: true,
Expand Down
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"typedoc": "^0.22.7",
"typescript": "^4.4.4",
"unistore": "^3.5.2",
"web-vitals": "^3.0.0",
"webdev-infra": "^1.0.32"
},
"devDependencies": {
Expand All @@ -89,6 +90,7 @@
"@rollup/plugin-json": "^4.1.0",
"@types/cheerio": "^0.22.22",
"@types/express": "^4.17.13",
"@types/google.analytics": "^0.0.40",
"@types/js-yaml": "^4.0.3",
"@types/node": "^14.17.32",
"@types/node-fetch": "^2.5.12",
Expand Down
5 changes: 5 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import {terser} from 'rollup-plugin-terser';
// A Rollup plugin for copying files.
import copy from 'rollup-plugin-copy';

// A Rollup plugin for reading JSON files.
import json from '@rollup/plugin-json';

const devConfig = {
input: [
'site/_js/main.js',
Expand All @@ -31,6 +34,7 @@ const devConfig = {
nodeResolve(),
commonjs(),
svg(),
json(),
copy({
// Legacy docs, like those at /docs/native-client/, rely on the old
// prettify.js code for syntax highlighting.
Expand All @@ -52,6 +56,7 @@ const productionConfig = {
nodeResolve(),
commonjs(),
svg(),
json(),
terser({
format: {
// Remove all comments, including @license comments,
Expand Down
8 changes: 5 additions & 3 deletions site/_data/analytics.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"id": "UA-41980257-1",
"dimensions": {
"TRACKING_VERSION": "dimension1"
"TRACKING_VERSION": "dimension1",
"NAVIGATION_TYPE": "dimension2",
"WEB_VITALS_DEBUG": "dimension3"
},
"TRACKING_VERSION": "2.0"
}
"TRACKING_VERSION": "3.0"
}
78 changes: 78 additions & 0 deletions site/_js/analytics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {
onCLS,
onFCP,
onFID,
onLCP,
onTTFB,
onINP,
} from 'web-vitals/attribution';
import {dimensions} from '../_data/analytics.json';

/**
* See: https://github.com/GoogleChrome/web-vitals#using-analyticsjs
* @param {Object} metric
*/
function sendToGoogleAnalytics({name, delta, id, attribution, navigationType}) {
let webVitalInfo = '(not set)';

switch (name) {
case 'CLS':
webVitalInfo = attribution.largestShiftTarget;
break;
case 'FID':
case 'INP':
webVitalInfo = attribution.eventTarget;
break;
case 'LCP':
webVitalInfo = attribution.element;
break;
}

// Assumes the global `ga()` function exists, see:
// https://developers.google.com/analytics/devguides/collection/analyticsjs
ga('send', 'event', {
eventCategory: 'Web Vitals',
eventAction: name,
// Google Analytics metrics must be integers, so the value is rounded.
// For CLS the value is first multiplied by 1000 for greater precision
// (note: increase the multiplier for greater precision if needed).
eventValue: Math.round(name === 'CLS' ? delta * 1000 : delta),
// The `id` value will be unique to the current page load. When sending
// multiple values from the same page (e.g. for CLS), Google Analytics can
// compute a total by grouping on this ID (note: requires `eventLabel` to
// be a dimension in your report).
eventLabel: id,
// Use a non-interaction event to avoid affecting bounce rate.
nonInteraction: true,

// See: https://web.dev/debug-web-vitals-in-the-field/
[dimensions.WEB_VITALS_DEBUG]: webVitalInfo,
[dimensions.NAVIGATION_TYPE]: navigationType,
});
}

/**
* Add a listener to detect back/forward cache restores and track them
* as pageviews with the "bfcache" navigation type set (in case we need
* to distinguish them from regular pageviews).
* https://web.dev/bfcache/#how-bfcache-affects-analytics-and-performance-measurement
*/
window.addEventListener(
'pageshow',
/**
* @param {PageTransitionEvent} e
*/
e => {
if (e.persisted) {
ga('set', dimensions.NAVIGATION_TYPE, 'back-forward-cache');
ga('send', 'pageview');
}
}
);

onCLS(sendToGoogleAnalytics);
onFCP(sendToGoogleAnalytics);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onTTFB(sendToGoogleAnalytics);
1 change: 1 addition & 0 deletions site/_js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

// Utilities
import './store.js';
import './analytics.js';

// Web Components
// These are components that appear on _every_ page.
Expand Down
25 changes: 25 additions & 0 deletions types/modules/webdev_analytics/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare module 'webdev_analytics' {
export declare const id: string;
export declare const dimensions: {
TRACKING_VERSION: 'dimension1';
NAVIGATION_TYPE: 'dimension2';
WEB_VITALS_DEBUG: 'dimension3';
};
export declare const version: number;
}

0 comments on commit 69957ba

Please sign in to comment.