summaryrefslogtreecommitdiff
path: root/packages/integrations/vercel/src/analytics.ts
diff options
context:
space:
mode:
authorGravatar Justin Sun <i@jsun969.cn> 2023-02-09 00:32:20 +0800
committerGravatar GitHub <noreply@github.com> 2023-02-08 13:32:20 -0300
commit23c60cfa45d0c01c2a710de9c6a644cd91d1b3f3 (patch)
treef813e8cd50ee4959e37dd8734102c273a289c060 /packages/integrations/vercel/src/analytics.ts
parentec2f2a31dec78e5749cdea524ae926a19df300e3 (diff)
downloadastro-23c60cfa45d0c01c2a710de9c6a644cd91d1b3f3.tar.gz
astro-23c60cfa45d0c01c2a710de9c6a644cd91d1b3f3.tar.zst
astro-23c60cfa45d0c01c2a710de9c6a644cd91d1b3f3.zip
feat(vercel): Add support for analytics (Audiences & Web Vitals) (#6148)
* feat(intergration/vercel): add vercel analytics support * docs(intergration/vercel): add vercel analytics prop * docs(intergration/vercel): bump version to 3.1.0 * Update packages/integrations/vercel/README.md Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * docs(intergration/vercel): add file name for example * feat(intergration/vercel): convert analytics to ts and support in edge * docs(intergration/vercel): move file names to code blocks as comments * fix(intergration/vercel): remove unused import * feat(intergration/vercel): add analytics support to static mode * chore(intergration/vercel): revert version change * style(intergration/vercel): add a blank line after astro import * chore(intergration/vercel): generate file by changeset * Update .changeset/eighty-bobcats-deliver.md Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/integrations/vercel/README.md Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * Update packages/integrations/vercel/src/analytics.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * chore(intergration/vercel): simplify analytics script --------- Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com> Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
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();
+}