Proxy Flowsery Analytics avec Next.js
Faites transiter Flowsery Analytics via votre propre domaine dans une application Next.js afin d'eviter les interferences des bloqueurs de publicites et de capturer des donnees visiteurs precises.
Un proxy complet comporte deux etapes : un rewrite (qui rend le tracker first-party pour survivre aux bloqueurs) et un middleware (qui transfere la vraie IP du visiteur au backend de Flowsery). Les rewrites seuls enverront bien les evenements, mais tous les visiteurs sembleront venir de la region de votre serveur : il faut les deux.
1. Configurer les rewrites
Ajoutez ou mettez a jour votre next.config.js a la racine du projet :
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',
},
];
},
};Si votre projet utilise deja /api/track, choisissez un autre chemin et passez-le via data-api sur le script tracker (par exemple data-api="/flowsery-events").
2. Injecter la vraie IP du visiteur (middleware)
Les rewrites Next.js effectuent une requete serveur-a-serveur, donc le edge Cloudflare en aval remplace cf-connecting-ip par l'IP de votre serveur Next.js. Flowsery voit alors chaque visiteur comme "votre serveur" et resout la geo vers votre region d'hebergement.
Pour corriger cela, ajoutez un middleware qui lit la vraie IP du visiteur a l'arrivee et la fige dans un en-tete personnalise x-flowsery-real-ip. Cet en-tete personnalise traverse le saut proxy sans etre modifie, et le backend de Flowsery le privilegie par rapport a cf-connecting-ip lorsqu'il est present.
Creez ou mettez a jour middleware.ts a la racine du projet :
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'],
};Si vous avez deja un middleware
Deux points a fusionner avec soin :
1. Le handler. Appelez d'abord la logique du proxy de tracking pour les chemins /api/track, puis laissez la main a votre logique existante :
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. Le matcher. La plupart des middlewares de pages utilisent un negative lookahead du type /((?!api/|_next/...).*) pour exclure les routes API. Ce motif exclura aussi /api/track, donc le middleware ne s'executera jamais sur le chemin de tracking. Etendez le tableau matcher pour le reinclure :
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',
],
};L'ordre n'a pas d'importance. Les entrees du matcher sont reliees par un OR : un chemin declenche le middleware si n'importe quelle entree correspond. Les routes de pages continuent d'utiliser votre motif existant ; /api/track utilise la nouvelle entree explicite et atteint le handler de proxy ci-dessus.
3. Modifier la balise script
Pointez le script vers le chemin local proxifie :
<script defer data-fl-website-id="flid_******" src="/js/main.js"></script>4. Deployer
Le rewrite et le middleware prennent effet au deploiement.
Verifier que cela fonctionne
- Ouvrez votre site dans un onglet de navigateur classique.
- Ouvrez DevTools → Reseau. Filtrez sur
/api/track. - Verifiez que chaque requete part vers votre propre domaine (et non
analytics.flowsery.com). - Dans votre tableau de bord Flowsery, verifiez que les pays et villes des visiteurs correspondent a votre audience (et non a votre region d'hebergement).
Depannage
Tous les visiteurs apparaissent au meme endroit
Si tous les visiteurs affichent une seule localisation geographique (generalement la region de votre serveur), l'etape middleware n'applique pas l'en-tete x-flowsery-real-ip.
Causes frequentes :
- Le matcher du middleware n'inclut pas le chemin de tracking. La plupart des matchers existants utilisent un negative lookahead comme
/((?!api/|...).*), qui exclut/api/*. Ajoutez/api/track(et/:locale/api/tracksi vous utilisez des URL prefixees par locale) comme entrees explicites dans le tableaumatcher. - Vous avez ajoute l'en-tete a la reponse au lieu de la requete. Le backend lit les en-tetes de requete ; utilisez
NextResponse.next({ request: { headers } }), pasresponse.headers.set(...). - Votre fournisseur edge n'est pas Cloudflare. Si vous etes derriere Vercel, Fly.io ou un autre edge, lisez l'IP visiteur dans l'en-tete fourni par ce edge (
x-real-ip,x-vercel-forwarded-for,fly-client-ip, etc.).