React
React a un wrapper dédié : @vskstudio/takt-react (provider, hooks, widgets, web component), bâti sur le cœur @vskstudio/takt-core.
pnpm add @vskstudio/takt-react @vskstudio/takt-core
# ou : npm install @vskstudio/takt-react @vskstudio/takt-core
# ou : yarn add @vskstudio/takt-react @vskstudio/takt-core
# ou : bun add @vskstudio/takt-react @vskstudio/takt-core react (^18 || ^19) et @vskstudio/takt-core (>=0.8.1) sont des peer dependencies : le cœur n’est pas installé automatiquement, ajoute-le explicitement.
Le package est entièrement typé et sûr au SSR / RSC (l’init n’a lieu qu’au montage, côté navigateur). L’entrée . embarque la directive 'use client', donc il s’intègre directement à l’App Router de Next.js. Il expose deux points d’entrée :
@vskstudio/takt-react— le provider<Takt>, les hooksuseTakt()etuseTaktEvent(), le composant<TaktEvent>, les widgets<TaktBadge>et<TaktEmbed>, ainsi que les helpers du cœur réexportés (badgeUrl(),embedUrl(),createStats(),PublicApiError).@vskstudio/takt-react/element— le web component<takt-analytics>sans React, pour du HTML pur.
Provider <Takt> + useTakt()
Place <Takt> une fois près de la racine : il initialise l’instance au montage, émet le pageview initial et câble la navigation SPA. useTakt() récupère l’instance partagée dans n’importe quel composant descendant pour émettre des events.
// app/layout.tsx (ou ton composant racine)
import { Takt } from '@vskstudio/takt-react'
export default function RootLayout({ children }) {
return (
<html lang="fr">
<body>
<Takt domain="exemple.fr" outbound files>
{children}
</Takt>
</body>
</html>
)
} <Takt> ne rend qu’un provider autour de ses enfants : sous l’App Router de Next.js, c’est bien au layout racine de rendre les balises <html> et <body>.
import { useTakt } from '@vskstudio/takt-react'
function SignupButton() {
const takt = useTakt()
return (
<>
<button onClick={() => takt.track('Signup', { props: { plan: 'pro' } })}>
S'inscrire
</button>
<button
onClick={() =>
takt.track('Purchase', {
props: { plan: 'pro' },
revenue: { amount: '29', currency: 'EUR' }
})
}
>
Acheter
</button>
</>
)
} Props du provider <Takt> :
| Prop | Type | Défaut | Rôle |
|---|---|---|---|
domain | string | location.hostname | Identifiant du site |
endpoint | string | https://taktlytics.com/api/event | URL d’ingestion. Passe /api/event pour un proxy first-party same-origin. |
scriptOrigin | string | — | Origine first-party dont dériver l’endpoint (l’origine suivie de /api/event). endpoint l’emporte. |
outbound | boolean | false | Suit les liens sortants |
files | boolean \| string[] | false | Suit les téléchargements (liste d’extensions optionnelle) |
spa | boolean | true | Suit la navigation client (pageviews auto) |
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 automatiquement les clics sur les éléments [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 coupe toute mesure |
sampleRate | number | 1 | Fraction de sessions échantillonnées (0–1) |
trackQuery | boolean | false | Conserve la query string dans les URL |
queryParams | string[] | — | Paramètres conservés quand trackQuery est false (liste blanche) |
exclude | string[] | — | Préfixes de chemin jamais suivis. Bornés au segment : /app couvre /app et /app/… mais pas /application. |
scrubUrl | (url: string) => string | — | Transforme chaque URL avant envoi |
Les props de config sont lues une seule fois au montage de <Takt> — les changer ensuite n’a aucun effet ; remonte le composant pour reconfigurer.
enabled, sampleRate, trackQuery, queryParams, exclude, scrubUrl) sont disponibles en props, sans piloter le cœur à côté. Seul debug n'est pas exposé : pour l'activer, instancie le cœur toi-même avec createTakt() — et n'utilise pas <Takt> en même temps, sous peine de doubler les pageviews. N'appelle jamais init() au niveau module dans un fichier rendu côté serveur : le cœur touche history à l'instanciation.scrubUrl est une fonction : elle ne peut pas traverser la frontière serveur → client de Next.js. Rends <Takt> depuis un composant client si tu la passes.
useTakt() ne lève jamais : appelé hors d’un <Takt> ou pendant le SSR, il renvoie une instance no-op. Les appels restent inoffensifs, mais le premier track() / pageview() émet un console.warn signalant que <Takt> n’est pas monté.
Hook useTaktEvent() + <TaktEvent>
Pour du tracking de clic déclaratif, useTaktEvent() renvoie un { onClick } que tu étales sur n’importe quel élément. L’instance est résolue au moment du clic (pas de closure périmée), avec un repli sur le track() du cœur :
import { useTaktEvent } from '@vskstudio/takt-react'
function BuyButtons() {
const signup = useTaktEvent({ name: 'Signup', props: { plan: 'pro' } })
const purchase = useTaktEvent({
name: 'Purchase',
revenue: { amount: '29', currency: 'EUR' }
})
return (
<>
<button {...signup}>S'inscrire</button>
<button {...purchase}>Acheter</button>
</>
)
} <TaktEvent> enveloppe un unique enfant et compose son onClick existant, pour annoter un élément sans toucher à son handler. Il forwarde les refs vers l’enfant :
import { TaktEvent } from '@vskstudio/takt-react'
function Cta({ onClick }) {
return (
<TaktEvent name="Signup" props={{ plan: 'pro' }}>
<button onClick={onClick}>S'inscrire</button>
</TaktEvent>
)
} Le onClick d’origine de l’enfant se déclenche toujours ; le tracking tourne en parallèle.
Widgets <TaktBadge> et <TaktEmbed>
Pour afficher les statistiques publiques d’un site (voir Widgets), le package fournit deux composants prêts à poser :
import { TaktBadge, TaktEmbed } from '@vskstudio/takt-react'
function Footer() {
return (
<>
<TaktBadge domain="exemple.fr" variant="b" glyph="dash" lang="fr" />
<TaktEmbed domain="exemple.fr" theme="dark" lang="fr" />
</>
)
} <TaktBadge> rend une <img> (loading="lazy", decoding="async") : variant vaut a, b ou d, glyph vaut unplug, dash, off ou eyeoff. <TaktEmbed> rend une <iframe> de 404×264 par défaut, loading="lazy" et sandboxée : theme vaut light, dark ou auto. Les deux acceptent lang (fr / en), une prop host pour pointer une autre origine Takt, et forwardent le reste de leurs attributs à l’élément rendu.
Web component <takt-analytics>
Pour du HTML pur ou un framework non-React, importe l’élément sans React (auto-enregistré) :
<script type="module">
import '@vskstudio/takt-react/element'
</script>
<takt-analytics domain="exemple.fr" outbound files></takt-analytics> Les attributs miroir des props, en kebab-case :
- Drapeaux (présence = actif, valeur ignorée) :
outbound,files,tagged. - Actifs par défaut, mets
="false"(ou="0") pour les couper :spa,respect-dnt,exclude-localhost. - Valeurs :
domain,endpoint,script-origin,enabled,sample-rate,track-query, ainsi quequery-paramsetexcludequi prennent une liste séparée par des virgules.
<takt-analytics domain="exemple.fr" spa="false" respect-dnt="false"></takt-analytics> files ne prend pas de liste d’extensions ici, et scrubUrl n’a pas d’équivalent : ce sont des valeurs que seul le provider <Takt> reçoit en props. La détection 404 passe elle aussi par la prop track404. Le bundle est sûr au SSR : l’importer côté serveur est un no-op tant que customElements n’existe pas.