Skip to content

Add Umami privacy-friendly analytics#3

Open
mabry1985 wants to merge 2 commits intomainfrom
feature/add-umami-privacy-friendly-analytics-o03ljij
Open

Add Umami privacy-friendly analytics#3
mabry1985 wants to merge 2 commits intomainfrom
feature/add-umami-privacy-friendly-analytics-o03ljij

Conversation

@mabry1985
Copy link
Copy Markdown

@mabry1985 mabry1985 commented Apr 1, 2026

Summary

Milestone: M3: Automation & Agents

Set up Umami analytics for privacy-friendly traffic tracking.

Steps:

  1. Register worldmonitor website in the Umami dashboard
  2. Add Umami tracking script to the main HTML entry point (index.html)
  3. Use environment variables for the Umami URL and website ID (VITE_UMAMI_URL, VITE_UMAMI_WEBSITE_ID)
  4. Ensure the script is only loaded in production builds
  5. Update .env.example with the new environment variables

Acceptance Criteria:

  • Umami ...

Recovered automatically by Automaker post-agent hook

Summary by CodeRabbit

  • New Features

    • Umami Analytics configuration is now environment-based, allowing customizable tracking setup across different deployments.
  • Chores

    • Optimized analytics initialization for improved flexibility and maintainability.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

Walkthrough

This pull request replaces a hardcoded Umami Analytics script with a configurable, environment-based approach. The hardcoded script tag is removed from HTML, replaced by dynamic runtime loading in production and an optional build-time injection plugin, both controlled via new environment variables.

Changes

Cohort / File(s) Summary
Environment Configuration
.env.example
Added VITE_UMAMI_URL and VITE_UMAMI_WEBSITE_ID environment variables for Umami Analytics configuration.
HTML Markup
index.html
Removed hardcoded Umami Analytics script tag with its data-website-id and data-domains attributes.
Runtime Loading
src/main.ts
Added conditional logic to load Umami Analytics dynamically at runtime when both environment variables are present and in production environment. Script is created with defer attribute and appended to document head.
Build Configuration
vite.config.ts
Added umamiPlugin() function that injects Umami script tag into HTML during build by replacing </head> closing tag. Reads VITE_UMAMI_URL and VITE_UMAMI_WEBSITE_ID from environment and registers plugin in build pipeline.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description covers key implementation steps and objectives but is incomplete: the acceptance criteria section ends abruptly with an unchecked checkbox, and most required template sections (Type of change, Affected areas, Checklist) are missing or unfilled. Complete the acceptance criteria, select appropriate 'Type of change' and 'Affected areas' checkboxes, and verify all checklist items (TypeScript compilation, environment variables, etc.) before merging.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add Umami privacy-friendly analytics' accurately and concisely summarizes the main change: introducing Umami analytics integration to the project.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/add-umami-privacy-friendly-analytics-o03ljij

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.automaker-lock:
- Around line 1-5: The .automaker-lock file contains ephemeral runtime metadata
and should not be committed; add ".automaker-lock" to .gitignore and remove the
committed .automaker-lock from the repository index (so it remains locally if
needed) and commit that removal. Specifically, add the filename .automaker-lock
to the .gitignore file, stop tracking the existing .automaker-lock in the repo
(remove it from the index while keeping any local copy), and create a commit
that reflects the updated .gitignore and the removal of .automaker-lock from
version control.

In `@src/main.ts`:
- Around line 11-12: The comment inside initAnalytics() is stale: replace the
line that says "Umami initialises itself via the script tag in index.html" with
a concise note that Umami is now dynamically injected from the main bootstrap
(main.ts) when running a production build and required environment variables are
present (the code path that checks import.meta.env.PROD and env vars); update
the comment in initAnalytics() to reference this dynamic injection behavior and
remove the old index.html/script-tag wording.
- Around line 11-22: Add the Umami data-domains attribute when creating the
script in src/main.ts: after obtaining umamiUrl and umamiWebsiteId, read an
optional VITE_UMAMI_DOMAINS env var (or hardcode the same domains used
previously) and set script.dataset.domains = <domains string> before appending
the script element; also update the stale comment in src/services/analytics.ts
(around the comment at line referencing "Umami initialises itself via the script
tag in index.html") to mention that the script is injected from src/main.ts and
that data-domains is used to restrict tracking to production domains.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9f154607-9d9c-46db-8ebb-0d5e86112b0b

📥 Commits

Reviewing files that changed from the base of the PR and between 9b2c944 and 543ba5e.

📒 Files selected for processing (4)
  • .automaker-lock
  • .env.example
  • index.html
  • src/main.ts
💤 Files with no reviewable changes (1)
  • index.html

.automaker-lock Outdated
Comment on lines +1 to +5
{
"pid": 7,
"featureId": "feature-1775017198975-rmo03ljij",
"startedAt": "2026-04-01T04:30:49.193Z"
} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Lock file should not be committed to version control.

This .automaker-lock file contains ephemeral runtime metadata (process ID, timestamp) that is specific to a single execution of the Automaker tool. Committing this file can cause merge conflicts and serves no purpose in the repository.

Add .automaker-lock to .gitignore and remove this file from the commit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.automaker-lock around lines 1 - 5, The .automaker-lock file contains
ephemeral runtime metadata and should not be committed; add ".automaker-lock" to
.gitignore and remove the committed .automaker-lock from the repository index
(so it remains locally if needed) and commit that removal. Specifically, add the
filename .automaker-lock to the .gitignore file, stop tracking the existing
.automaker-lock in the repo (remove it from the index while keeping any local
copy), and create a commit that reflects the updated .gitignore and the removal
of .automaker-lock from version control.

Comment on lines +11 to +12
// Umami Analytics — only load in production builds when env vars are configured
if (import.meta.env.PROD) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the stale comment exists in analytics.ts
rg -n -C2 "index\.html" src/services/analytics.ts

Repository: protoLabsAI/worldmonitor

Length of output: 212


🏁 Script executed:

#!/bin/bash
# Get the full context of Umami loading in main.ts around lines 11-12
sed -n '1,30p' src/main.ts

Repository: protoLabsAI/worldmonitor

Length of output: 1234


🏁 Script executed:

#!/bin/bash
# Check if index.html contains the Umami script tag
rg -n "umami" -i index.html

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 in initAnalytics() to reflect this change.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main.ts` around lines 11 - 12, The comment inside initAnalytics() is
stale: replace the line that says "Umami initialises itself via the script tag
in index.html" with a concise note that Umami is now dynamically injected from
the main bootstrap (main.ts) when running a production build and required
environment variables are present (the code path that checks
import.meta.env.PROD and env vars); update the comment in initAnalytics() to
reference this dynamic injection behavior and remove the old
index.html/script-tag wording.

Comment on lines +11 to +22
// 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);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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 data-domains attribute to restrict Umami tracking to production domains.

The previous Umami script in public/pro/index.html included data-domains="worldmonitor.app,tech.worldmonitor.app,finance.worldmonitor.app,commodity.worldmonitor.app,happy.worldmonitor.app". Without this attribute, the current implementation will track pageviews on Vercel preview deployments and local builds where import.meta.env.PROD is true (e.g., vite preview).

Additionally, the comment in src/services/analytics.ts:66 stating "Umami initialises itself via the script tag in index.html" is now stale and should be updated to reflect the new loading mechanism in src/main.ts.

♻️ 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 VITE_UMAMI_DOMAINS environment variable to make this configurable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main.ts` around lines 11 - 22, Add the Umami data-domains attribute when
creating the script in src/main.ts: after obtaining umamiUrl and umamiWebsiteId,
read an optional VITE_UMAMI_DOMAINS env var (or hardcode the same domains used
previously) and set script.dataset.domains = <domains string> before appending
the script element; also update the stale comment in src/services/analytics.ts
(around the comment at line referencing "Umami initialises itself via the script
tag in index.html") to mention that the script is injected from src/main.ts and
that data-domains is used to restrict tracking to production domains.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@vite.config.ts`:
- Around line 45-48: The transformIndexHtml hook currently interpolates umamiUrl
and umamiWebsiteId directly into scriptTag in transformIndexHtml; add basic
validation for umamiUrl before building scriptTag (e.g., attempt to construct
new URL(umamiUrl) in a try/catch or run a simple URL regex) and only
create/insert the scriptTag when the URL is valid; if validation fails, log or
warn and return the original html unchanged. Also ensure any interpolation for
umamiWebsiteId is sanitized (e.g., string-only) before embedding to avoid
injecting quotes/special chars.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2faa48af-3efd-4ce5-9ddf-bf2b52f6318a

📥 Commits

Reviewing files that changed from the base of the PR and between 543ba5e and 28830ac.

📒 Files selected for processing (1)
  • vite.config.ts

Comment on lines +45 to +48
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>`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider validating the Umami URL format.

The umamiUrl value is directly interpolated into the src attribute without validation. While environment variables are typically trusted, a malformed URL (e.g., containing quotes or other special characters) could break the HTML or, in edge cases, introduce unintended behavior.

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

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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>`);
transformIndexHtml(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>`);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vite.config.ts` around lines 45 - 48, The transformIndexHtml hook currently
interpolates umamiUrl and umamiWebsiteId directly into scriptTag in
transformIndexHtml; add basic validation for umamiUrl before building scriptTag
(e.g., attempt to construct new URL(umamiUrl) in a try/catch or run a simple URL
regex) and only create/insert the scriptTag when the URL is valid; if validation
fails, log or warn and return the original html unchanged. Also ensure any
interpolation for umamiWebsiteId is sanitized (e.g., string-only) before
embedding to avoid injecting quotes/special chars.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant