Skip to content

Add Umami as an analytics source alongside Google Analytics - #464

Open
midego1 wants to merge 3 commits into
every-app:mainfrom
midego1:feat/umami-analytics
Open

midego1 wants to merge 3 commits into
every-app:mainfrom
midego1:feat/umami-analytics

Conversation

@midego1

@midego1 midego1 commented Oct 21, 2026

Copy link
Copy Markdown

TL;DR

Projects whose sites use Umami instead of Google Analytics get no traffic data in OpenSEO. This PR connects a project to an Umami website (self-hosted or Umami Cloud), so the dashboard, the chat and the MCP tools show its organic traffic the same way they show a GA4 property.

Closes #373.

What changes

In Project settings → Integrations there's a new Umami card. It takes the Umami URL and a login: username and password for self-hosted, or an API key for Umami Cloud. Optional request headers can be added for an auth proxy. The login is saved once per organization, and each project picks its own website from it. Once connected:

  • The dashboard shows an Organic traffic · Umami card. It has visits, visitors, pageviews and bounce rate from Umami's Organic search channel, comparing the last 28 complete days with the previous 28, plus a daily visitors trend.

  • MCP and the chat get four new tools, in the same ok/error envelope as the GA4 tools:

    • get_umami_organic_overview
    • get_umami_landing_pages: organic entry pages, to put next to Search Console
    • get_umami_page_performance: all traffic
    • get_umami_traffic_sources: referrers or channels

    Every tool also accepts channel: "all".

Screenshots

Umami card in Project settings → Integrations (connected; project, website and login blurred):

Umami integration card

Organic traffic card on the project dashboard:

Organic traffic card from Umami

Setup (self-hosted Umami)

  1. Make sure BETTER_AUTH_SECRET is set to at least 32 characters. It encrypts the stored Umami credentials, the same way the Google tokens are encrypted. The new D1 and Postgres migrations run on deploy.
  2. In Umami (v3 or newer), create a view-only user without two-factor sign-in and give it access to the websites.
  3. Open a project's Settings → Integrations → Umami, enter the Umami URL and that user's login, then choose Sign in and list websites and pick a website.
  4. For the other projects, use Choose website on the saved login.

The full guide is in docs/UMAMI_ANALYTICS.md, and the design record is in docs/maintainers/specs/0017-umami-analytics.md.

Notes for review

  • Umami version: v3+ is required, because organic filtering uses Umami's referrer regex filter, which v2 doesn't have. A v2 server is rejected when a website is picked, so it never silently reports zeros.
  • URL safety: the Umami URL goes through the existing outbound URL policy (normalizeAndValidateStartUrl), redirects aren't followed, and response bodies are size-bounded.
  • Credentials: passwords, API keys and header values are encrypted at rest. They never reach the browser, MCP output, logs or error messages.
  • Time zone: days are counted in the browser time zone captured when the website is picked. Ranges over 180 days get a monthly trend.
  • Entry pages and referrers: these use a search-engine referrer filter. Umami's filter only matches the entry pageview, so those reports show visits and visitors, not pageviews.
  • Hosted mode (open question): "Sign in and list websites" has no rate limit of its own, so on a hosted multi-tenant deployment it could be used to try passwords against a public Umami server. I'm happy to add a limiter in whatever way you prefer.
  • Not included: joining Umami entry pages with Search Console in get_search_opportunities, which stays GA4-only for now.
  • Plugin version: bumped to 1.0.24 because of the new MCP tools. Feel free to adjust.
  • Schema: adds two new tables, umami_instances and umami_connections, with SQLite and Postgres migrations and parity tests. Workspace merge and GDPR erase cover them.

Testing

  • tsc, oxlint (type-aware), knip, prettier and the plugin-skill sync all pass, and pnpm build passes.
  • pnpm test passes 1681 of 1681. That includes tests for the client, the service (real SQLite running the shipped migration), reporting and the MCP tools.
  • It's running in production on a self-hosted Cloudflare deployment against a self-hosted Umami v3 instance with 11 websites.

…y-app#373)

A project can now read its traffic from a self-hosted Umami server or
Umami Cloud. An Umami login (URL, username/password or API key, optional
auth-proxy headers) is saved once per organization with the secret and
headers encrypted by BETTER_AUTH_SECRET; each project picks its own
website from it.

- Settings > Integrations: Umami card to add a login, pick a website,
  change it, disconnect, or remove a saved login.
- Dashboard: Organic traffic card from Umami's organicSearch channel,
  last 28 days vs the previous 28, with a daily visitors trend.
- MCP and chat: get_umami_organic_overview, get_umami_landing_pages,
  get_umami_page_performance, get_umami_traffic_sources, in the GA4
  tools' ok/error envelope.
- The Umami URL passes the outbound URL policy; redirects are rejected.
- New umami_instances / umami_connections tables (SQLite + Postgres),
  covered by workspace merge and GDPR erasure.
- Plugin version 1.0.24 for the new MCP tools.
Overview totals come from Umami's Organic search channel, while entry
pages, referrers and the trend filter on the visit's referrer. The tool
text and docs now say so, and the traffic sources description no longer
promises pageviews for the referrer breakdown.
@midego1
midego1 requested a review from bensenescu as a code owner October 21, 2026 07:22
snowopsdev pushed a commit to snowopsdev/open-seo that referenced this pull request Oct 22, 2026
@alexis-morain

Copy link
Copy Markdown

Yeah !

Main added pg 0038-0039 and sqlite 0060-0061, so the Umami migrations
are regenerated on top as pg 0040 and sqlite 0062 (SQL unchanged).
Plugin version bumped to 1.0.26 past main's 1.0.25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@midego1

midego1 commented Oct 24, 2026

Copy link
Copy Markdown
Author

Merged main to resolve conflicts. The Umami migrations are regenerated on top of main’s as pg 0040 and sqlite 0062 (SQL unchanged). Plugin version is now 1.0.26, since main moved to 1.0.25.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Connect Umami as an analytics source alongside Google Analytics

2 participants