Seguimiento de primera parte con Astro
Configura un proxy de primera parte en tu proyecto Astro usando rutas API. Funciona con modos estático y SSR.
Dificultad: Fácil - Agrega un archivo de ruta API a tu proyecto.
Por qué funciona (mismo origen)
Este enfoque utiliza /api/_z/script.js que está en el mismo origen que tu sitio web. Firefox ETP y otras protecciones de rastreo solo bloquean solicitudes entre orígenes.
- El navegador ve:
tudominio.com/api/_z/script.js— mismo origen, sin bloqueo entre orígenes - La ruta API de Astro proxifica la solicitud al servidor de Zenovay en el servidor (el navegador nunca ve esto)
- Toda la protección de rastreo se evita porque la solicitud es de primera parte
Antes de empezar
Asegúrate de tener:
- Un proyecto de Astro (v2.0+ recomendado)
- Tu código de rastreo de Zenovay (encontrado en Dominios → tu dominio → General)
- Adaptador SSR instalado (para Vercel, Netlify, Cloudflare, Node, etc.)
Formato de tu código de rastreo
Tu código de rastreo se ve así: ZV_XXXXXXXXXX
- Comienza con
ZV_ - Seguido por 10 caracteres (letras y números)
- SENSIBLE A MAYÚSCULAS - cópialo exactamente
Ejemplo: ZV_Q8U0GYD70WR

Sitios estáticos: Si estás usando output: 'static', las rutas API de Astro no funcionarán. Usa el proxy de tu plataforma de alojamiento en su lugar (reescrituras de Vercel, redirecciones de Netlify, etc.).
Paso 1: Habilitar SSR (si no lo está ya)
Primero, asegúrate de que tu proyecto Astro tenga SSR habilitado con un adaptador.
Para Vercel
npm install @astrojs/vercelimport { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'server', // o 'hybrid' para SSR parcial
adapter: vercel(),
});Para Netlify
npm install @astrojs/netlifyimport { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
export default defineConfig({
output: 'server',
adapter: netlify(),
});Para Cloudflare
npm install @astrojs/cloudflareimport { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare(),
});Para Node.js
npm install @astrojs/nodeimport { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone'
}),
});Paso 2: Crear la ruta API del proxy
Crea una ruta API de captura que proxifique solicitudes a Zenovay:
import type { APIRoute } from 'astro'
export const ALL: APIRoute = async ({ params, request }) => {
// Construir la ruta desde el parámetro de captura
const path = params.path || ''
const url = new URL(request.url)
const targetUrl = `https://api.zenovay.com/fp/${path}${url.search}`
// Manejar solicitudes preflight CORS
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 {
// Obtener la IP real del cliente para geolocalización exacta
const clientIP = request.headers.get('x-forwarded-for')?.split(',')[0]
|| request.headers.get('cf-connecting-ip')
|| request.headers.get('x-real-ip')
|| ''
// Construir encabezados del proxy
const headers = new Headers()
headers.set('Content-Type', request.headers.get('Content-Type') || 'application/json')
headers.set('X-Zenovay-Real-IP', clientIP)
// Reenviar la solicitud
const response = await fetch(targetUrl, {
method: request.method,
headers: headers,
body: request.method !== 'GET' ? await request.text() : undefined,
})
// Construir respuesta con encabezados CORS
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('Error del proxy:', error)
return new Response(JSON.stringify({ error: 'Error del proxy' }), {
status: 502,
headers: { 'Content-Type': 'application/json' },
})
}
}¿Por qué [...path].ts? La sintaxis de expansión crea una ruta de captura que captura múltiples segmentos de ruta. Esto significa que /api/_z/script.js, /api/_z/e/CODE, y /api/_z/settings/CODE todas se enrutan a este único archivo.
Paso 3: Agregar el script de rastreo
Agrega el script de rastreo a tu maquetación:
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title}</title>
<!-- Análisis de Zenovay (Proxy de primera parte) -->
<script defer data-tracking-code="TU_CÓDIGO_DE_RASTREO" src="/api/_z/script.js"></script>
</head>
<body>
<slot />
</body>
</html>Importante: Reemplaza TU_CÓDIGO_DE_RASTREO con tu código de rastreo real del panel de control de Zenovay.
Paso 4: Desplegar
Despliega tu proyecto Astro en tu plataforma elegida:
# Construir el proyecto
npm run build
# Desplegar (depende de tu adaptador)
# Vercel: vercel deploy
# Netlify: netlify deploy --prod
# Cloudflare: wrangler pages deploy distModo híbrido (recomendado)
Si la mayoría de tu sitio es estático pero necesitas el proxy, usa el modo híbrido:
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'hybrid', // Estático por defecto, SSR para rutas específicas
adapter: vercel(),
});Luego marca la ruta API para renderizado en el servidor:
// Forzar renderizado en el servidor para esta ruta
export const prerender = false;
import type { APIRoute } from 'astro'
export const ALL: APIRoute = async ({ params, request }) => {
// ... resto del código del proxy
}Verificar que funciona
Revisar la pestaña de red
- Visita tu sitio desplegado
- Abre las herramientas de desarrollo (F12)
- Ve a la pestaña Red
- Recarga la página
- Busca
/api/_z/script.js
Deberías ver:
- Estado: 200
- Dominio: Tu dominio
- Respuesta: Código JavaScript
Probar en Firefox
- Abre Firefox
- Configuración → Privacidad y seguridad → Protección mejorada de rastreo: Estricta
- Visita tu sitio
- Verifica que el script cargue correctamente
Solución de problemas
Error 404 en la ruta API
Causa: SSR no habilitado o adaptador no configurado.
Solución:
- Asegúrate de tener
output: 'server'ooutput: 'hybrid'enastro.config.mjs - Verifica que tengas un adaptador instalado y configurado
- Para modo híbrido, agrega
export const prerender = false;a la ruta API
Error 500
Causa: Error de sintaxis o problema en tiempo de ejecución en la ruta API.
Solución:
- Revisa los registros del servidor para mensajes de error detallados
- Asegúrate de que los tipos de TypeScript sean correctos
- Verifica que todas las importaciones estén disponibles
El script carga pero no hay datos
Causa: Falta de concordancia en el código de rastreo.
Solución:
- Verifica que
data-tracking-codecoincida con tu código en el panel de control de Zenovay - Revisa la consola del navegador para errores de JavaScript
- Asegúrate de que el dominio esté registrado en Zenovay
Geolocalización incorrecta
Causa: La IP del cliente no se reenvía correctamente.
Solución: La ruta API intenta múltiples encabezados. Asegúrate de que tu plataforma reenvíe uno de estos:
x-forwarded-for(más común)cf-connecting-ip(Cloudflare)x-real-ip(nginx)
Alternativa para sitios estáticos
Si estás usando output: 'static', no puedes usar rutas API. En su lugar, usa el proxy de tu plataforma de alojamiento:
Vercel
{
"rewrites": [
{ "source": "/api/_z/:path*", "destination": "https://api.zenovay.com/fp/:path*" }
]
}Netlify
/api/_z/* https://api.zenovay.com/fp/:splat 200Cloudflare Pages
Usa las funciones de Cloudflare Pages en su lugar - consulta la guía de Cloudflare Pages.
Ejemplo completo
mi-sitio-astro/
├── 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="es">
<head>
<meta charset="UTF-8" />
<title>{title}</title>
<script defer data-tracking-code="TU_CÓDIGO_DE_RASTREO" src="/api/_z/script.js"></script>
</head>
<body>
<slot />
</body>
</html>Lista de verificación final
Antes de terminar, verifica todos estos puntos:
- SSR de Astro está habilitado (o usando reescrituras de la plataforma de sitios estáticos)
- El archivo de ruta API existe en
src/pages/api/_z/[...path].ts -
export const prerender = falseestá configurado (para modo híbrido) - La etiqueta de script usa
/api/_z/script.js(no la URL directa de Zenovay) - El atributo
data-tracking-codecontiene tu código de rastreo correcto - El proyecto está desplegado (no solo ejecutándose localmente)
- Probado en Firefox con Protección mejorada de rastreo configurada en Estricta
- Las visitas aparecen en el panel de control de Zenovay
Próximos pasos
- Eventos personalizados - Rastrear interacciones del usuario
- Identificación de visitantes - Vincular análisis a usuarios
- Solución de problemas - Más ayuda con problemas