Proxy do Flowsery Analytics com Astro
Encaminhe o Flowsery Analytics através da sua aplicação Astro usando middleware para evitar interferência de bloqueadores de anúncios e capturar dados de visitantes mais precisos.
1. Criar o middleware
Crie um ficheiro de middleware em src/middleware.js (ou src/middleware.ts para projetos 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. Ativar server-side rendering no Astro
Atualize o seu astro.config.mjs para suportar SSR (obrigatório para 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',
}),
});Também vai precisar do adaptador Node.js: npm install @astrojs/node
3. Alternativa: site estático com rotas de API
Se preferir manter o site totalmente estático, crie rotas de API em vez de middleware:
Rota proxy do script
Crie 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',
},
});
}Rota proxy dos eventos
Crie 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: Se o seu projeto já usa uma rota /api/track, adicione data-api à tag de script do Flowsery Analytics para encaminhar os eventos para outro caminho. Por exemplo, data-api="/flowsery-events" envia os dados para /flowsery-events.
Importante: Se todos os visitantes aparecerem na mesma localização no seu painel, confirme que x-flowsery-real-ip está definido com o IP real do visitante (e não o IP do servidor proxy) ao encaminhar pedidos para o endpoint /events do Flowsery Analytics.
4. Modificar a tag de script
Substitua o snippet original do Flowsery Analytics no seu layout pela versão com 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. Fazer deploy
Depois do deploy, a configuração de proxy entra em vigor automaticamente. Verifique se o seu fornecedor de alojamento suporta:
- Server-side rendering (para a abordagem com middleware)
- Rotas de API (para a abordagem do site estático)
Entre os hosts compatíveis com Astro mais comuns estão Vercel, Netlify e Cloudflare Pages.
Confirmar que funciona
Para validar que o proxy está a funcionar corretamente:
- Navegue até ao seu site
- Abra as ferramentas de desenvolvedor do navegador e mude para o separador Network
- Verifique que os pedidos de analytics são servidos a partir do seu domínio em vez de
analytics.flowsery.com
Nota: a abordagem com middleware requer server-side rendering, enquanto as rotas de API funcionam tanto em sites estáticos como renderizados no servidor.
Resolução de problemas
Todos os visitantes aparecem da mesma localização
Quando todos os visitantes mostram uma única localização geográfica (normalmente a região do seu servidor), o proxy não está a encaminhar corretamente os IPs reais dos visitantes.
Resolução:
- Garanta que o seu proxy define
x-flowsery-real-ipcom o IP real do visitante (e não com o IP do servidor) ao encaminhar pedidos para o endpoint/eventsdo Flowsery Analytics. - Se a sua implementação Astro estiver atrás de outro proxy (Vercel, Cloudflare, Netlify), o IP que pretende normalmente está em
cf-connecting-ip,x-vercel-forwarded-foroux-real-ip. Leia primeiro o cabeçalho que a sua edge fornece.