Skip to content

v0.2.0-beta.1 — Custom events, comparisons, and ad-blocker fixes

Pre-release
Pre-release

Choose a tag to compare

@al3xg0r al3xg0r released this 12 Aug 03:39
· 9 commits to main since this 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. New POST /track endpoint,
    new GET /events breakdown, 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, an X-Robots-Tag header, 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 shared workers.dev domain is a more
    generic target for filter lists).

Fixed

  • Ad blockers silently dropping visits, root-caused properly this time.
    Renamed /collect/event and /heartbeat/ping (old paths still work as
    aliases), renamed tracker.jswidget.js (old path still works as an
    alias) — both common blocklist patterns. More importantly: switched from
    navigator.sendBeacon() to fetch(..., { 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 ci failing on Cloudflare's build step due to wrangler version
    drift between package.json and package-lock.json.
  • Cron trigger deploy failure — Cloudflare's day-of-week field is 1-7
    (1 = Sunday), not the standard Unix 0-6; fixed by using SUN instead 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 as https://example.com instead 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 CACHEAGANALITICS_CACHE for clarity.
  • Dashboard cache TTL raised from 5 to 15 minutes (reduces D1 read volume);
    configurable in src/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

  1. Re-run npm run db:migrate:remote — adds the new events table and
    indexes (safe to re-run any time, only ever creates what's missing).
  2. If you haven't already: create a KV namespace named AGANALITICS_CACHE
    and update wrangler.toml if you're still on the old CACHE binding.
  3. 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