IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Enable Vercel Analytics in Astro

    Jsun Dot LOL发表于 2023-02-05 00:00:00
    love 0

    2023-02-09 Update

    This feature has been added to vercel integration by me. Just enable it in Astro Config.

    astro.config.mjs

    import vercel from '@astrojs/vercel/serverless';
    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
      output: 'server',
      adapter: vercel({ analytics: true }),
    });
    

    Astro has its Vercel integration. But it hasn't provided any option to enable analytics yet. So we need to add some scripts for it manually.

    I have created a feature discussion for integration. But I don't have enough ability to create a PR for it. Hope this post can help it get integrated.

    Example

    Analytics script for this blog:
    https://github.com/jsun969/jsundotlol/blob/a8557715c5471adfd0857b3d240e080277a4077c/src/scripts/vercel/analytics.ts

    Create entry script

    Create analytics.ts in src/scripts/vercel and add it in your layout.

    src/layout/Layout.astro

    <body>
      ...
      <script src="../scripts/vercel/analytics.ts"></script>
    </body>
    

    Define a mode variable because we only enable it in production mode.

    src/scripts/vercel/analytics.ts

    const mode = import.meta.env.MODE as 'development' | 'production';
    

    Audiences

    Vercel docs: https://vercel.com/docs/concepts/analytics/audiences

    pnpm add @vercel/analytics
    

    src/scripts/vercel/analytics.ts

    + import { inject } from '@vercel/analytics';
    
      const mode = import.meta.env.MODE as 'development' | 'production';
    
    + inject({ mode });
    

    Web Vitals

    Vercel docs: https://vercel.com/docs/concepts/analytics/web-vitals

    Thanks to this stackoverflow answer. I have converted the script of this answer to typescript and simplified a bit.

    pnpm add web-vitals
    

    src/scripts/vercel/webVitals.ts

    import { getCLS, getFCP, getFID, getLCP, getTTFB } from 'web-vitals';
    import type { Metric } from 'web-vitals';
    
    const vitalsUrl = 'https://vitals.vercel-analytics.com/v1/vitals';
    
    type Options = { path: string; analyticsId: string; debug?: boolean };
    
    const getConnectionSpeed = () => {
      return 'connection' in navigator &&
        navigator['connection'] &&
        'effectiveType' in (navigator['connection'] as { effectiveType: string })
        ? (navigator['connection'] as { effectiveType: string })['effectiveType']
        : '';
    };
    
    const sendToAnalytics = (metric: Metric, options: Options) => {
      const body = {
        dsn: options.analyticsId,
        id: metric.id,
        page: options.path,
        href: location.href,
        event_name: metric.name,
        value: metric.value.toString(),
        speed: getConnectionSpeed(),
      };
    
      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() {
      const options = {
        path: window.location.pathname,
        analyticsId: import.meta.env.PUBLIC_VERCEL_ANALYTICS_ID,
      };
      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);
      }
    }
    

    src/scripts/vercel/analytics.ts

      import { inject } from '@vercel/analytics';
    
    + import { webVitals } from './webVitals';
    
      const mode = import.meta.env.MODE as 'development' | 'production';
    
      inject({ mode });
    + if (mode === 'production') {
    +   webVitals();
    + }
    
    

    https://stackoverflow.com/questions/74820110/why-vercel-web-vitals-is-not-loading-for-my-astro-project/74823176#74823176



沪ICP备19023445号-2号
友情链接