v0.2.0-beta.1 — Custom events, comparisons, and ad-blocker fixes
Pre-release
Pre-release
AG Analytics v0.2.0-beta.1
A substantial update since v0.1.0-beta.2 — new features (custom events, period
comparisons, UTM campaigns, automatic data retention) alongside a series of
ad-blocker compatibility fixes discovered through real-world testing.
Added
- Custom events / goals API.
agEvent("signup", { plan: "pro" })in your own
page code tracks any action, not just page views. NewPOST /trackendpoint,
newGET /eventsbreakdown, and a "Custom events" dashboard panel. - Period-over-period comparison. Every stat card now shows a delta against
the immediately preceding window of the same length (e.g. this week vs last
week), with an arrow that reflects the real direction and a color that
reflects whether the change is actually good for that metric — a drop in
bounce rate is shown in green, not red. - Bot/crawler filtering. Known search engine crawlers, SEO tools, uptime
monitors, and scripted HTTP clients (curl, headless browsers, etc.) are
filtered out server-side before being recorded anywhere. - Campaigns panel, breaking visits down by
utm_campaign. - Country flags and full country names, referrer favicons.
- Automatic weekly data cleanup via a Cron Trigger — visits, sessions, and
events older than 13 months are deleted automatically, so D1 storage doesn't
grow forever on the free plan. - View tracking code any time, not just right after creating a site (new
"Code" button), plus a Delete site button with confirmation. - Customizable dashboard: show/hide individual panels, saved per browser.
- Interactive chart: hover for exact time, views, and visitors at a point,
with gridlines and axis labels. - Hyperlinked entries in Top pages and Referrers.
robots.txt, anX-Robots-Tagheader, and a<meta name="robots">tag —
the dashboard/tracking domain is never meant to appear in search results,
especially relevant once you're serving it from your own custom domain.- A guide for using a custom domain instead of
*.workers.dev(reduces
ad-blocker false positives, since the sharedworkers.devdomain is a more
generic target for filter lists).
Fixed
- Ad blockers silently dropping visits, root-caused properly this time.
Renamed/collect→/eventand/heartbeat→/ping(old paths still work as
aliases), renamedtracker.js→widget.js(old path still works as an
alias) — both common blocklist patterns. More importantly: switched from
navigator.sendBeacon()tofetch(..., { keepalive: true }), since
sendBeacon()requests are tagged by the browser itself as resource type
"ping", which several ad-blocker configurations (Brave Shields, some
uBlock Origin lists) block categorically, regardless of URL or domain —
renaming things alone doesn't fix that; this does. - KV write-quota exhaustion. "Online now" tracking previously wrote to KV
on every heartbeat; moved entirely to D1, which needs no extra writes.
Free-plan KV allows only 1,000 writes/day and was being exhausted within
minutes under light traffic. npm cifailing on Cloudflare's build step due towranglerversion
drift betweenpackage.jsonandpackage-lock.json.- Cron trigger deploy failure — Cloudflare's day-of-week field is
1-7
(1= Sunday), not the standard Unix0-6; fixed by usingSUNinstead of
a numeric day. - Double
https://in generated links when a site's domain was saved with
a protocol already in it (e.g. pasted ashttps://example.cominstead of
example.com). Domains are now normalized on save, and already-existing
bad values are fixed defensively when building links. - URL hash fragments (
#section) were silently stripped from every page
URL before storage, merging genuinely different sections/hash-routed pages
into a single "Top pages" row. Hash fragments are now preserved (query
strings are still cleaned of UTM noise, as before). - Sidebar site-selector layout.
Changed
- KV binding renamed
CACHE→AGANALITICS_CACHEfor clarity. - Dashboard cache TTL raised from 5 to 15 minutes (reduces D1 read volume);
configurable insrc/lib/kv.js. - Default theme switched from dark to light, with a refreshed visual design.
- Search engine traffic (Google, Bing, DuckDuckGo, etc.) broken out into its
own panel, separate from regular referring websites.
Known limitations
- Single admin account per deployment (no multi-user roles yet).
- No CSV/JSON export yet.
- No long-lived API token for external integrations (e.g. a bot/script) —
only the short-lived (12h) dashboard login token exists today. - No automated test suite yet.
Upgrading from beta.2
- Re-run
npm run db:migrate:remote— adds the neweventstable and
indexes (safe to re-run any time, only ever creates what's missing). - If you haven't already: create a KV namespace named
AGANALITICS_CACHE
and updatewrangler.tomlif you're still on the oldCACHEbinding. - Existing embedded snippets (
/tracker.js,/collect,/heartbeat) keep
working unchanged — no action needed on already-tracked sites, though new
sites will get/widget.js-based snippets going forward.
Full Changelog: v0.1.0-beta.2...v0.2.0-beta.1