Home
Softono

Cloudcounter

Open source TypeScript
14
Stars
3
Forks
3
Issues
1
Watchers
5 months
Last Commit

 About Cloudcounter

Privacy-focused web analytics running on Cloudflare Pages + D1. A serverless port of GoatCounter.

Platforms

Web Self-hosted Cloud

Languages

TypeScript

Links

Need Help Installing Cloudcounter?

We provide expert installation service for this software. Our team will install, configure, and secure Cloudcounter on your server. plans start at just $30.

Cloudcounter

View on GitHub

CloudCounter

License: EUPL Cloudflare Pages TypeScript Node.js 18+

A standalone port of GoatCounter to run entirely on Cloudflare's edge infrastructure.

CloudCounter brings GoatCounter's privacy-focused analytics to Cloudflare Pages + D1, requiring no external servers or databases. Deploy once and track pageviews across your sites with a single JavaScript snippet.

Features

  • Pageview tracking with session deduplication
  • Top pages, referrers, browsers, operating systems, locations
  • Screen size breakdown
  • Event tracking support
  • Privacy-first: no cookies, session hash only
  • Server-rendered dashboard
  • Data retention policies

Screenshots

Dashboard with bar chart

Dashboard with line chart

Additional screenshots available in the media folder.

Prerequisites

  • Node.js 18+
  • Wrangler CLI
  • Cloudflare account with Pages and D1 access

Quick Start

1. Clone and install

git clone https://github.com/philippdubach/cloudcounter.git
cd cloudcounter
npm install

2. Create Cloudflare resources

# Create D1 database
wrangler d1 create cloudcounter

# Create KV namespace for sessions
wrangler kv namespace create SESSIONS

3. Update wrangler.toml

Edit wrangler.toml and add your database_id and KV namespace id:

[[d1_databases]]
binding = "DB"
database_name = "cloudcounter"
database_id = "YOUR_DATABASE_ID_HERE"

[[kv_namespaces]]
binding = "SESSIONS"
id = "YOUR_KV_NAMESPACE_ID_HERE"

4. Initialize database

wrangler d1 execute cloudcounter --file=./migrations/0001_init.sql

5. Set dashboard password

wrangler secret put DASHBOARD_PASSWORD

6. Deploy

wrangler pages deploy public

7. Add tracking script to your site

<script async src="https://your-analytics.pages.dev/count.js"></script>

Local Development

# Start local dev server
npm run dev

# Apply migrations to local D1
npm run db:migrate:local

Configuration

Environment Variables

Variable Description Default
SITE_NAME Dashboard title "My Analytics"
DATA_RETENTION_DAYS Days to keep data (0 = unlimited) "0"

Secrets

Secret Description
DASHBOARD_PASSWORD Password for dashboard access

Tracking Script

Basic usage

The script auto-tracks pageviews on load:

<script async src="https://your-analytics.pages.dev/count.js"></script>

Manual tracking

// Custom pageview
cloudcounter.count({ path: '/custom-path', title: 'Custom Title' });

// Event tracking
cloudcounter.count({ path: 'button-click', title: 'Sign Up Button', event: true });

Click tracking

Add data-cloudcounter-click attribute to elements:

<button data-cloudcounter-click="signup-btn">Sign Up</button>

Disable tracking

cloudcounter.skip();   // Disable for this session
cloudcounter.enable(); // Re-enable

API

Track pageview

GET/POST /api/count?p=/path&t=Title&r=referrer
Parameter Description Required
p Page path Yes
t Page title No
r Referrer URL No
e Event flag (1 or true) No
s Screen width No

Returns: 1x1 transparent GIF

Architecture

cloudcounter/
├── functions/           # Cloudflare Pages Functions
│   ├── _middleware.ts   # Auth guard
│   ├── _worker.ts       # Cron handler
│   ├── api/count.ts     # Hit tracking endpoint
│   ├── index.ts         # Dashboard
│   ├── login.ts         # Login page
│   └── logout.ts        # Logout
├── src/
│   ├── lib/             # Core utilities
│   └── stats/           # Query functions
├── public/
│   ├── count.js         # Tracking script
│   ├── dashboard.js     # Dashboard charts
│   └── dashboard.css    # Dashboard styles
└── migrations/          # D1 schema

Database Schema

Table Description
paths Normalized page paths
refs Referrer URLs
browsers Browser names
systems Operating systems
hits Raw pageview data
hit_counts Hourly aggregates
hit_stats Daily aggregates
browser_stats Browser breakdown
system_stats OS breakdown
location_stats Country breakdown
size_stats Screen size breakdown

Cron Jobs

Daily at 3 AM UTC:

  • Apply data retention policy
  • Vacuum unused referrers
  • Clean orphaned dimension records

Credits

This project is a port of GoatCounter by Martin Tournoij.

License

Licensed under the EUPL.