takt

Svelte

Svelte a un wrapper dédié : @vskstudio/takt-svelte (composant, action, web component), bâti sur le cœur @vskstudio/takt-core.

Le cœur est une dépendance peer : installe les deux paquets. Depuis la 0.8.0, le wrapper exige @vskstudio/takt-core >=0.10.0.

pnpm add @vskstudio/takt-svelte @vskstudio/takt-core
# ou : npm install @vskstudio/takt-svelte @vskstudio/takt-core
# ou : yarn add @vskstudio/takt-svelte @vskstudio/takt-core
# ou : bun add @vskstudio/takt-svelte @vskstudio/takt-core

Le package expose trois styles d’intégration :

  • @vskstudio/takt-svelte : le composant <Takt> + le hook useTakt(), et les fonctions de consentement optOut() / optIn() / isOptedOut() réexportées du cœur.
  • @vskstudio/takt-svelte/actions : l’action use:taktEvent + les fonctions init/track/pageview/optOut/optIn/isOptedOut réexportées du cœur.
  • @vskstudio/takt-svelte/element : le web component <takt-analytics> pour du HTML pur.
Seuls <Takt> et <takt-analytics> sont sûrs au SSR : ils n'initialisent qu'au montage, côté navigateur. Le init() du sous-chemin /actions touche history dès l'appel. L'exécuter dans le <script> d'un composant SvelteKit le fait tourner au rendu serveur et lève ReferenceError: history is not defined. Appelle-le depuis onMount.

Cette page est la référence des options. Pour l’intégration de bout en bout dans une application SvelteKit et son piège principal (useTakt() appelé dans le <script> d’un composant, donc avant le montage de <Takt>) : voir le guide analytics sans cookie dans une application SvelteKit.

Composant <Takt> + useTakt()

Place <Takt> une fois (typiquement dans +layout.svelte) : il initialise l’instance au montage, émet le pageview initial et câble la navigation SPA. Le composant ne rend aucun balisage. C’est un point de câblage, pas un conteneur, et il n’a donc pas d’enfants. useTakt() récupère l’instance depuis n’importe où dans l’application (un store de module sert de relais), pas seulement sous <Takt>.

<!-- +layout.svelte -->
<script>
  import { Takt } from '@vskstudio/takt-svelte'
</script>

<Takt domain="exemple.fr" outbound files />
<slot />

Appelle useTakt() dans le gestionnaire, pas dans le <script> : le <script> s’exécute à l’initialisation du composant, donc avant le onMount de <Takt>. Une instance capturée là serait le no-op définitif, et tous les events partiraient dans le vide.

<script>
  import { useTakt } from '@vskstudio/takt-svelte'
</script>

<button onclick={() => useTakt().track('Signup', { props: { plan: 'pro' } })}>
  S'inscrire
</button>

<button
  onclick={() =>
    useTakt().track('Purchase', {
      props: { plan: 'pro' },
      revenue: { amount: '29', currency: 'EUR' }
    })}
>
  Acheter
</button>

Props du composant <Takt> :

PropTypeDéfautRôle
domainstringlocation.hostnameIdentifiant du site
endpointstringhttps://taktlytics.com/api/eventURL d’ingestion. Passe /api/event pour un proxy first-party same-origin.
scriptOriginstringaucunOrigine first-party dont dériver l’endpoint (l’origine suivie de /api/event). endpoint l’emporte.
outboundbooleanfalseSuit les liens sortants
filesboolean \| string[]falseSuit les téléchargements (liste d’extensions optionnelle)
spabooleantrueSuit la navigation client (pageviews auto)
track404booleanfalseSignale un événement 404 sur les pages d’erreur (marqueur [data-takt-404] / <meta name="takt:404">, ou statut HTTP 404).
taggedbooleanfalseSuit automatiquement les éléments [data-takt-event]
respectDntbooleantrueRespecte Do Not Track
excludeLocalhostbooleantrueIgnore localhost / IP privées
enabledbooleantrueInterrupteur général : false coupe toute mesure
sampleRatenumber1Fraction de sessions échantillonnées (0 à 1)
trackQuerybooleanfalseConserve la query string dans les URL
queryParamsstring[]aucunParamètres conservés quand trackQuery est false (liste blanche)
excludestring[]aucunPréfixes de chemin jamais suivis. Bornés au segment : /app couvre /app et /app/… mais pas /application.
scrubUrl(url: string) => stringaucunTransforme chaque URL avant envoi (page, referrer, url des liens sortants et des téléchargements, path des 404)
debugbooleanfalseTrace chaque payload dans la console avant l’envoi
redactRoutesstring[]aucunMotifs de routes sensibles envoyés à la place du chemin réel, ex. ['/verify/[token]'] (voir Masquage de routes)
redactUndecodablePathsbooleantrueNon exposée par ce wrapper : se règle sur le SDK core (init() / createTakt()), voir Chemins illisibles
routeTemplatesbooleanfalseEnvoie chaque page sous la forme de son gabarit de route ; exige routeTemplate
routeTemplate() => string \| null \| undefinedaucunRenvoie le gabarit de la route courante, ex. () => page.route.id avec SvelteKit
Le composant forwarde toutes ces options au cœur : les réglages avancés (enabled, sampleRate, trackQuery, queryParams, exclude, scrubUrl) sont disponibles en props, sans passer par le sous-chemin /actions, tout comme debug depuis la 0.7.0.

useTakt() ne lève pas : appelé avant le montage de <Takt> ou pendant le SSR, il renvoie une instance no-op et avertit une fois en console (useTakt() called before <Takt /> mounted). Ce message est le symptôme du piège ci-dessus. Les appels de consentement font exception : ils agissent réellement, voir Consentement.

Masquage de routes

La query string est retirée par défaut, mais le chemin part en clair : /verify/abc123 transmet le jeton. redactRoutes liste les routes sensibles, et un chemin qui correspond part sous la forme de son motif. Tous les autres chemins gardent leur valeur réelle, les statistiques par page restent intactes.

<Takt domain="exemple.fr" redactRoutes={['/verify/[token]', '/reset/[code]', '/invoices/[id].pdf']} />

Les motifs acceptent la syntaxe SvelteKit ([param], [[optionnel]], [...reste], (groupe)) ainsi que :param, :param?, * et **. La règle couvre l’URL de la page, le referrer du même site, la destination des téléchargements et le chemin des 404.

Pour une application entièrement privée, routeTemplates envoie chaque page sous la forme de son gabarit : /blog/bonjour devient /blog/[slug]. Le package ne dépend pas de SvelteKit, tu lui passes donc le résolveur. Avec SvelteKit, lis-le depuis page.route.id :

<!-- +layout.svelte -->
<script>
  import { page } from '$app/state'
  import { Takt } from '@vskstudio/takt-svelte'
</script>

<Takt domain="exemple.fr" routeTemplates routeTemplate={() => page.route.id} />

Les groupes de route comme (marketing) sont retirés par le cœur : /(marketing)/blog/[slug] part comme /blog/[slug]. Quand le résolveur renvoie null (aucune route trouvée), redactRoutes s’applique quand même, sinon le chemin réel part. Sur un site public, ce mode fusionne tous les articles en une seule ligne : préfère redactRoutes. init() du sous-chemin /actions accepte les mêmes options. Détails dans Vie privée.

Consentement

optOut, optIn et isOptedOut sont exportés depuis la racine du package (et depuis ./actions). Ils n’ont besoin d’aucune instance : une bannière de consentement peut enregistrer le choix du visiteur avant le montage de <Takt>, et l’instance créée ensuite le respecte. Sur l’instance no-op, useTakt().optOut(), useTakt().optIn() et useTakt().isOptedOut() délèguent aussi à ces fonctions.

<script>
  import { optOut, optIn, isOptedOut } from '@vskstudio/takt-svelte'

  let optedOut = $state(isOptedOut())

  function toggle(event) {
    if (event.currentTarget.checked) optIn()
    else optOut()
    optedOut = isOptedOut()
  }
</script>

<label>
  <input type="checkbox" checked={!optedOut} onchange={toggle} />
  Mesure d'audience
</label>

isOptedOut() lit le localStorage : sur un composant rendu côté serveur, appelle-le dans le navigateur (onMount ou un gestionnaire d’événement).

Action use:taktEvent

Sans composant, initialise toi-même via init(), puis attache taktEvent à un élément cliquable. init() doit être appelé depuis onMount : au niveau du <script>, il s’exécuterait au rendu serveur et lèverait ReferenceError: history is not defined.

<script>
  import { onMount } from 'svelte'
  import { init, taktEvent } from '@vskstudio/takt-svelte/actions'

  onMount(() => init({ domain: 'exemple.fr', sampleRate: 0.5, trackQuery: false }))
</script>

<button use:taktEvent={{ name: 'Signup', props: { plan: 'pro' } }}>
  S'inscrire
</button>

<button use:taktEvent={{ name: 'Purchase', revenue: { amount: '29', currency: 'EUR' } }}>
  Acheter
</button>

L’action est réactive : si les paramètres changent, les clics suivants utilisent les nouvelles valeurs. Le listener est retiré à la destruction de l’élément.

Web component <takt-analytics>

Pour du HTML pur ou un framework non-Svelte, importe l’élément (auto-enregistré) :

<script type="module">
  import '@vskstudio/takt-svelte/element'
</script>

<takt-analytics domain="exemple.fr" outbound files></takt-analytics>

Les attributs miroir des props :

  • Drapeaux (présence = actif, valeur ignorée) : outbound, files, track-404, tagged.
  • Actifs par défaut, mets ="false" pour les couper : spa, respect-dnt, exclude-localhost. Les graphies historiques en un mot respectdnt et excludelocalhost restent acceptées.
  • Valeurs : domain, endpoint, script-origin, enabled, sample-rate, track-query, debug (lu seulement si l’attribut est présent), ainsi que query-params, exclude et redact-routes qui prennent une liste séparée par des virgules (redact-routes="/verify/[token],/reset/:code").

routeTemplates et routeTemplate n’ont pas d’attribut : l’élément n’a pas de routeur. files ne prend pas de liste d’extensions ici, et scrubUrl n’a pas d’équivalent : ce sont des fonctions et des tableaux que le composant Svelte reçoit en props, hors de portée d’un attribut HTML.