Proxying Flowsery Analytics with Astro
Route Flowsery Analytics through your Astro application using middleware to prevent adblocker interference and capture more accurate visitor data.
1. Create the Middleware
Create a middleware file at src/middleware.js (or src/middleware.ts for TypeScript projects):
// src/middleware.js
export async function onRequest(context, next) {
const { request } = context;
const url = new URL(request.url);
// Proxy the Flowsery Analytics tracking script
if (url.pathname === '/js/script.js') {
const response = await fetch('https://analytics.flowsery.com/js/script.js');
const script = await response.text();
return new Response(script, {
headers: {
'Content-Type': 'application/javascript',
'Cache-Control': 'public, max-age=31536000',
},
});
}
// Proxy the event collection endpoint
if (url.pathname === '/api/events' && request.method === 'POST') {
const body = await request.text();
// Resolve the real visitor IP for accurate geolocation
const clientIp =
request.headers.get('x-real-ip') || request.headers.get('x-forwarded-for')?.split(',')[0] || request.headers.get('cf-connecting-ip') || '';
const response = await fetch('https://analytics.flowsery.com/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': request.headers.get('User-Agent') || '',
Origin: request.headers.get('Origin') || url.origin,
'x-flowsery-ip': clientIp,
},
body: body,
});
const responseText = await response.text();
return new Response(responseText, {
status: response.status,
headers: {
'Content-Type': 'application/json',
},
});
}
return next();
}
2. Enable Server-Side Rendering in Astro
Update your astro.config.mjs to support SSR (required for middleware):
// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server', // or 'hybrid'
adapter: node({
mode: 'standalone',
}),
});
You will also need the Node.js adapter: npm install @astrojs/node
3. Alternative: Static Site with API Routes
If you prefer keeping your site fully static, create API routes instead of middleware:
Script Proxy Route
Create src/pages/js/script.js.js:
// src/pages/js/script.js.js
export async function GET() {
const response = await fetch('https://analytics.flowsery.com/js/script.js');
const script = await response.text();
return new Response(script, {
headers: {
'Content-Type': 'application/javascript',
'Cache-Control': 'public, max-age=31536000',
},
});
}
Events Proxy Route
Create src/pages/api/events.js:
// src/pages/api/events.js
export async function POST({ request }) {
const body = await request.text();
const url = new URL(request.url);
// Resolve the real visitor IP for accurate geolocation
const clientIp =
request.headers.get('x-real-ip') || request.headers.get('x-forwarded-for')?.split(',')[0] || request.headers.get('cf-connecting-ip') || '';
const response = await fetch('https://analytics.flowsery.com/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': request.headers.get('User-Agent') || '',
Origin: request.headers.get('Origin') || url.origin,
'x-flowsery-ip': clientIp,
},
body: body,
});
const responseText = await response.text();
return new Response(responseText, {
status: response.status,
headers: {
'Content-Type': 'application/json',
},
});
}
Note: If your project already uses an /api/events route, add data-api to the Flowsery Analytics script tag to redirect events elsewhere. For example, data-api="/flowsery-events" sends data to /flowsery-events instead.
Important: If every visitor appears to be in the same location in your dashboard, confirm that the x-flowsery-ip header is set to the real visitor IP (not the proxy server IP) when forwarding requests to the Flowsery Analytics /events endpoint.
4. Modify the Script Tag
Replace the original Flowsery Analytics snippet in your layout with the proxied version:
---
// src/layouts/Layout.astro
const { title } = Astro.props;
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>{title}</title>
<script
defer
data-fl-website-id="flid_******"
data-domain="your_domain.com"
src="/js/script.js"
></script>
</head>
<body>
<slot />
</body>
</html>
5. Deploy
After deploying, the proxy configuration takes effect automatically. Verify that your hosting provider supports:
- Server-side rendering (for the middleware approach)
- API routes (for the static site approach)
Common Astro-compatible hosts include Vercel, Netlify, and Cloudflare Pages.
Confirming It Works
To validate that the proxy is functioning correctly:
- Navigate to your website
- Open your browser's developer tools and switch to the Network tab
- Verify that analytics requests are served from your domain rather than analytics.flowsery.com
Note: The middleware approach requires server-side rendering, whereas API routes work with both static and server-rendered sites.
Troubleshooting
Every visitor appears from the same location
When all visitors show a single geographic location (typically your server's region), the proxy is not forwarding real visitor IPs correctly.
Resolution:
- Ensure your proxy includes the
x-flowsery-ipheader containing the actual visitor IP address (not the server IP) when forwarding requests to the Flowsery Analytics/eventsendpoint