Proxy de Flowsery Analytics con Astro
Enruta Flowsery Analytics a través de tu aplicación Astro usando middleware para evitar la interferencia de los adblockers y capturar datos de visitantes más precisos.
1. Crea el middleware
Crea un archivo de middleware en src/middleware.js (o src/middleware.ts si tu proyecto usa TypeScript):
// 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/main.js') {
const response = await fetch('https://cdn.flowsery.com/main.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/track' && request.method === 'POST') {
const body = await request.text();
// Resolve the real visitor IP for accurate geolocation
const clientIp =
request.headers.get('cf-connecting-ip') || request.headers.get('x-real-ip') || request.headers.get('x-forwarded-for')?.split(',')[0] || '';
const response = await fetch('https://analytics.flowsery.com/analytics/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': request.headers.get('User-Agent') || '',
Origin: request.headers.get('Origin') || url.origin,
// Flowsery reads `x-flowsery-real-ip` as the authoritative visitor IP.
// Without it, every visitor resolves to your server's region because
// Cloudflare rewrites `cf-connecting-ip` on the proxy hop.
...(clientIp && { 'x-flowsery-real-ip': clientIp }),
},
body: body,
});
const responseText = await response.text();
return new Response(responseText, {
status: response.status,
headers: {
'Content-Type': 'application/json',
},
});
}
return next();
}2. Habilita el renderizado del lado del servidor en Astro
Actualiza tu astro.config.mjs para soportar SSR, que es necesario para el 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',
}),
});También necesitarás el adaptador de Node.js: npm install @astrojs/node
3. Alternativa: sitio estático con rutas API
Si prefieres mantener tu sitio completamente estático, crea rutas API en lugar de middleware:
Ruta proxy del script
Crea src/pages/js/main.js.js:
// src/pages/js/main.js.js
export async function GET() {
const response = await fetch('https://cdn.flowsery.com/main.js');
const script = await response.text();
return new Response(script, {
headers: {
'Content-Type': 'application/javascript',
'Cache-Control': 'public, max-age=31536000',
},
});
}Ruta proxy de eventos
Crea src/pages/api/track.js:
// src/pages/api/track.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/analytics/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': request.headers.get('User-Agent') || '',
Origin: request.headers.get('Origin') || url.origin,
'x-forwarded-for': clientIp,
},
body: body,
});
const responseText = await response.text();
return new Response(responseText, {
status: response.status,
headers: {
'Content-Type': 'application/json',
},
});
}Nota: Si tu proyecto ya usa una ruta /api/track, agrega data-api a la etiqueta del script de Flowsery Analytics para redirigir los eventos a otra ruta. Por ejemplo, data-api="/flowsery-events" enviará los datos a /flowsery-events.
Importante: Si todos los visitantes aparecen en la misma ubicación en tu panel, confirma que x-flowsery-real-ip se esté estableciendo con la IP real del visitante, no con la del servidor proxy, al reenviar solicitudes al endpoint /events de Flowsery Analytics.
4. Modifica la etiqueta del script
Reemplaza el snippet original de Flowsery Analytics en tu layout por la versión con proxy:
---
// 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_******"
src="/js/main.js"
></script>
</head>
<body>
<slot />
</body>
</html>5. Despliega
Después de desplegar, la configuración del proxy se activa automáticamente. Verifica que tu proveedor de hosting soporte:
- Renderizado del lado del servidor, si usas el enfoque con middleware.
- Rutas API, si usas el enfoque de sitio estático.
Entre los hosts compatibles con Astro más comunes están Vercel, Netlify y Cloudflare Pages.
Confirmar que funciona
Para validar que el proxy funciona correctamente:
- Navega a tu sitio web.
- Abre las herramientas de desarrollo del navegador y ve a la pestaña Network.
- Verifica que las solicitudes de analítica se sirvan desde tu dominio y no desde
analytics.flowsery.com.
Nota: el enfoque con middleware requiere SSR, mientras que las rutas API funcionan tanto en sitios estáticos como en sitios renderizados del lado del servidor.
Solución de problemas
Todos los visitantes aparecen desde la misma ubicación
Cuando todos los visitantes muestran una única ubicación geográfica, normalmente la región de tu servidor, el proxy no está reenviando correctamente las IP reales.
Resolución:
- Asegúrate de que tu proxy establezca
x-flowsery-real-ipcon la IP real del visitante, no con la IP del servidor, al reenviar solicitudes al endpoint/eventsde Flowsery Analytics. - Si tu despliegue de Astro está detrás de otro proxy, como Vercel, Cloudflare o Netlify, la IP que necesitas normalmente viene en
cf-connecting-ip,x-vercel-forwarded-forox-real-ip. Lee primero el encabezado que proporcione tu edge.