Plausible Analytics for Astro with Cloudflare Workers
Proxy Plausible Analytics through Cloudflare Workers on your Astro site. Free 100K requests/day setup that bypasses ad blockers for accurate, real visitor stats.

Plausible Analytics is a privacy-first, open-source alternative to Google Analytics. It’s lightweight (under 1KB script), uses no cookies, and tracks no personal data. With over 19,000 paying subscribers and 260 billion pageviews tracked, it’s the most popular privacy-focused analytics tool among developers.
You can self-host Plausible on your own servers. Check Install Plausible With One Click for a quick setup, or use one of the best self-hosted server panels for easy deployment.
Astro is a web framework built for speed, and it now runs natively on Cloudflare. After Cloudflare acquired Astro in January 2026, the @astrojs/cloudflare adapter dropped Pages support entirely. v13+ deploys exclusively to Cloudflare Workers. You can deploy your Astro site on Cloudflare or build a free blog with Astro & Cloudflare to get started. For a deeper look at framework choices, see the Astro vs Next.js vs TanStack Start comparison.
In this guide, you’ll set up Plausible Analytics for your Astro site using Cloudflare Workers as a proxy. The result: accurate analytics that bypass ad blockers, served from your own domain, on a free plan.
- Track real visitor data without ad-blocker interference
- Proxy Plausible scripts through your own domain via Cloudflare Workers
- Free setup (100,000 requests/day on Cloudflare’s free plan)
- Works with Plausible Cloud or self-hosted Plausible Community Edition
Why proxy Plausible Analytics through Cloudflare Workers?
Ad blockers and privacy-focused browsers routinely block requests to plausible.io. This can cause you to lose 20-30% of your analytics data. If you’re using tools like NextDNS or browser-level ad blockers on your own devices, you already know how aggressively they block analytics scripts.
A proxy solves this by routing Plausible requests through your own domain. To your visitors’ browsers, the analytics script looks like part of your site, not a third-party tracker. Ad blockers can’t distinguish it from regular site traffic.
Works with any static site
This proxy approach works with any static site generator or framework, not just Astro. Hugo, Next.js, Eleventy, plain HTML. If you can add a script tag to your head, you can use this setup. The Cloudflare Worker handles the proxying regardless of your build tool.
For more on blocking ads and trackers at the DNS level, see how to block ads and tracking with DNS protection.
Why use Cloudflare Workers instead of redirects?
If you’re deploying to Cloudflare Pages, you might think you can use the _redirects file to proxy Plausible requests. You can’t. Cloudflare Pages only supports relative-path redirects. It cannot proxy to external URLs.
Attempting to add a proxy redirect like this will fail:
Found invalid redirect lines:
09:59:12.187 - #1: /js/script.js https://domain.com/js/plausible.outbound-links.js 200
09:59:12.187 Proxy (200) redirects can only point to relative paths. Got https://domain.com/js/plausible.outbound-links.js
09:59:12.187 - #2: /api/event https://domain.com/api/event 200
09:59:12.187 Proxy (200) redirects can only point to relative paths. Got https://domain.com/api/event
Cloudflare Workers don’t have this limitation. They can fetch from any external URL and return the response, making them the right tool for proxying Plausible on Cloudflare.
Proxying Plausible through Cloudflare Workers (step by step)
Cloudflare Workers offers a free plan with 100,000 requests per day. That’s more than enough for most sites. All you need is a free Cloudflare account.
Free tier is enough
Cloudflare Workers free plan includes 100,000 requests/day. A typical site loading the Plausible script once per pageview will stay well within this limit.
Step 1: Create a Worker
Go to the Workers & Pages section in your Cloudflare dashboard and click Create application. Then click Create Worker in the Workers tab. Give your worker a name that doesn’t suggest analytics. Something like theme-assets or cdn-helper works well. Click Deploy.
Create Cloudflare Worker:

Deploy Cloudflare Worker:

Step 2: Add the Worker code (ES Modules)
Click Edit Code, delete the default code, and replace it with the code below.
Service Worker syntax is deprecated
The old addEventListener('fetch', ...) syntax is deprecated by Cloudflare. The code below uses the recommended ES Modules format. If you’re updating from an older setup, replace your entire worker script.
Use this version if you’re on Plausible’s hosted cloud service.
// Replace 'pa-XXXXX.js' with your site-specific script ID
// Find it in Plausible: Site Settings → General → Data Snippets
const ProxyScript = 'https://plausible.io/js/pa-XXXXX.js';
const ScriptPath = '/theone/script';
const Endpoint = '/theone/event';
export default {
async fetch(request, env, ctx) {
ctx.passThroughOnException();
const url = new URL(request.url);
const pathname = url.pathname;
if (pathname.startsWith(ScriptPath)) {
return getScript(request, ctx);
} else if (pathname === Endpoint) {
return postData(request);
}
return new Response(null, { status: 404 });
}
}
async function getScript(request, ctx) {
let response = await caches.default.match(request);
if (!response) {
response = await fetch(ProxyScript);
ctx.waitUntil(caches.default.put(request, response.clone()));
}
return response;
}
async function postData(request) {
const req = new Request(request);
req.headers.delete('cookie');
return await fetch('https://plausible.io/api/event', req);
}Replace pa-XXXXX.js with your actual site-specific script ID. You can find it in your Plausible dashboard under Site Settings → General → Data Snippets. The theone path segment can be anything you want. Just keep it consistent across ScriptPath and Endpoint.
Use this version if you’re running Plausible Community Edition on your own server.
// Replace with your self-hosted Plausible domain
const ProxyScript = 'https://plausible.yourdomain.com/js/pa-XXXXX.js';
const ScriptPath = '/theone/script';
const Endpoint = '/theone/event';
export default {
async fetch(request, env, ctx) {
ctx.passThroughOnException();
const url = new URL(request.url);
const pathname = url.pathname;
if (pathname.startsWith(ScriptPath)) {
return getScript(request, ctx);
} else if (pathname === Endpoint) {
return postData(request);
}
return new Response(null, { status: 404 });
}
}
async function getScript(request, ctx) {
let response = await caches.default.match(request);
if (!response) {
response = await fetch(ProxyScript);
ctx.waitUntil(caches.default.put(request, response.clone()));
}
return response;
}
async function postData(request) {
const req = new Request(request);
req.headers.delete('cookie');
return await fetch('https://plausible.yourdomain.com/api/event', req);
}Replace plausible.yourdomain.com with your actual self-hosted Plausible domain, and pa-XXXXX.js with your site-specific script ID.
Performance optimization (optional)
You can reduce proxy latency from ~140ms to ~9ms by returning an immediate 202 response and forwarding the event asynchronously. In the postData function, replace the final return with ctx.waitUntil(fetch(...)) and return a new Response('OK', { status: 202 }). Note: some users have reported issues with request stream access after the response is sent, so test this carefully.
Edit Worker:

Add Code:

Once you’ve added the code, click Save and Deploy in the top right.
Step 3: Verify the Worker is working
Test your worker by accessing it directly:
https://your-worker-name.your-cloudflare-username.workers.dev/theone/script
You should see JavaScript code returned (the Plausible script). If you get a 404, double-check the ScriptPath variable in your worker code matches the URL path you’re testing.
Step 4: Run the proxy as a subdirectory
Running the proxy under a subdirectory of your main domain (e.g., example.com/theone/) is better than using a separate subdomain. It keeps requests first-party, which avoids cookie restrictions and looks cleaner in network logs.
To set this up, add a Worker route in the Routes section of your Worker settings:
Route: *example.com/theone/*
Replace theone with whatever path segment you chose in your worker code. Select your domain in the zone dropdown.

Step 5: Add the Plausible snippet to your Astro site
Snippet format changed
The old data-domain / data-api format is deprecated. Plausible now uses a site-specific script (pa-XXXXX.js) with a plausible.init() call for the endpoint. Use the format below.
Add this snippet to your Astro site’s <head>. In Astro, you can place it in your main layout file (e.g., src/layouts/Layout.astro):
<script async src="https://yourdomain.com/theone/pa-XXXXX.js"></script>
<script>
window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)};
plausible.init=plausible.init||function(i){plausible.o=i||{}};
plausible.init({
endpoint: "https://yourdomain.com/theone/event"
})
</script>
Replace the following:
yourdomain.com: your actual site domaintheone: the subdirectory path you configured in Steps 2 and 4pa-XXXXX.js: your site-specific script ID from Plausible (Site Settings → General → Data Snippets)
The endpoint URL must match the Endpoint variable in your Worker code, and the script src must match the ScriptPath. The script URL goes through your Worker (serving the cached Plausible script), and the endpoint URL routes analytics events through your Worker to Plausible’s API.
You should now have Plausible Analytics proxied through Cloudflare Workers, served from your own domain.
Plausible pricing (2025)
Plausible offers several cloud tiers. All plans include the core analytics features: pageviews, visitors, bounce rate, visit duration, referral sources, and more.
| Plan | Price | Pageviews | Sites | Notable Features |
|---|---|---|---|---|
| Starter | $9/mo | 10,000 | 1 | Core analytics |
| Growth | $14/mo | 10,000 | 3 | 3 team members |
| Business | $19/mo | 10,000 | 10 | Funnels, revenue goals, Stats API |
| Enterprise | Custom | Custom | Custom | SSO, Sites API, Managed Proxy |
Higher pageview tiers are available at each level. The Enterprise plan includes a Managed Proxy where Plausible handles the proxy for you via a CNAME record. No Worker needed.
If you want to skip the cloud pricing entirely, the Community Edition is free.
Plausible Community Edition vs Cloud
Plausible Community Edition (CE) is a free, self-hosted version under the AGPL license. It follows an open-core model. CE includes the core analytics engine, but some advanced features are exclusive to the cloud Business and Enterprise plans.
Pros:
- Fully managed, no server to maintain
- All features including funnels, revenue goals, and SSO
- Managed Proxy option (Enterprise plan)
- Automatic updates and security patches
- Stats API V2 for custom integrations
Cons:
- Monthly cost starting at $9/mo
- Data stored on Plausible’s infrastructure
Pros:
- Completely free, self-hosted
- Full control over your data
- AGPL licensed, open source
- Core analytics features included
Cons:
- No funnels, revenue goals, or SSO
- Self-managed server required
- Manual updates and maintenance
- No Managed Proxy option
If you’re self-hosting Plausible CE, affordable VPS providers like Hetzner Cloud or Hostinger VPS offer solid performance for running your instance. See Install Plausible With One Click for deployment instructions.
Can I use this Cloudflare Worker proxy with Plausible CE?
Yes. The Worker code is the same. You just change the ProxyScript URL and the postData fetch URL to point to your self-hosted Plausible domain instead of plausible.io. Use the “Self-Hosted (Plausible CE)” tab in Step 2 for the correct code.
Troubleshooting common issues
Analytics data not showing up
Open your browser’s developer tools (Network tab) and reload your site. Look for requests to your subdirectory path (e.g., /theone/script and /theone/event). If the script request returns 200 but the event request fails, check that the endpoint URL in your snippet matches the Worker’s Endpoint variable exactly. If neither request appears, verify your snippet is in the <head> and not blocked by Content-Security-Policy headers.
Worker returns 404
Verify the Worker route pattern matches your subdirectory. The route should be *example.com/theone/* (note the trailing /*). Also check that the ScriptPath and Endpoint variables in your Worker code match the paths in your snippet. Make sure the Worker is deployed (not just saved as a draft).
CORS errors in the console
Since the proxy runs on your own domain, requests should be same-origin and CORS shouldn’t trigger. If you see CORS errors, your Worker route is likely misconfigured. The requests might be hitting Plausible directly instead of going through the Worker. Double-check the route pattern and ensure the snippet URLs point to your domain, not plausible.io.
Plausible dashboard shows 0 visitors
First, verify you’re looking at the correct site in your Plausible dashboard. If you recently switched to the new snippet format, make sure the old data-domain snippet is completely removed. Having both can cause conflicts. Also check that your own browser isn’t blocking the requests during testing (disable your ad blocker for your own domain).
What’s new in Plausible since 2023
Plausible has shipped a lot of features since this article was first published. Here are the highlights:
- Automatic scroll depth tracking (no setup required)
- AI Assistants traffic channel: tracks visits from ChatGPT, Claude, Gemini, Perplexity
- User Journeys: visualize how visitors navigate your site
- Automatic form submission tracking (toggle-on)
- Revenue goals and ecommerce attribution (Business plan)
- Funnels for multi-step conversion analysis (Business plan)
- Stats API V2 with simpler querying and multi-dimension support
- Search Console integration: keyword data in your dashboard
- Google Analytics import (both UA and GA4)
- Traffic drop alerts via email or Slack
- 2FA and SSO security enhancements
- Improved “Time on Page” metric based on engagement signals
- Site-specific script format (
pa-XXXXX.js) replacing the genericscript.js
If you’re also working on your Astro site’s performance, check how to optimize Astro build speeds or migrate Astro to Bun on Cloudflare for faster builds.
View Full Plausible ChangelogFrequently asked questions
Does this work with frameworks other than Astro?
Yes. The Cloudflare Worker proxy is completely framework-agnostic. It works with any static site generator (Hugo, Eleventy, Next.js, Gatsby) or even plain HTML. The only requirement is that you can add a script tag to your site’s <head>. The Worker handles all the proxying regardless of what generated the HTML.
What is Plausible's Managed Proxy?
Plausible’s Managed Proxy is an Enterprise-only feature. Instead of setting up and maintaining your own Cloudflare Worker, you add a CNAME record pointing to Plausible’s proxy infrastructure. They handle the rest. It’s a good option for teams that want the proxy benefit without managing Workers, but it requires an Enterprise plan.
How much traffic can the free Workers plan handle?
Cloudflare Workers free plan allows 100,000 requests per day. Since the Plausible script is cached by the Worker, most pageviews only count as one request (the event POST). For a site with average traffic, 100K requests translates to roughly 80,000 to 100,000 pageviews per day. That covers the vast majority of sites. If you need more, Cloudflare’s paid plan ($5/mo) includes 10 million requests per month.
Can I use Cloudflare Zaraz instead?
Cloudflare Zaraz is a tag manager that loads third-party scripts through Cloudflare’s infrastructure. As of now, Plausible is not officially supported as a Zaraz integration. The Worker proxy approach described in this article remains the recommended way to proxy Plausible on Cloudflare. If Zaraz adds Plausible support in the future, it could simplify the setup.


