Saltar al contenido

· · Herramientas  · 6 min read

Tu Google Analytics Está Muerto en Silencio: La Trampa de Partytown en los Temas de Astro

Mi Google Analytics estaba instalado, verificado, y no recolectaba absolutamente nada — sin un solo error que me avisara. El culpable era un valor por default de Partytown en mi tema de Astro, que emite GA como un script que el navegador jamás ejecuta. Aquí está la trampa, y el arreglo de una línea.

Mi Google Analytics estaba instalado, verificado, y no recolectaba absolutamente nada — sin un solo error que me avisara. El culpable era un valor por default de Partytown en mi tema de Astro, que emite GA como un script que el navegador jamás ejecuta. Aquí está la trampa, y el arreglo de una línea.

Google Analytics estaba instalado en mi sitio Astro. El tag estaba verificado. El sitio estaba en producción y recibiendo tráfico. Y el dashboard de GA4 era una línea perfectamente plana — cero sesiones, cero eventos, ningún error por ningún lado. Nada me avisaba que estaba roto. Ese es el peor tipo de bug: el silencioso. La causa era un valor por default de Partytown enterrado en mi tema, y si corres un portafolio o blog sobre un tema estilo AstroWind, hay una probabilidad real de que el tuyo también esté muerto y no lo sepas.

Aquí está toda la trampa, por qué pasa a nivel de código, y el arreglo de una sola línea.

La prueba de 30 segundos: ¿tu GA realmente está disparando?

Antes de tocar código, confirma el síntoma. Abre tu sitio en producción, abre DevTools → Network, filtra por collect, y recarga:

  • GA funcionando: verás una petición a google-analytics.com/g/collect (o region1.google-analytics.com/g/collect) que regresa 204.
  • GA muerto: nada. Ninguna petición a collect.

Después revisa el código fuente de la página (pestaña Elements) buscando el script de gtag. Si tu GA está muerto como estaba el mío, vas a encontrar algo así:

<script type="text/partytown" async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>

¿Ves ese type="text/partytown"? Esa es la pistola humeante. El navegador no reconoce text/partytown como JavaScript ejecutable, así que parsea el tag, se encoge de hombros, y jamás lo corre. Tu script de analytics está ahí, en el HTML, inerte. GA “está instalado” y no recolecta nada. (Si todavía estás armando el resto de tu setup, analytics es solo una pieza de una checklist más grande que cubro en la configuración de SEO en Astro que la mayoría de los portafolios se salta.)

Por qué pasa: un default que asume una integración que desactivaste

Partytown es una idea genuinamente buena — mueve scripts pesados de terceros (como GA) fuera del hilo principal hacia un web worker, para que no te dañen los Core Web Vitals. El atributo type="text/partytown" es cómo le dices a Partytown “toma este script y córrelo en el worker en vez del hilo principal”.

El detalle: type="text/partytown" solo hace algo si la librería de Partytown realmente está cargada en la página para recoger esos scripts. Si no lo está, ese atributo es nada más una cadena de texto que el navegador ignora.

Y esa es exactamente la contradicción con la que vienen de fábrica los temas basados en AstroWind. Tres piezas se alinean para matar a GA:

1. El tema pone partytown en true por default. En el constructor de configuración, la integración de Google Analytics viene configurada para usar Partytown desde el inicio:

// vendor/integration/utils/configBuilder.ts
partytown: true,

2. Entonces el componente de GA marca sus scripts para Partytown. El componente <GoogleAnalytics> de @astrolib/analytics lee esa prop y, cuando es verdadera, le estampa el tipo text/partytown tanto al script que carga gtag como al script inline de configuración:

---
// @astrolib/analytics/GoogleAnalytics.astro
const { id, partytown = false } = Astro.props;
const attrs = partytown ? { type: 'text/partytown' } : {};
---

<script is:inline async src={`https://www.googletagmanager.com/gtag/js?id=${id}`} {...attrs}></script>
<script is:inline define:vars={{ id }} {...attrs}>
  // ...gtag('config', id)
</script>

3. Pero la integración de Partytown está desactivada. En astro.config.mjs, el tema pone a Partytown detrás de una bandera — y esa bandera viene en false:

// astro.config.mjs
const hasExternalScripts = false;
const whenExternalScripts = (items = []) =>
  hasExternalScripts ? (Array.isArray(items) ? items.map((i) => i()) : [items()]) : [];

export default defineConfig({
  integrations: [
    // ...
    ...whenExternalScripts(() => partytown({ config: { forward: ['dataLayer.push'] } })),
  ],
});

Con hasExternalScripts = false, whenExternalScripts(...) regresa un arreglo vacío, así que la integración de Partytown nunca se registra. Ningún runtime de Partytown llega al navegador.

Junta las tres piezas y tienes la trampa: el tema marca a GA para Partytown mientras nunca carga Partytown para manejarlo. El navegador ve type="text/partytown", decide que no es JavaScript que sepa correr, y lo salta. GA se emite y nunca se ejecuta. Sin error, porque nada falló — el navegador hizo exactamente lo que un tipo de script desconocido le indica hacer: nada.

El arreglo (una sola línea)

Tienes dos arreglos correctos, dependiendo de si quieres GA en el hilo principal o fuera de él.

Opción A — hacer que GA sea un script normal (una línea, se sube al instante). Dile a la integración de GA que deje de marcar sus scripts para Partytown. En config.yaml:

analytics:
  vendors:
    googleAnalytics:
      id: 'G-XXXXXXXXXX'
      partytown: false # carga GA como un <script> async normal en el hilo principal

Ahora attrs está vacío, el tipo text/partytown desaparece, y el navegador corre gtag como cualquier otro script. Este es el arreglo que yo subí a producción — para un blog estático, el costo de GA en el hilo principal es insignificante y la confiabilidad lo vale.

Opción B — de verdad activar Partytown. Si te importa exprimir a GA fuera del hilo principal por los Core Web Vitals, voltea el otro lado de la contradicción: pon hasExternalScripts = true en astro.config.mjs. Partytown ya es una dependencia en estos temas, así que esto registra el runtime que hace que text/partytown signifique algo. Un poco mejor de CWV, un poco más de piezas moviéndose.

Elige una. El bug es no tener ninguna de las dos consistente: marcado para Partytown, pero sin Partytown. No hagas las dos a medias.

Verifica que esté vivo

Sube el arreglo, y repite la prueba de 30 segundos: recarga la página en producción con la pestaña Network abierta, filtrada por collect. Ahora deberías ver la petición a g/collect disparar con un 204. Confírmalo también en GA4 → Reports → Realtime cargando tu propio sitio — deberías aparecer como usuario activo en cuestión de segundos.

La lección real: cuidado con los defaults que asumen una integración que desactivaste

Esto en realidad no es un bug de Partytown ni de Astro. Partytown hace exactamente lo que se le indica; Astro renderiza exactamente lo que el componente emite. El bug vive en la costura — un default (partytown: true) que asume en silencio una capacidad (hasExternalScripts: true) que un archivo de configuración distinto desactivó. Dos archivos, cada uno razonable por sí solo, contradictorios en conjunto.

Esas son las fallas que te cuestan meses, porque nada truena. El hábito que vale la pena construir: cuando conectas analytics, un webhook de pagos, un envío de correo — cualquier cosa donde “sin error” y “no funciona” se vean idénticos — no confíes en el dashboard, verifica el cable. Un solo vistazo a la pestaña Network me hubiera dicho en la primera semana lo que una gráfica de GA plana tardó mucho más en hacerme sospechar. Es la misma disciplina que aplico en mi rutina para validar un post de blog en Astro antes de publicarlo — revisar el resultado renderizado, no solo que el build haya pasado.

Si estás configurando uno de estos temas desde cero, mi análisis a fondo del template de AstroWind recorre cómo encajan sus capas de configuración — la misma capa por capa que hizo posible esta trampa. Y si quieres las herramientas que uso para atrapar este tipo de bugs de “costura silenciosa” más rápido, están en mi post sobre el stack de IA con el que desarrollo.

Ve a revisar tu propia petición a collect ahora mismo. Toma 30 segundos, y la versión de esta historia con la línea plana sale mucho más cara.

¿Te sirvió este artículo?

Recibe nuevos artículos sobre desarrollo web, IA y SEO directo en tu correo. Sin spam, cancela cuando quieras.

Sin spam. Al suscribirte aceptas la política de privacidad .

Volver al blog

Related Posts

View All Posts »
Cómo Valido un Post de Astro Antes de Publicarlo

Cómo Valido un Post de Astro Antes de Publicarlo

Publicar un post estático en Astro está a un merge de estar en vivo — justo por eso los bugs silenciosos son peligrosos. Un lang incorrecto, un canonical que da 404, un link entre idiomas que se filtró: nada de eso se ve en tu editor, solo en el HTML compilado. Aquí está el checklist que corro sobre dist/ antes de cada post, scripts incluidos.