When using Plausible Analytics, a common challenge arises: privacy-conscious users and browser extensions often block tracking scripts, leading to incomplete data. Additionally, direct tracking requests to Plausible’s servers can expose your analytics setup to ad blockers, reducing the accuracy of your insights.
By implementing a proxy, you can mask the Plausible script and tracking requests under your own domain, bypassing ad blockers while maintaining full privacy compliance. This setup ensures more reliable data collection, improves website performance, and enhances user trust. In this guide, we’ll walk you through setting up a proxy for Plausible to maximize your analytics efficiency without compromising privacy.
Solution: Use a Custom Proxy Domain
The most effective solution is to proxy Plausible through your own domain. This makes the analytics requests appear as first-party requests (from your own domain) rather than third-party requests that Brave blocks.
Let's implement this:
import Plausible from 'plausible-tracker';
// Initialize Plausible with your domain and custom proxy configuration
export const plausible = Plausible({
domain: 'yourdomain.com',
trackLocalhost: process.env.NODE_ENV === 'development', // Only track localhost in development
// Using default script path with proxy
apiHost: '' // Empty means it uses the current domain (for /api/event)
});
// Get the functions we need
export const { trackEvent, trackPageview, enableAutoPageviews, enableAutoOutboundTracking } = plausible;
// Export a function to enable both auto page views and outbound tracking
export const enablePlausibleTracking = () => {
// Set up automatic page view tracking
const cleanupPageviews = enableAutoPageviews();
// Set up automatic outbound link click tracking
const cleanupOutbound = enableAutoOutboundTracking();
// Return a cleanup function that will clean up both
return () => {
cleanupPageviews();
cleanupOutbound();
};
};
export default plausible;
Now let's create the API proxy endpoint with the file src/app/api/plausible/event/route.ts :
import { NextRequest, NextResponse } from 'next/server';
/**
* Proxy for Plausible's event API
* This prevents Brave and other privacy browsers from blocking the analytics
*
* Route: /api/event -> https://plausible.io/api/event
*/
export async function POST(request: NextRequest) {
try {
// Get request body as text to preserve its exact format
const body = await request.text();
// Forward the request to Plausible's API
const response = await fetch('https://plausible.io/api/event', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': request.headers.get('user-agent') || '',
'X-Forwarded-For': request.headers.get('x-forwarded-for') || '',
},
body
});
// Return success status if Plausible accepted the event
if (response.ok) {
return new NextResponse(null, {
status: 202,
headers: {
// Add CORS headers
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
}
});
}
// Return the error from Plausible
return new NextResponse(null, {
status: response.status,
statusText: response.statusText
});
} catch (error) {
console.error('Error proxying to Plausible:', error);
return new NextResponse(null, { status: 500 });
}
}
// Also handle OPTIONS requests for CORS
export async function OPTIONS() {
return new NextResponse(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
}
});
}
We also need to create a second endpoint for pageview script requests using src/app/api/plausible/route.ts :
import { NextRequest, NextResponse } from 'next/server';
/**
* General proxy route for Plausible API
* This handles requests that aren't directed to the /event endpoint
*/
export async function GET(request: NextRequest) {
// Parse the request URL to extract any query parameters
const url = new URL(request.url);
// Forward the request to Plausible
const plausibleUrl = new URL('https://plausible.io');
plausibleUrl.pathname = url.pathname.replace('/api/plausible', '');
plausibleUrl.search = url.search;
try {
const response = await fetch(plausibleUrl.toString(), {
method: 'GET',
headers: {
'User-Agent': request.headers.get('user-agent') || '',
},
});
// Return the response from Plausible
const contentType = response.headers.get('content-type') || 'text/plain';
const body = await response.text();
return new NextResponse(body, {
status: response.status,
headers: {
'Content-Type': contentType,
'Cache-Control': 'public, max-age=3600',
}
});
} catch (error) {
console.error('Error proxying to Plausible:', error);
return new NextResponse(null, { status: 500 });
}
}
Let's update our test page to help confirm the proxy is working trough page.tsx :
// ... existing code ...
<Typography variant="h4" component="h1" gutterBottom>
Plausible Analytics Test Page
</Typography>
<Typography paragraph>
This page is designed to test if Plausible Analytics is working correctly.
Check your browser's network tab for requests to "/api/plausible".
</Typography>
<Box sx={{ my: 3, p: 2, bgcolor: '#f5f5f5', borderRadius: 1 }}>
<Typography variant="subtitle2" gutterBottom>
Brave Compatibility:
</Typography>
<Typography variant="body2">
Analytics requests are now proxied through your own domain, which should bypass
Brave Shields and other privacy blockers. Look for requests to
"/api/plausible/event" in your network tab instead of direct plausible.io calls.
</Typography>
</Box>
// ... existing code ...
Making Plausible Analytics Work with Brave Browser 🛡️
I've implemented a solution that will allow Plausible Analytics to work with Brave Browser and other privacy-focused browsers. Here's what I did:
1. Created a First-Party Proxy for Plausible
The main issue with Brave is that its shields feature blocks third-party tracking requests. By proxying all Plausible requests through your own domain, we make them appear as first-party requests that won't be blocked.I've set up:
- A local API endpoint: Changed apiHost from https://plausible.io to /api/plausible
- Proxy route for events: Created /api/plausible/event which forwards tracking events
- General proxy route: Created /api/plausible for other Plausible requests
2. How This Works
Instead of sending analytics directly to plausible.io:
- Plausible tracker sends requests to /api/plausible/event on your domain
- Our server-side API routes forward those requests to Plausible
- Brave doesn't block these requests because they appear to come from your domain
3. Testing It
To verify it works in Brave:
- Open your site in Brave Browser
- Visit the test page at /plausible-test
- Open DevTools (Right click → Inspect or press F12)
- Go to the Network tab
- Look for requests to /api/plausible/event instead of plausible.io
- Try the test buttons to generate events
4. Privacy Considerations
This approach respects user privacy while still collecting the analytics you need:
- No cookies are used
- No personal data is collected
- The proxy is transparent about what it's doing
- Users who have globally opted out of Plausible tracking will still be respected
5. Next Steps
After deploying these changes:
- Check your Plausible dashboard: You should start seeing data from Brave users
- Additional customization: Consider adding this information to your privacy policy
- Testing: Verify functionality across different browsers, especially privacy-focused ones
This solution preserves Plausible's privacy-friendly approach while working around Brave's blocking mechanisms by proxying the requests through your own domain - a common and recommended practice for analytics implementations.
More technical details using https://plausible.io/docs/proxy/introduction