Analytics
Use server-side analytics when you want redirect and page activity without adding browser tracking JavaScript. vanityURLs sends analytics from the Worker with ctx.waitUntil(), so provider failures should not delay redirects.
For provider selection and privacy tradeoffs, read Choosing privacy-friendly analytics for short links. For event names, provider payloads, IP handling, and blocked-traffic behavior, read Analytics.
flowchart LR A["Request
reaches
Worker"] --> B{"Request type"} B -->|"valid short link"| C["Redirect
response"] C --> D["redirect event"] B -->|"valid local page"| E["Public page
response"] E --> F["pageview event"] B -->|"unknown slug"| G["404 page"] G --> H["short-link-miss
event"] B -->|"lookup"| I["Lookup response"] I --> J["pageview event"] D --> K["ctx.waitUntil
analytics send"] F --> K H --> K J --> K K --> L["Umami or Fathom"]
Decide whether to enable analytics
Leave analytics disabled during the first setup unless you already know what question the reports need to answer. A working redirector with no analytics is a valid production choice.
Enable analytics when you need to measure campaign links, printed QR codes, launch traffic, old-link usage, lookups, or realistic missing-link activity.
Choose a provider
Set ANALYTICS_PROVIDER in wrangler.toml.
| Value | Use when |
|---|---|
disabled | You do not want vanityURLs to send analytics events |
umami | You want structured event properties in Umami |
fathom | You want Fathom pageviews and named events |
umami,fathom | You are migrating providers or comparing both temporarily |
Keep dual collection temporary
Configure analytics solution
Configure either Umami or Fathom in wrangler.toml.
For Umami, configure the provider, endpoint, website ID, and IP mode:
[vars]
ANALYTICS_PROVIDER = "umami"
UMAMI_ENDPOINT = "https://cloud.umami.is/api/send"
UMAMI_WEBSITE_ID = "<umami website id>"
UMAMI_GEO_IP_MODE = "truncated"
Prefer less location detail
truncated or none for UMAMI_GEO_IP_MODE unless you have a specific operational need for full geo reporting.OR
For Fathom, configure the provider, site ID, and collection endpoint:
[vars]
ANALYTICS_PROVIDER = "fathom"
FATHOM_SITE_ID = "<fathom site id>"
FATHOM_ENDPOINT = "https://cdn.usefathom.com/"
The Worker does not need the Fathom management API key for collection. Use secrets only for provider API keys needed by local helper scripts.
Keep edge protection in front
Requests blocked by Cloudflare before the Worker do not emit vanityURLs analytics events. Review WAF, rate limiting, bot, and AI crawler decisions with Network protection, and Access decisions with Access control.
Treat Cloudflare network controls and the runtime blocklist as analytics quota protection, not only as security features.
Verify locally
Before deployment, run:
npm run smoke:analytics
The smoke test builds the instance and intercepts analytics calls locally. It verifies the event path without sending data to the provider.
Verify after deployment
- Visit
https://v8s.link/lookupand confirm pageviews with the analytics dashboard - Visit a valid short link; confirm a
redirectevent - Visit a realistic missing slug; confirm a
short-link-missevent - Visit
/file.php; confirm it is blocked without a miss event - Check Workers Logs for umami or fathom tracking failed
Provider dashboards can lag. Use Workers Logs first when debugging ingestion errors.