add dashboard filtering to analytics
All checks were successful
deploy / deploy (push) Successful in 1m19s

Click any row in pages, sources, countries, or devices tables to
filter the entire dashboard by that dimension. Active filters show
as dismissible chips. Filters thread through all queries including
previous-period deltas. 1050 tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-23 13:46:34 +00:00
parent 6eda1de1bc
commit 7ceee9c814
6 changed files with 328 additions and 61 deletions

View File

@@ -231,6 +231,62 @@ defmodule Berrypod.AnalyticsTest do
end
end
describe "filtering" do
test "count_visitors respects country_code filter" do
v1 = :crypto.strong_rand_bytes(8)
v2 = :crypto.strong_rand_bytes(8)
insert_event(%{visitor_hash: v1, country_code: "GB"})
insert_event(%{visitor_hash: v2, country_code: "US"})
assert Analytics.count_visitors(today_range(), %{country_code: "GB"}) == 1
end
test "top_pages respects referrer_source filter" do
v1 = :crypto.strong_rand_bytes(8)
v2 = :crypto.strong_rand_bytes(8)
insert_event(%{visitor_hash: v1, pathname: "/", referrer_source: "Google"})
insert_event(%{visitor_hash: v2, pathname: "/about", referrer_source: "Facebook"})
pages = Analytics.top_pages(today_range(), filters: %{referrer_source: "Google"})
assert length(pages) == 1
assert hd(pages).pathname == "/"
end
test "bounce_rate respects filter" do
s1 = :crypto.strong_rand_bytes(8)
s2 = :crypto.strong_rand_bytes(8)
# GB visitor bounces (1 pageview)
insert_event(%{session_hash: s1, country_code: "GB"})
# US visitor doesn't bounce (2 pageviews)
insert_event(%{session_hash: s2, country_code: "US", pathname: "/"})
insert_event(%{session_hash: s2, country_code: "US", pathname: "/about"})
assert Analytics.bounce_rate(today_range(), %{country_code: "GB"}) == 100
assert Analytics.bounce_rate(today_range(), %{country_code: "US"}) == 0
end
test "multiple filters combine with AND logic" do
v1 = :crypto.strong_rand_bytes(8)
v2 = :crypto.strong_rand_bytes(8)
insert_event(%{visitor_hash: v1, country_code: "GB", browser: "Chrome"})
insert_event(%{visitor_hash: v2, country_code: "GB", browser: "Firefox"})
assert Analytics.count_visitors(today_range(), %{country_code: "GB", browser: "Chrome"}) ==
1
end
test "unknown filter keys are ignored" do
v1 = :crypto.strong_rand_bytes(8)
insert_event(%{visitor_hash: v1})
assert Analytics.count_visitors(today_range(), %{nonexistent: "val"}) == 1
end
end
describe "delete_events_before/1" do
test "deletes old events" do
old = DateTime.add(DateTime.utc_now(), -400, :day) |> DateTime.truncate(:second)