Astro
Astro a une intégration dédiée : @vskstudio/takt-astro, bâtie sur le cœur @vskstudio/takt-core. Elle injecte un petit runtime navigateur qui boote Takt, émet le pageview initial et suit la navigation client — y compris les View Transitions d'Astro.
pnpm add @vskstudio/takt-astro @vskstudio/takt-core @vskstudio/takt-core (>=0.8.1) et astro (>=4) sont des peer dependencies. Le runtime est sûr au SSR / prerender : il est gardé par un test typeof window et ne s’exécute que dans le navigateur.
Cette page est la référence des options. Pour l’intégration de bout en bout et son piège principal — l’écouteur astro:page-load ajouté en trop, qui double chaque page vue — voir le guide analytics sans cookie sur un site Astro.
window.__takt : la seconde voie chargée ne réinitialise rien, elle ne fait strictement rien. Tu n'aurais donc pas de double comptage, juste un second script embarqué pour rien.Intégration (recommandé)
Ajoute takt() à la liste integrations de ta config Astro :
// astro.config.mjs
import { defineConfig } from 'astro/config'
import takt from '@vskstudio/takt-astro'
export default defineConfig({
integrations: [takt({ domain: 'exemple.fr' })]
}) Composant <Takt />
Pour un contrôle par layout, place le composant dans le <head> d’un layout :
---
import Takt from '@vskstudio/takt-astro/Takt.astro'
---
<head>
<Takt domain="exemple.fr" />
</head> L’intégration et le composant acceptent les mêmes options, à une exception près : scrubUrl est une fonction et n’est acceptée que par l’intégration (voir la note sous le tableau).
| Option | Type | Défaut | Rôle |
|---|---|---|---|
domain | string | location.hostname | Identifiant du site |
endpoint | string | https://taktlytics.com/api/event | URL d’ingestion ; mets /api/event pour un proxy first-party same-origin |
scriptOrigin | string | — | Origine dont dériver l’endpoint ({origin}/api/event), pour un domaine custom proxifié ; endpoint reste prioritaire |
outbound | boolean | false | Suit les liens sortants |
files | boolean | false | Suit les téléchargements |
spa | boolean | true | Suit la navigation client (mappé sur l’option auto du cœur) |
track404 | boolean | false | Signale un événement 404 sur les pages d’erreur (marqueur [data-takt-404] / <meta name="takt:404">, ou statut HTTP 404). |
tagged | boolean | false | Suit les éléments porteurs de data-takt-event |
respectDnt | boolean | true | Respecte Do Not Track |
excludeLocalhost | boolean | true | Ignore localhost / IP privées |
enabled | boolean | true | Interrupteur général : à false, plus aucun event |
sampleRate | number | 1 | Fraction de visiteurs suivis, de 0 à 1 |
trackQuery | boolean | false | Envoie l’URL complète au lieu d’en retirer query et hash |
queryParams | string[] | — | Liste blanche de paramètres conservés quand trackQuery est off |
exclude | string[] | — | Préfixes de chemin jamais suivis, ex. ['/app','/compte'] (bornés au segment : /app couvre /app et /app/…, pas /application) |
scrubUrl | (url: string) => string | — | Intégration seulement. Réécrit chaque URL avant envoi |
scrubUrl est une fonction : elle est sérialisée à la compilation via toString() puis réévaluée dans le navigateur. Elle doit donc être autonome — aucune variable de closure ni référence au scope englobant — et ne jamais être construite à partir d'entrées utilisateur. Le composant <Takt />, lui, sérialise sa config en îlot de données JSON, qui ne peut pas transporter de fonction : lui passer scrubUrl lève une erreur à la compilation plutôt que de l'ignorer en silence.View Transitions
Le ClientRouter d’Astro effectue plusieurs opérations d’historique par navigation (un replaceState de restauration de scroll, puis un pushState). Le patch d’historique du cœur compterait donc en double. L’intégration l’écarte : elle initialise le cœur avec auto: false, ce qui désactive à la fois le patch pushState/replaceState et le pageview de boot.
Le runtime pilote donc les pageviews depuis le cycle de vie d’Astro :
- un pageview initial explicite au boot du script — ce qui couvre aussi les sites MPA classiques, où le script est réexécuté à chaque chargement de page et où
astro:after-swapne se déclenche jamais ; - puis un pageview par événement
astro:after-swap, émis exactement une fois par navigation duClientRouter(échanges de DOM des View Transitions et retour/avant compris), quandspaest actif.
Chaque navigation est ainsi comptée exactement une fois.
astro:page-load pour suivre les pages : le runtime enregistre déjà son propre astro:after-swap. Le tien en installerait un second et compterait chaque navigation deux fois.history.pushState que tu pilotes à la main — filtres, onglets, pagination hors ClientRouter — ne déclenche aucun astro:after-swap, donc aucun pageview. C'est le seul cas où appeler pageview() toi-même est la bonne réponse.Events personnalisés
Les fonctions du cœur sont réexportées par commodité :
import { track } from '@vskstudio/takt-astro'
track('Signup', { revenue: { amount: '9.00', currency: 'USD' } }) track/pageview/optOut/optIn s’exécutent côté navigateur — appelle-les depuis un <script> client ou un composant d’un framework UI hydraté.