Suivi du trafic au premier niveau avec Astro
Configurez un proxy au premier niveau dans votre projet Astro en utilisant des routes API. Fonctionne avec les modes static et SSR.
Difficulté : Facile - Ajoutez un fichier de route API à votre projet.
Pourquoi cela fonctionne (Même origine)
Cette approche utilise /api/_z/script.js qui se trouve sur la même origine que votre site web. Firefox ETP et les autres protections de suivi bloquent uniquement les requêtes cross-origin.
- Le navigateur voit :
yourdomain.com/api/_z/script.js— même origine, pas de blocage cross-origin - La route API d'Astro proxie la requête vers le serveur Zenovay (le navigateur ne voit jamais ceci)
- Toute la protection contre le suivi est contournée car la requête est au premier niveau
Avant de commencer
Assurez-vous que vous disposez de :
- Un projet Astro (v2.0+ recommandé)
- Votre code de suivi Zenovay (trouvé sous Domaines → votre domaine → Général)
- Un adaptateur SSR installé (pour Vercel, Netlify, Cloudflare, Node, etc.)
Format de votre code de suivi
Votre code de suivi ressemble à : ZV_XXXXXXXXXX
- Commence par
ZV_ - Suivi de 10 caractères (lettres et chiffres)
- CAS SENSIBLE - copiez-le exactement
Exemple : ZV_Q8U0GYD70WR

Sites statiques : Si vous utilisez output: 'static', les routes API d'Astro ne fonctionneront pas. Utilisez plutôt le proxy de votre plateforme d'hébergement (rewrites Vercel, redirects Netlify, etc.).
Étape 1 : Activer SSR (si ce n'est pas déjà fait)
Tout d'abord, assurez-vous que votre projet Astro a SSR activé avec un adaptateur.
Pour Vercel
npm install @astrojs/vercelimport { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'server', // or 'hybrid' for partial SSR
adapter: vercel(),
});Pour Netlify
npm install @astrojs/netlifyimport { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
export default defineConfig({
output: 'server',
adapter: netlify(),
});Pour Cloudflare
npm install @astrojs/cloudflareimport { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare(),
});Pour Node.js
npm install @astrojs/nodeimport { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone'
}),
});Étape 2 : Créer la route API Proxy
Créez une route API catch-all qui proxie les requêtes vers Zenovay :
import type { APIRoute } from 'astro'
export const ALL: APIRoute = async ({ params, request }) => {
// Build the path from the catch-all parameter
const path = params.path || ''
const url = new URL(request.url)
const targetUrl = `https://api.zenovay.com/fp/${path}${url.search}`
// Handle CORS preflight requests
if (request.method === 'OPTIONS') {
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
},
})
}
try {
// Get the real client IP for accurate geolocation
const clientIP = request.headers.get('x-forwarded-for')?.split(',')[0]
|| request.headers.get('cf-connecting-ip')
|| request.headers.get('x-real-ip')
|| ''
// Build proxy headers
const headers = new Headers()
headers.set('Content-Type', request.headers.get('Content-Type') || 'application/json')
headers.set('X-Zenovay-Real-IP', clientIP)
// Forward the request
const response = await fetch(targetUrl, {
method: request.method,
headers: headers,
body: request.method !== 'GET' ? await request.text() : undefined,
})
// Build response with CORS headers
const responseHeaders = new Headers(response.headers)
responseHeaders.set('Access-Control-Allow-Origin', '*')
return new Response(response.body, {
status: response.status,
headers: responseHeaders,
})
} catch (error) {
console.error('Proxy error:', error)
return new Response(JSON.stringify({ error: 'Proxy error' }), {
status: 502,
headers: { 'Content-Type': 'application/json' },
})
}
}Pourquoi [...path].ts ? La syntaxe spread crée une route catch-all qui capture plusieurs segments de chemin. Cela signifie que /api/_z/script.js, /api/_z/e/CODE et /api/_z/settings/CODE sont tous routés vers ce fichier unique.
Étape 3 : Ajouter le script de suivi
Ajoutez le script de suivi à votre mise en page :
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title}</title>
<!-- Zenovay Analytics (First-Party Proxy) -->
<script defer data-tracking-code="YOUR_TRACKING_CODE" src="/api/_z/script.js"></script>
</head>
<body>
<slot />
</body>
</html>Important : Remplacez YOUR_TRACKING_CODE par votre code de suivi réel du tableau de bord Zenovay.
Étape 4 : Déployer
Déployez votre projet Astro sur la plateforme de votre choix :
# Build the project
npm run build
# Deploy (depends on your adapter)
# Vercel: vercel deploy
# Netlify: netlify deploy --prod
# Cloudflare: wrangler pages deploy distMode hybride (Recommandé)
Si la plupart de votre site est statique mais que vous avez besoin du proxy, utilisez le mode hybride :
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'hybrid', // Static by default, SSR for specific routes
adapter: vercel(),
});Puis marquez la route API pour le rendu serveur :
// Force server rendering for this route
export const prerender = false;
import type { APIRoute } from 'astro'
export const ALL: APIRoute = async ({ params, request }) => {
// ... rest of the proxy code
}Vérifier que cela fonctionne
Vérifier l'onglet Réseau
- Visitez votre site déployé
- Ouvrez DevTools (F12)
- Allez à l'onglet Réseau
- Rechargez la page
- Cherchez
/api/_z/script.js
Vous devriez voir :
- Statut : 200
- Domaine : Votre domaine
- Réponse : Code JavaScript
Test dans Firefox
- Ouvrez Firefox
- Paramètres → Confidentialité et sécurité → Protection contre le suivi renforcée : Strict
- Visitez votre site
- Vérifiez que le script se charge correctement
Dépannage
Erreur 404 sur la route API
Cause : SSR n'est pas activé ou l'adaptateur n'est pas configuré.
Solution :
- Assurez-vous que vous avez
output: 'server'ououtput: 'hybrid'dansastro.config.mjs - Vérifiez que vous avez un adaptateur installé et configuré
- Pour le mode hybride, ajoutez
export const prerender = false;à la route API
Erreur 500
Cause : Erreur de syntaxe ou problème à l'exécution dans la route API.
Solution :
- Vérifiez les journaux du serveur pour les messages d'erreur détaillés
- Assurez-vous que les types TypeScript sont corrects
- Vérifiez que tous les imports sont disponibles
Le script se charge mais pas de données
Cause : Code de suivi ne correspond pas.
Solution :
- Vérifiez que
data-tracking-codecorrespond à votre code dans le tableau de bord Zenovay - Vérifiez la console du navigateur pour les erreurs JavaScript
- Assurez-vous que le domaine est enregistré dans Zenovay
Géolocalisation incorrecte
Cause : L'IP du client n'est pas transmise correctement.
Solution : La route API essaie plusieurs en-têtes. Assurez-vous que votre plateforme en transmet un parmi :
x-forwarded-for(plus courant)cf-connecting-ip(Cloudflare)x-real-ip(nginx)
Alternative pour sites statiques
Si vous utilisez output: 'static', vous ne pouvez pas utiliser les routes API. Utilisez plutôt le proxy de votre plateforme d'hébergement :
Vercel
{
"rewrites": [
{ "source": "/api/_z/:path*", "destination": "https://api.zenovay.com/fp/:path*" }
]
}Netlify
/api/_z/* https://api.zenovay.com/fp/:splat 200Cloudflare Pages
Utilisez plutôt les Cloudflare Pages Functions - consultez le guide Cloudflare Pages.
Exemple complet
my-astro-site/
├── astro.config.mjs
├── src/
│ ├── layouts/
│ │ └── Layout.astro
│ └── pages/
│ ├── index.astro
│ └── api/
│ └── _z/
│ └── [...path].ts
└── package.jsonimport { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'hybrid',
adapter: vercel(),
});---
const { title } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{title}</title>
<script defer data-tracking-code="YOUR_TRACKING_CODE" src="/api/_z/script.js"></script>
</head>
<body>
<slot />
</body>
</html>Liste de contrôle finale
Avant de terminer, vérifiez tous ces points :
- Astro SSR est activé (ou utilise rewrites de plateforme statique)
- Le fichier de route API existe à
src/pages/api/_z/[...path].ts -
export const prerender = falseest défini (pour le mode hybride) - La balise script utilise
/api/_z/script.js(pas l'URL Zenovay directe) - L'attribut
data-tracking-codecontient votre code de suivi correct - Le projet est déployé (pas seulement exécuté localement)
- Testé dans Firefox avec Protection contre le suivi renforcée définie à Strict
- Les visites apparaissent dans le tableau de bord Zenovay
Prochaines étapes
- Événements personnalisés - Suivi des interactions utilisateur
- Identification des visiteurs - Lier l'analytique aux utilisateurs
- Dépannage - Plus d'aide pour les problèmes