6

enter image description hereI created a landing page using Astro with Tailwind CSS. And it is currently hosted on Vercel. I wanted to try out the analytics service provided by Vercel. I have been able to avail the Audience analytics service provided by Vercel. However, I cannot avail the web vitals services. After enabling the service and redeploying my project, I am stuck in this screen (screen shot provided).

Please note that I did turn off the ad blocker but that did not resolve the issue.I also added the following meta tag to resolve any CSP issue

<meta http-equiv="Content-Security-Policy"
      content="default-src 'self' vitals.vercel-insights.com"/>

But that has not solved the problem.That is why I want to know does Vercel support analytics for Astro projects and if they do, then what am I doing wrong? Thank you.

paradus-hex
  • 221
  • 2
  • 6

3 Answers3

6

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.

  1. If you are not yet using the Vercel adapter, install it in your project:

    npm i @astrojs/vercel
    
  2. 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.

swithinbank
  • 1,127
  • 1
  • 6
  • 15
  • Thanks for the reply. Unfortunately, the solutions did not work for me. Here are the things that I tried. 1) Followed the approach that you have given in the answer in the code snippets. 2) When that did not work, I dived into the IRL example you shared. Followed your implementation of on my project, but still no luck. 3) Finally I cloned your GitHub badges repo, hosted it on vertical, and turned on web Analytics. But I am still getting the same error over there as well. Any ideas on why this is happening? – paradus-hex Dec 18 '22 at 10:59
  • Hard to say. Could you share your project? If not, do you see any error logging in the browser dev tools when visiting your website? – swithinbank Dec 18 '22 at 13:49
  • After checking the logs I found that the requests to v1/vitals were getting blocked. And after a bit of digging around, I realized one of my content blockers was still on! I turned it off and it is now working. I followed the track vitals approach. Thanks a ton for your help. – paradus-hex Dec 19 '22 at 06:16
0

Vercel analytics has support for frameworks other than Next, Nuxt Gatsby etc. The way to achieve it in Astro (1.6, 2.0 etc.) is to install the @vercel/analytics package and inject a simple <script> tag that imports it and calls its exported function inject():

<script>
  import { inject } from '@vercel/analytics'
  // @ts-ignore: process.env.NODE_ENV is required by @vercel/analytics internally
  // so that it can determine the correct path for importing the analytics script
  globalThis.process = { env: { NODE_ENV: import.meta.env.MODE } }
  inject()
</script>

You can inject this code in your <head> section in any .astro template file.

Unfortunately, the package is expecting a non-ESM runtime environment and is internally conditionally checking for process.env.NODE_ENV to determine which script to load (local-relative path to JS or from a remote host, fully qualified domain name). This is the reason, the MODE needs to be exposed as process.env.NODE_ENV. I tried to achieve this via Vite using define, but Astro seems to check for process somewhere else internally and fails.

krymel
  • 1
0

This worked for me:

Install react and vercel integration using: npx astro add vercel react

Then modify the config file like this:

import { defineConfig } from 'astro/config';
import vercel from "@astrojs/vercel/serverless"; // can be static or edge instead of serverless

export default defineConfig({
  output: 'server', // not required if using static
  adapter: vercel({
    analytics: true
  })
});