swirl.events

What we count, and what we don't

swirl.events runs first-party, aggregate-only analytics. Counters live in our own database; we don't load Google Analytics, Mixpanel, Facebook Pixel, or any other third-party tracker. This page is the complete inventory of every numeric we keep about visitor activity.

The counters

Every row in the table below is one type of counter. Each counter is keyed on (kind, event_id, bucket, day) — never on a visitor identifier, session, or fingerprint.

Kind Per-event? Bucket When it fires
view Yes The event detail page loads in your browser.
ics Yes You download the .ics calendar file for an event.
share_click Yes You open an invite-link URL (/i/<token>/).
search No Normalized search query (lowercased, whitespace-collapsed, max 80 chars, drops anything with @) You submit the search box.
referrer Yes One of: direct, search, social, share, internal An event detail page loads — we classify document.referrer in your browser and send only the bucket, not the URL.

What we explicitly do not capture

  • No session IDs, no device fingerprints, no user-agent strings.
  • No IP addresses are stored. Your IP is used only in-request — for the one-time IP-geo redirect on the home page and for a tiny in-memory rate-limit counter on the analytics beacon — and never persisted to our database.
  • No raw Referer header. The classifier runs in your browser; we receive only the resulting bucket above.
  • No click sequences, replay, heatmaps, scrollmaps.
  • No per-visitor location finer than the city you picked yourself via the location pill.
  • No third-party SDKs.

How to opt out

We honor the Do Not Track request header. If your browser sends DNT: 1, no counter will increment from your visits — checked both in the browser before the beacon fires and on the server as defense-in-depth.

If you don't have DNT but want to opt out anyway, set the local-storage key swirl-no-track to "1" in your browser devtools. The beacon will never fire from that browser on this domain.

Who sees the numbers

  • Event hosts see counts for their own events in the editor and on /manage/insights.
  • Site-wide trending search terms are visible to every signed-in host so they can see what visitors are looking for. (The query itself is aggregate; we have no way to link a query to who typed it.)
  • Any count below 5 is suppressed everywhere — host dashboards, the editor, and the API response itself — so small-N reverse-engineering can't identify individual visitors of small events.

Retention

Per-day counters older than 90 days are compacted into per-month summaries. The raw day-level grain disappears at that point — we keep the totals, not the daily shape.

Source of truth for this list: crates/swirl-events-api/src/metrics.rs. If this page and that module ever disagree, the module is right and this page has drifted — please let us know.