-
Notifications
You must be signed in to change notification settings - Fork 0
Add Umami privacy-friendly analytics #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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); | ||
| } | ||
| } | ||
|
Comment on lines
+11
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for previous Umami configuration in index.html or related files
rg -n "data-domains|data-website-id" --type html
rg -n "umami" index.html 2>/dev/null || echo "index.html not found at root"
fd -t f "index.html" --exec rg -l "umami" {} \;Repository: protoLabsAI/worldmonitor Length of output: 382 🏁 Script executed: #!/bin/bash
# 1. Verify src/main.ts current content at lines 11-22
echo "=== Current src/main.ts (lines 11-30) ==="
sed -n '11,30p' src/main.ts
echo -e "\n=== Check for analytics.ts and any Umami-related comments ==="
fd -t f "analytics.ts" --exec grep -n "index.html\|umami\|script" {} +
echo -e "\n=== Search for VITE_UMAMI environment variable references ==="
rg -n "VITE_UMAMI" --type ts --type js
echo -e "\n=== Check if public/index.html exists and contains Umami ==="
if [ -f "public/index.html" ]; then
rg -n "umami\|data-domains" public/index.html
else
echo "public/index.html not found"
fi
echo -e "\n=== Check .env files for Umami configuration ==="
fd -t f "\.env" --exec rg -l "UMAMI" {} \;Repository: protoLabsAI/worldmonitor Length of output: 2257 🏁 Script executed: #!/bin/bash
# Check if there are any comments or references to domain restriction or data-domains elsewhere
echo "=== Search for 'domain' references in codebase ==="
rg -i "domain" --type ts --type js -B 2 -A 2 | head -50
echo -e "\n=== Check vite.config.ts for any Umami-related logic ==="
sed -n '620,630p' vite.config.ts
echo -e "\n=== Search for any TODO, FIXME, or NOTE about Umami ==="
rg -i "todo|fixme|note" --type ts --type js | rg -i "umami|analytics" | head -20
echo -e "\n=== Check if there's a .env.example or documentation about VITE_UMAMI ==="
fd -t f "\.env" -o "README*" -o "DEPLOY*" | xargs rg -l "VITE_UMAMI" 2>/dev/null || echo "No matches found"Repository: protoLabsAI/worldmonitor Length of output: 50532 Add The previous Umami script in Additionally, the comment in ♻️ Proposed fix // 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;
+ script.dataset.domains = 'worldmonitor.app,www.worldmonitor.app,tech.worldmonitor.app,finance.worldmonitor.app,commodity.worldmonitor.app,happy.worldmonitor.app';
document.head.appendChild(script);
}
}Alternatively, add a 🤖 Prompt for AI Agents |
||
|
|
||
| // Initialize Sentry error tracking (early as possible) | ||
| Sentry.init({ | ||
| dsn: sentryDsn || undefined, | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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 <script defer src="${umamiUrl}" data-website-id="${umamiWebsiteId}"></script>`; | ||||||||||||||||||||||||||||||||
| return html.replace('</head>', `${scriptTag}\n </head>`); | ||||||||||||||||||||||||||||||||
|
Comment on lines
+45
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Consider validating the Umami URL format. The A simple URL validation would add defense in depth: 🛡️ Optional: Add basic URL validation function umamiPlugin(umamiUrl: string, umamiWebsiteId: string): Plugin {
return {
name: 'umami-analytics',
apply: 'build',
transformIndexHtml(html) {
- if (!umamiUrl || !umamiWebsiteId) return html;
+ if (!umamiUrl || !umamiWebsiteId) return html;
+ try {
+ new URL(umamiUrl); // Validate URL format
+ } catch {
+ console.warn('[umami-analytics] Invalid VITE_UMAMI_URL, skipping injection');
+ return html;
+ }
const scriptTag = `\n <script defer src="${umamiUrl}" data-website-id="${umamiWebsiteId}"></script>`;
return html.replace('</head>', `${scriptTag}\n </head>`);
},
};
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| function htmlVariantPlugin(activeMeta: VariantMeta, activeVariant: string, isDesktopBuild: boolean): Plugin { | ||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||
| name: 'html-variant', | ||||||||||||||||||||||||||||||||
|
|
@@ -608,13 +620,16 @@ 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: { | ||||||||||||||||||||||||||||||||
| __APP_VERSION__: JSON.stringify(pkg.version), | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| plugins: [ | ||||||||||||||||||||||||||||||||
| htmlVariantPlugin(activeMeta, activeVariant, isDesktopBuild), | ||||||||||||||||||||||||||||||||
| umamiPlugin(umamiUrl, umamiWebsiteId), | ||||||||||||||||||||||||||||||||
| polymarketPlugin(), | ||||||||||||||||||||||||||||||||
| rssProxyPlugin(), | ||||||||||||||||||||||||||||||||
| youtubeLivePlugin(), | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: protoLabsAI/worldmonitor
Length of output: 212
🏁 Script executed:
Repository: protoLabsAI/worldmonitor
Length of output: 1234
🏁 Script executed:
Repository: protoLabsAI/worldmonitor
Length of output: 50
Update stale comment in
src/services/analytics.ts.The comment at line 66 states that "Umami initialises itself via the script tag in index.html", but this is outdated. Umami is now dynamically injected in
src/main.ts(lines 11-22) when conditions are met (PROD build and environment variables configured). Update the comment ininitAnalytics()to reflect this change.🤖 Prompt for AI Agents