Proxy do Flowsery Analytics com Next.js
Encaminhe o Flowsery Analytics através do seu próprio domínio numa aplicação Next.js para evitar interferência de bloqueadores de anúncios e capturar dados de visitantes mais precisos.
Há dois passos para um proxy completo: um rewrite (faz o tracker parecer first-party para resistir aos ad-blockers) e middleware (encaminha o IP real do visitante para o backend da Flowsery). Só os rewrites entregam eventos, mas todos os visitantes vão parecer vir da região do seu servidor. Precisa dos dois.
1. Configurar rewrites
Adicione ou atualize o seu next.config.js na raiz do projeto:
module.exports = {
async rewrites() {
return [
{
source: '/js/main.js',
destination: 'https://cdn.flowsery.com/main.js',
},
{
source: '/api/track',
destination: 'https://analytics.flowsery.com/analytics/events',
},
{
source: '/:locale/api/track',
destination: 'https://analytics.flowsery.com/analytics/events',
},
];
},
};Se o seu projeto já usa /api/track, escolha outro caminho e passe-o com data-api no script do tracker (por exemplo, data-api="/flowsery-events").
2. Injetar o IP real do visitante (middleware)
Os rewrites do Next.js fazem um fetch servidor-para-servidor, por isso a edge Cloudflare a jusante substitui cf-connecting-ip pelo IP do seu servidor Next.js. A Flowsery passa então a ver todos os visitantes como "o seu servidor" e resolve a geolocalização para a região onde está alojado.
Para corrigir isto, adicione middleware que leia o IP real do visitante à chegada e o fixe num cabeçalho personalizado x-flowsery-real-ip. Este cabeçalho personalizado sobrevive ao salto de proxy sem alterações, e o backend da Flowsery dá-lhe prioridade sobre cf-connecting-ip quando está presente.
Crie ou atualize middleware.ts na raiz do projeto:
import { NextRequest, NextResponse } from 'next/server';
const TRACKING_PROXY_PATHS = /\/api\/track$/;
export default function middleware(request: NextRequest) {
if (!TRACKING_PROXY_PATHS.test(request.nextUrl.pathname)) {
return NextResponse.next();
}
const realIp = request.headers.get('cf-connecting-ip') || request.headers.get('x-forwarded-for')?.split(',')[0]?.trim();
if (!realIp) return NextResponse.next();
const forwardedHeaders = new Headers(request.headers);
forwardedHeaders.set('x-flowsery-real-ip', realIp);
return NextResponse.next({
request: { headers: forwardedHeaders },
});
}
export const config = {
matcher: ['/api/track', '/:locale/api/track'],
};Se já tiver middleware
Há duas partes que precisa de fundir com cuidado:
1. O handler. Chame primeiro a lógica do tracking proxy para caminhos /api/track, e depois deixe seguir para a sua lógica existente:
export default function middleware(request: NextRequest) {
// Runs for /api/track + /:locale/api/track. Returns a response only when
// the path matches, otherwise returns NextResponse.next() so your existing
// logic runs below.
if (/\/api\/track$/.test(request.nextUrl.pathname)) {
const realIp = request.headers.get('cf-connecting-ip') || request.headers.get('x-forwarded-for')?.split(',')[0]?.trim();
if (realIp) {
const headers = new Headers(request.headers);
headers.set('x-flowsery-real-ip', realIp);
return NextResponse.next({ request: { headers } });
}
return NextResponse.next();
}
// ...your existing middleware logic here (locale detection, auth, etc.)
}2. O matcher. A maior parte do middleware ao nível da página usa um negative lookahead como /((?!api/|_next/...).*) para excluir rotas de API. Esse padrão também vai excluir /api/track, portanto o middleware nunca corre para o caminho de tracking. Alargue o array matcher para o incluir novamente:
export const config = {
matcher: [
// Your existing page-level pattern — leave it alone.
'/((?!api/|js/|_next/static|_next/image|favicon.ico|locales|ingest).*)',
// Added so middleware also runs for the tracking proxy paths.
'/api/track',
'/:locale/api/track',
],
};A ordem não importa. As entradas do matcher são combinadas com OR. Um caminho aciona o middleware se qualquer entrada corresponder. As rotas de página continuam a acertar no seu padrão existente; /api/track acerta na nova entrada explícita e chega ao handler do tracking proxy acima.
3. Modificar a tag de script
Aponte o script para o caminho local com proxy:
<script defer data-fl-website-id="flid_******" src="/js/main.js"></script>4. Fazer deploy
O rewrite e o middleware entram em vigor após o deploy.
Confirmar que funciona
- Abra o seu site num separador normal do navegador.
- Abra DevTools -> Network. Filtre por
/api/track. - Confirme que cada pedido vai para o seu próprio domínio (não para
analytics.flowsery.com). - No painel da Flowsery, confirme que os países e cidades dos visitantes refletem a sua audiência (e não a região do seu alojamento).
Resolução de problemas
Todos os visitantes aparecem da mesma localização
Se todos os visitantes mostrarem uma única localização geográfica (normalmente a região do seu servidor), o passo de middleware não está a aplicar o cabeçalho x-flowsery-real-ip.
As causas mais comuns são:
- O matcher do middleware não inclui o caminho de tracking. A maioria dos matchers existentes usa um negative lookahead como
/((?!api/|...).*), que exclui/api/*. Adicione/api/track(e/:locale/api/trackse usar URLs com locale no prefixo) como entradas explícitas no arraymatcher. - Adicionou o cabeçalho à resposta em vez do pedido. O backend lê cabeçalhos do pedido; use
NextResponse.next({ request: { headers } }), nãoresponse.headers.set(...). - O seu provider de edge não é a Cloudflare. Se estiver atrás da Vercel, Fly.io ou outra edge, leia o IP do visitante a partir do cabeçalho dessa edge (
x-real-ip,x-vercel-forwarded-for,fly-client-ip, etc.).