This project is a Visitor Count API built with Cloudflare Workers and Upstash Redis. It helps you track page visits and unique visitors across multiple web apps in real-time and at scale.
- Total Visits: Counts how many times your site has been visited.
- Unique Visitors: Tracks unique visitors by IP, resetting every 24 hours.
- Timestamps: Records when your site was first and last visited.
- Multi-App Support: Track multiple web apps independently.
- CORS Enabled: Safe cross-origin requests.
- Real-Time: Updates instantly.
- Scalable and Fast: Runs on Cloudflare's edge with Upstash Redis.
Fetch the current visitor statistics for a specific app.
Response Example:
{
"success": true,
"data": {
"count": 1250,
"lastVisit": "2024-01-15T10:30:00.000Z",
"firstVisit": "2024-01-01T08:15:00.000Z",
"uniqueVisitors": 892
},
"webApp": "my-awesome-app"
}Increment the visitor count for your app. Updates timestamps and counts unique visitors based on IP.
Response Example:
{
"success": true,
"data": {
"count": 1251,
"lastVisit": "2024-01-15T10:35:00.000Z",
"firstVisit": "2024-01-01T08:15:00.000Z",
"uniqueVisitors": 892
},
"webApp": "my-awesome-app"
}- Node.js installed
- Cloudflare account with Workers enabled
- Upstash Redis database
-
Clone the repository and install dependencies:
npm install
-
Create a Redis database on Upstash: Go to Upstash Console, set up a Redis instance, and copy your REST URL and token.
-
Add your Upstash credentials to
wrangler.tomlas environment variables:[vars] UPSTASH_REDIS_REST_URL = "your-upstash-rest-url" UPSTASH_REDIS_REST_TOKEN = "your-upstash-token"
-
Deploy your worker using Wrangler:
wrangler deploy
Run the worker locally:
npm run devasync function trackVisit(webAppName) {
const res = await fetch(`https://your-worker.yourdomain.workers.dev/api/visitor-count/${webAppName}`, {
method: 'POST'
});
const data = await res.json();
console.log(`Total visits: ${data.data.count}`);
}
async function getVisitorCount(webAppName) {
const res = await fetch(`https://your-worker.yourdomain.workers.dev/api/visitor-count/${webAppName}`);
const data = await res.json();
return data.data.count;
}
// Usage
trackVisit('my-blog');
const count = await getVisitorCount('my-blog');import { useState, useEffect } from 'react';
function useVisitorCount(webAppName, trackOnMount = true) {
const [visitorData, setVisitorData] = useState(null);
const [loading, setLoading] = useState(true);
const API_BASE = 'https://your-worker.yourdomain.workers.dev/api/visitor-count';
const trackVisit = async () => {
try {
const res = await fetch(`${API_BASE}/${webAppName}`, { method: 'POST' });
const data = await res.json();
setVisitorData(data.data);
} catch (e) {
console.error('Error tracking visit:', e);
}
};
const getCount = async () => {
try {
setLoading(true);
const res = await fetch(`${API_BASE}/${webAppName}`);
const data = await res.json();
setVisitorData(data.data);
} catch (e) {
console.error('Error getting count:', e);
} finally {
setLoading(false);
}
};
useEffect(() => {
if (trackOnMount) {
trackVisit();
} else {
getCount();
}
}, [webAppName]);
return { visitorData, loading, trackVisit, getCount };
}<div id="visitor-count">Loading...</div>
<script>
const API_BASE = 'https://your-worker.yourdomain.workers.dev/api/visitor-count';
const WEB_APP_NAME = 'my-website';
async function updateVisitorCount() {
try {
const res = await fetch(`${API_BASE}/${WEB_APP_NAME}`, { method: 'POST' });
const data = await res.json();
document.getElementById('visitor-count').innerText =
`Visitors: ${data.data.count} | Unique: ${data.data.uniqueVisitors}`;
} catch {
document.getElementById('visitor-count').innerText = 'Error loading count';
}
}
updateVisitorCount();
</script>- count: Total visits (increments on each POST)
- uniqueVisitors: Unique visitor count (IP-based, resets daily)
- firstVisit: Timestamp of first visit
- lastVisit: Timestamp of last visit
- Runs at Cloudflare's edge for low latency.
- Redis operations are optimized for speed.
- IP-based unique visitor tracking with 24-hour expiry.
- CORS enabled for safe cross-origin requests.
- Input validation and error handling implemented.
To serve your worker on a custom domain like visitor-count.clustrix.tech:
- Manage DNS for your domain in Cloudflare.
- Add a CNAME or A record pointing your subdomain to Cloudflare.
- Add the following to
wrangler.toml:[[routes]] pattern = "visitor-count.clustrix.tech/api/visitor-count/*" zone_id = "your-cloudflare-zone-id"
- Deploy using:
wrangler deploy
- Use the Cloudflare Workers dashboard to check usage and logs.
- Monitor Redis usage and performance in the Upstash Console.
- Use
wrangler tailto stream logs during development.
If you have any questions or need help with integrating or extending this API, feel free to reach out.
Contact me at: hello@sagarkundu.live
Happy tracking!