Suporte/Guias de proxy
Guias de proxy

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.

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:

JavaScript
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:

TypeScript
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:

TypeScript
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:

TypeScript
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:

HTML
<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

  1. Abra o seu site num separador normal do navegador.
  2. Abra DevTools -> Network. Filtre por /api/track.
  3. Confirme que cada pedido vai para o seu próprio domínio (não para analytics.flowsery.com).
  4. 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/track se usar URLs com locale no prefixo) como entradas explícitas no array matcher.
  • Adicionou o cabeçalho à resposta em vez do pedido. O backend lê cabeçalhos do pedido; use NextResponse.next({ request: { headers } }), não response.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.).