Update, April 2023
Astro’s Vercel integration added built-in support for analytics in version 3.1.0. You can now enable this just by updating the Astro config file.
If you are not yet using the Vercel adapter, install it in your project:
npm i @astrojs/vercel
Update astro.config.mjs
to use the Vercel adapter and set analytics: true
:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/static';
export default defineConfig({
adapter: vercel({
analytics: true
}),
});
Original answer, December 2022
Vercel’s Web Vitals analytics currently only has out-of-the-box support for Next, Nuxt, and Gatsby.
To track Web Vitals with a different framework like Astro, you need a bit of manual set up work as documented in Vercel’s Web Vitals API docs.
For example in your base Astro layout you could include a script tag that will import their example code and run it:
---
// src/layouts/BaseLayout.astro
---
<script>
import { webVitals } from '../scripts/vitals';
const analyticsId = import.meta.env.PUBLIC_VERCEL_ANALYTICS_ID;
webVitals({
path: window.location.pathname,
analyticsId,
});
</script>
Here’s Vercel’s example vitals.js
snippet:
// src/scripts/vitals.js
import { getCLS, getFCP, getFID, getLCP, getTTFB } from 'web-vitals';
const vitalsUrl = 'https://vitals.vercel-analytics.com/v1/vitals';
function getConnectionSpeed() {
return 'connection' in navigator &&
navigator['connection'] &&
'effectiveType' in navigator['connection']
? navigator['connection']['effectiveType']
: '';
}
function sendToAnalytics(metric, options) {
const body = {
dsn: options.analyticsId, // qPgJqYH9LQX5o31Ormk8iWhCxZO
id: metric.id, // v2-1653884975443-1839479248192
page: options.path, // /blog/my-test
href: location.href, // https://my-app.vercel.app/blog/my-test
event_name: metric.name, // TTFB
value: metric.value.toString(), // 60.20000000298023
speed: getConnectionSpeed(), // 4g
};
if (options.debug) {
console.log('[Analytics]', metric.name, JSON.stringify(body, null, 2));
}
const blob = new Blob([new URLSearchParams(body).toString()], {
// This content type is necessary for `sendBeacon`
type: 'application/x-www-form-urlencoded',
});
if (navigator.sendBeacon) {
navigator.sendBeacon(vitalsUrl, blob);
} else
fetch(vitalsUrl, {
body: blob,
method: 'POST',
credentials: 'omit',
keepalive: true,
});
}
export function webVitals(options) {
try {
getFID((metric) => sendToAnalytics(metric, options));
getTTFB((metric) => sendToAnalytics(metric, options));
getLCP((metric) => sendToAnalytics(metric, options));
getCLS((metric) => sendToAnalytics(metric, options));
getFCP((metric) => sendToAnalytics(metric, options));
} catch (err) {
console.error('[Analytics]', err);
}
}
For a slightly more real-world implementation you, check out the <TrackVitals>
Astro component in the astro-badge
repo.