Getting started

Introduction

PageView Tracker is a free, self-hosted analytics tool powered by Upstash Redis. Deploy it once, then embed the tracker on any website with two script tags - no clone or download needed.

  • A tracking script to count visits on any website
  • An embeddable banner showing online users and total visitors
  • A stats dashboard with visitors, pageviews, and top pages (private access)

Quick start

Replace https://your-app.example.com with your deployed URL (e.g. https://tracker.josejavierdiazglez.com). For local development, use http://localhost:3000.

1. Tracking script (invisible)

Drop this in any HTML page to count visits:

<script
  src="https://your-app.example.com/script"
  data-site="example.com"
  data-auto="true"
  defer
></script>
AttributeRequiredDescription
data-siteYesYour site identifier (e.g. example.com)
data-pathNo*Track a specific path only (precision mode)
data-autoNo*Set to "true" to track every page automatically
data-debugNoEnable console logging

*Use either data-path (single page) or data-auto="true" (all pages).

2. Visitor banner (visible)

Add the live stats banner to your site. By default it shows only the counter - no external link:

<script
  src="https://your-app.example.com/widget.js"
  data-site="example.com"
  data-lang="en"
  defer
></script>

Spanish version:

<script
  src="https://your-app.example.com/widget.js"
  data-site="example.com"
  data-lang="es"
  defer
></script>
AttributeRequiredDescription
data-siteYesYour site identifier
data-langNoen (default) or es
data-statsNoSet to "true" to show a "see stats" link
data-positionNobottom (default) or top

Default banner: 1 online · 42 visitors (online hidden when 0)

With data-stats="true": adds · see stats → linking to your dashboard

3. View stats

Open the dashboard at https://your-app.example.com/stats?site=example.com and enter your STATS_SECRET.

Only you can access the dashboard and detailed API. The widget banner still shows online and visitors publicly.


Use in another project

No clone needed. After deploying PageView Tracker once, paste these two lines in any website:

<script src="https://your-app.example.com/script" data-site="my-blog.com" data-auto="true" defer></script>
<script src="https://your-app.example.com/widget.js" data-site="my-blog.com" data-lang="es" defer></script>

Each site uses a unique data-site identifier. Data is stored in your Upstash Redis.

To view full stats, go to /stats?site=your-site and sign in with your secret.


API endpoints

Public

Live counters (widget)

GET /api/v1/live?site=example.com

Response: { "online": 2, "visitors": 42 }

Track a visit

GET /api/v1/track?site=example.com&path=/

Private (requires STATS_SECRET)

Use the Authorization: Bearer <STATS_SECRET> header or sign in at /stats.

Get page views

GET /api/v1/views?site=example.com&path=/

Response: { "views": 123 }

Get stats

GET /api/v1/stats?site=example.com&type=overview
GET /api/v1/stats?site=example.com&type=timeseries
GET /api/v1/stats?site=example.com&type=pages

Environment variables

UPSTASH_REDIS_REST_URL=
UPSTASH_REDIS_REST_TOKEN=
# Local: http://localhost:3000
# Production: https://tracker.josejavierdiazglez.com
NEXT_PUBLIC_APP_URL=http://localhost:3000
STATS_SECRET=your-long-secret

Set NEXT_PUBLIC_APP_URL to your public URL in production. Scripts automatically use the correct API origin based on where they are served from.


Privacy

  • No tracking cookies, no PII stored
  • The script generates an anonymous ID (UUID) and stores it in the embedded site's localStorage; only its SHA-256 hash (16 chars) is stored server-side
  • If localStorage is unavailable, a hash of IP + User-Agent is used as fallback
  • Online = users with the page open (heartbeat every 30s; 2-minute active window)
  • Visitors = unique people who have visited the site at least once
  • 30-minute deduplication window per page
  • Rate limited: 5 requests/min per IP