Skip to content

Count entry and exit pages per visit on ClickHouse - #4638

Open
pcbeingused333 wants to merge 1 commit into
umami-software:devfrom
pcbeingused333:fix/clickhouse-entry-exit-per-visit
Open

pcbeingused333 wants to merge 1 commit into
umami-software:devfrom
pcbeingused333:fix/clickhouse-entry-exit-per-visit

Conversation

@pcbeingused333

@pcbeingused333 pcbeingused333 commented Oct 17, 2026 •

Copy link
Copy Markdown

Without event filters, the ClickHouse branch of getPageviewMetrics computes entry/exit pages from website_event_stats_hourly, merging entry_url / exit_url grouped by session (group by s). That keeps one entry page (the first visit's) and one exit page (the last visit's) per session. Any page that starts or ends a later visit is never counted, so the Entry and Exit tables are missing pages. The relational branch takes the entry/exit page of every visit (distinct on (visit_id)), so Postgres/MySQL and ClickHouse instances report different pages for the same traffic.

How it shows up

Seeded data: the same 37 events (8 visitors, 15 visits) sent through /api/send with fixed timestamps to two instances built from dev. One runs on PostgreSQL only; the other runs on PostgreSQL + ClickHouse. Then GET /api/websites/:id/metrics?type=entry|exit:

PostgreSQL ClickHouse (before) ClickHouse (after)
entry / 8, /blog/b 6 / 8 / 8, /blog/b 6
exit /blog/a 6, /blog/b 6, / 3 /blog/b 5, / 3 /blog/a 6, /blog/b 6, / 3

Six visitors came back for a second visit that started on /blog/b. ClickHouse dropped those entries, and the exits of their first visits (/blog/a). The "after" column is the patched query run against the same ClickHouse data.

With an event filter (for example path=…), ClickHouse takes the other branch, which already groups per visit. The two backends agree there.

Change

group by s → group by s, visit_id for entry / exit in the hourly-table branch. visit_id is part of the table's primary key.

Tests

src/queries/sql/pageviews/getPageviewMetrics.test.ts (new), in the style of getPageviewExpandedMetrics.test.ts. It checks that the ClickHouse entry/exit query merges per visit. It fails on dev and passes with the change.

npx vitest run src/queries/sql src/lib   # 61 files, 589 tests passed
npx biome check <changed files>          # clean
npx tsc --noEmit                          # no errors

Also seen in the same comparison, not changed here

  • /metrics/expanded?type=entry|exit: pageviews differs. The relational query joins only the entry/exit event of each visit (x.target_created_at = website_event.created_at), so / gets 9 pageviews. ClickHouse joins every event of the visit, so / gets 21. visitors / visits match. With a path filter, the relational expanded query returns nothing, because the filter has to match the entry event itself. ClickHouse returns the entry pages of visits that viewed that path, as the non-expanded endpoint does on both backends. Happy to align one way or the other if you say which is intended.
  • /daterange: on ClickHouse, endDate comes from the hourly table, so it's truncated to the hour (23:00:00 vs 23:30:30).
  • /revenue/stats comparison.sum is null on PostgreSQL and 0 on ClickHouse when the comparison period has no revenue.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Without event filters, the ClickHouse entry/exit metrics read
website_event_stats_hourly and merged entry_url / exit_url per session
(`group by s`). That keeps one entry page (the first visit's) and one exit
page (the last visit's) per session, so a page that starts or ends any
later visit is never counted. The relational query takes the entry/exit
page of every visit (`distinct on (visit_id)`).

Group the hourly states by session and visit, so both backends count the
same pages.

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

vercel Bot commented Oct 17, 2026

Copy link
Copy Markdown

@pcbeingused333 is attempting to deploy a commit to the Umami Software Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps

greptile-apps Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] This PR appears safe to merge.

Summary

Updates ClickHouse entry/exit metrics to select a page for each visit, matching the relational query.

  • ClickHouse Entry and Exit metrics count pages from each visit.

Reviews (1) · Last reviewed commit: "Count entry and exit pages per visit on ..." · Reviewed by Greptile

This branch has not been deployed

No deployments
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.

1 participant