summaryrefslogtreecommitdiff
path: root/packages/integrations/vercel/src/analytics.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/integrations/vercel/src/analytics.ts')
-rw-r--r--packages/integrations/vercel/src/analytics.ts64
1 files changed, 64 insertions, 0 deletions
diff --git a/packages/integrations/vercel/src/analytics.ts b/packages/integrations/vercel/src/analytics.ts
new file mode 100644
index 000000000..95dee83e3
--- /dev/null
+++ b/packages/integrations/vercel/src/analytics.ts
@@ -0,0 +1,64 @@
+import { inject } from '@vercel/analytics';
+import type { Metric } from 'web-vitals';
+import { getCLS, getFCP, getFID, getLCP, getTTFB } from 'web-vitals';
+
+const vitalsUrl = 'https://vitals.vercel-analytics.com/v1/vitals';
+
+type Options = { path: string; analyticsId: string };
+
+const getConnectionSpeed = () => {
+ return 'connection' in navigator &&
+ navigator['connection'] &&
+ 'effectiveType' in (navigator['connection'] as unknown as { effectiveType: string })
+ ? (navigator['connection'] as unknown 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(),
+ };
+ const blob = new Blob([new URLSearchParams(body).toString()], {
+ type: 'application/x-www-form-urlencoded',
+ });
+ if (navigator.sendBeacon) {
+ navigator.sendBeacon(vitalsUrl, blob);
+ } else
+ fetch(vitalsUrl, {
+ body: blob,
+ method: 'POST',
+ credentials: 'omit',
+ keepalive: true,
+ });
+};
+
+function webVitals() {
+ const analyticsId = (import.meta as any).env.PUBLIC_VERCEL_ANALYTICS_ID;
+ if (!analyticsId) {
+ console.error('[Analytics] VERCEL_ANALYTICS_ID not found');
+ return;
+ }
+ const options: Options = { path: window.location.pathname, analyticsId };
+ 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);
+ }
+}
+
+const mode = (import.meta as any).env.MODE as 'development' | 'production';
+
+inject({ mode });
+if (mode === 'production') {
+ webVitals();
+}