Counterscale is a simple web analytics tracker and dashboard that you self-host on Cloudflare.
It's designed to be easy to deploy and maintain, and should cost you near-zero to operate – even at high levels of traffic (Cloudflare's free tier could hypothetically support up to 100k hits/day).
NOTE: Counterscale is currently in very early development and if you're prepared to run it, expect to get your hands dirty.
If you don't have one already, create a Cloudflare account here.
- Go to your Cloudflare dashboard and set up a Cloudflare Workers subdomain
- Enable Cloudflare Analytics Engine beta for your account
- Create a Cloudflare API token. This token needs
Account.Account Analytics
permissions at a minimum. - Run
npm install
- Run
npx wrangler secret put CF_BEARER_TOKEN
→ when prompted, paste the API token you created - Run
npx wrangler secret put CF_ACCOUNT_ID
→ when prompted, paste your Cloudflare Account ID - Run
npm run deploy
– this will do two things:- Create a new worker,
counterscale
, now visible under Workers and Pages in Cloudflare - Create a new Analytics Engine dataset, called
metricsDataset
- Create a new worker,
- It should now be live. Visit
https://counterscale.{yoursubdomain}.workers.dev
.
To get started, in the project root, copy .dev.vars.example
to .dev.vars
.
Open .dev.vars
and enter the same values for CF_BEARER_TOKEN
and CF_ACCOUNT_ID
you used earlier.
Counterscale is built on Remix and Cloudflare Workers. In development, you'll run two servers:
- The Remix development server
- The Miniflare server (local environment for Cloudflare Workers)
You run both using:
npm run dev
Afterwards, the dashboard should be visible at http:https://127.0.0.1:8787.
If you want to check the production build, you can stop the dev server and run following commands:
npm run build
npm start
Then refresh the same URL in your browser (no live reload for production builds).
There is only one "database": the Cloudflare Analytics Engine dataset, which is communicated entirely over HTTP using Cloudflare's API.
Right now there is no local "test" database. This means in local development:
- Writes will no-op (no hits will be recorded)
- Reads will be read from the production Analaytics Engine dataset (local development shows production data)