From 543ba5e42b3cb9f1f7073e069626360a6355b041 Mon Sep 17 00:00:00 2001 From: protoLabs CI Date: Wed, 1 Apr 2026 04:40:49 +0000 Subject: [PATCH 1/2] refactor: Add Umami privacy-friendly analytics --- .automaker-lock | 5 +++++ .env.example | 6 ++++++ index.html | 3 --- src/main.ts | 13 +++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 .automaker-lock diff --git a/.automaker-lock b/.automaker-lock new file mode 100644 index 0000000000..4c55e8c528 --- /dev/null +++ b/.automaker-lock @@ -0,0 +1,5 @@ +{ + "pid": 7, + "featureId": "feature-1775017198975-rmo03ljij", + "startedAt": "2026-04-01T04:30:49.193Z" +} \ No newline at end of file diff --git a/.env.example b/.env.example index 21a74f820e..15b28241fd 100644 --- a/.env.example +++ b/.env.example @@ -235,6 +235,12 @@ VITE_WS_API_URL= # Client-side Sentry DSN (optional). Leave empty to disable error reporting. VITE_SENTRY_DSN= +# Umami Analytics (privacy-friendly, only loaded in production builds) +# VITE_UMAMI_URL: URL to your Umami script.js (e.g. https://analytics.example.com/script.js) +# VITE_UMAMI_WEBSITE_ID: Website ID from your Umami dashboard +VITE_UMAMI_URL= +VITE_UMAMI_WEBSITE_ID= + # Map interaction mode: # - "flat" keeps pitch/rotation disabled (2D interaction) # - "3d" enables pitch/rotation interactions (default) diff --git a/index.html b/index.html index fe9e4fe714..32fe7a2af8 100644 --- a/index.html +++ b/index.html @@ -117,9 +117,6 @@ } - - - diff --git a/src/main.ts b/src/main.ts index 95a36376da..85c55ebed6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,6 +8,19 @@ import { installUtmInterceptor } from './utils/utm'; const sentryDsn = import.meta.env.VITE_SENTRY_DSN?.trim(); +// Umami Analytics — only load in production builds when env vars are configured +if (import.meta.env.PROD) { + const umamiUrl = import.meta.env.VITE_UMAMI_URL?.trim(); + const umamiWebsiteId = import.meta.env.VITE_UMAMI_WEBSITE_ID?.trim(); + if (umamiUrl && umamiWebsiteId) { + const script = document.createElement('script'); + script.defer = true; + script.src = umamiUrl; + script.dataset.websiteId = umamiWebsiteId; + document.head.appendChild(script); + } +} + // Initialize Sentry error tracking (early as possible) Sentry.init({ dsn: sentryDsn || undefined, From 28830ac1f1523de5537247bb4b93edf65c6f31d1 Mon Sep 17 00:00:00 2001 From: protoLabs CI Date: Wed, 1 Apr 2026 04:43:42 +0000 Subject: [PATCH 2/2] refactor: Add Umami privacy-friendly analytics --- .automaker-lock | 5 ----- vite.config.ts | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) delete mode 100644 .automaker-lock diff --git a/.automaker-lock b/.automaker-lock deleted file mode 100644 index 4c55e8c528..0000000000 --- a/.automaker-lock +++ /dev/null @@ -1,5 +0,0 @@ -{ - "pid": 7, - "featureId": "feature-1775017198975-rmo03ljij", - "startedAt": "2026-04-01T04:30:49.193Z" -} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 3fd1230282..b7e08e427f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -38,6 +38,18 @@ function brotliPrecompressPlugin(): Plugin { }; } +function umamiPlugin(umamiUrl: string, umamiWebsiteId: string): Plugin { + return { + name: 'umami-analytics', + apply: 'build', + transformIndexHtml(html) { + if (!umamiUrl || !umamiWebsiteId) return html; + const scriptTag = `\n `; + return html.replace('', `${scriptTag}\n `); + }, + }; +} + function htmlVariantPlugin(activeMeta: VariantMeta, activeVariant: string, isDesktopBuild: boolean): Plugin { return { name: 'html-variant', @@ -608,6 +620,8 @@ export default defineConfig(({ mode }) => { const isDesktopBuild = process.env.VITE_DESKTOP_RUNTIME === '1'; const activeVariant = process.env.VITE_VARIANT || 'full'; const activeMeta = VARIANT_META[activeVariant] || VARIANT_META.full; + const umamiUrl = env.VITE_UMAMI_URL || ''; + const umamiWebsiteId = env.VITE_UMAMI_WEBSITE_ID || ''; return { define: { @@ -615,6 +629,7 @@ export default defineConfig(({ mode }) => { }, plugins: [ htmlVariantPlugin(activeMeta, activeVariant, isDesktopBuild), + umamiPlugin(umamiUrl, umamiWebsiteId), polymarketPlugin(), rssProxyPlugin(), youtubeLivePlugin(),