# Sarutobi
> Sarutobi est une plateforme de Product Analytics auto-hébergée, écrite en TypeScript (Next.js, PostgreSQL, Drizzle, Better Auth). Elle relie collecte d'événements, identité persistante, exploration et décision : pages vues, visites, sessions, personnes, groupes, funnels, rétention, cohortes, parcours, feature flags, expériences, Web Vitals et erreurs JavaScript. Les SDK navigateur pèsent moins de 5 ko gzip, n'ont aucune dépendance runtime et ne peuvent jamais faire échouer le site instrumenté. Un serveur MCP expose les mêmes mesures aux agents.
Le produit et sa documentation sont en **français** ; le code, les routes et les noms d'API sont en **anglais**. Instance officielle : `https://sarutobi.ascencia.re`. Dépôt : `https://github.com/pedrokarim/sarutobi` (MIT).
Repères pour intégrer sans rien lire d'autre :
- **La clé d'un site s'appelle `siteId`.** Elle ressemble à `st_live_8f3a1c9d2e4b6071` et s'obtient sur la page **Installation** du site, dans le dashboard. Elle **n'est pas un secret** : elle transite en clair dans le JavaScript. Ce qui protège les chiffres, c'est la liste des domaines autorisés déclarée sur le site. Ne jamais l'appeler « token » ni « clé d'API ».
- **La clé serveur `st_secret_…`** est réservée à `@ascencia/sarutobi-node` et ne doit jamais atteindre un bundle client.
- **Installer** : `bun add @ascencia/sarutobi-react@next` (React, Next.js) ou `@ascencia/sarutobi-js@next` (vanilla, Vue, Svelte). Sans bundler : ``.
- **Brancher** : `` en React, `sarutobi.init({ siteId })` ailleurs. Pages vues, visites, referrers, UTM, pays, appareil, Core Web Vitals et erreurs JavaScript sont collectés sans autre instrumentation.
- **API** : `capture(name, props?)`, `identify(id, props?)`, `reset()`, `setConsent(state)`, `pageview(path?)`, `setContext(props)`, `group(type, key, props?)`, `groupIdentify(type, key, props)`, `isFeatureEnabled(key)`, `getFeatureFlag(key)`, `flush()`. Aucune méthode ne renvoie de promesse ; aucune ne fait attendre l'appelant.
- **Ingestion** : `POST /api/collect`, corps JSON envoyé en `text/plain;charset=UTF-8` pour éviter le pré-vol CORS, 1 à 20 events par lot, 32 ko maximum. Réponse `202` au corps toujours vide.
- **En développement, rien n'est envoyé** : le SDK se désactive seul sur `localhost`, `127.0.0.1` et les domaines en `.localhost`. Passer `enabled: true` pour tester en local.
- **Un `202` veut dire « accepté », pas « visible »** : le temps réel lit les visites brutes, les courbes lisent des agrégats recalculés toutes les dix minutes par un cron.
- **Nommer un event** : verbe au passé en `snake_case`, jamais d'identifiant dans le nom, propriétés à faible cardinalité, jamais de donnée personnelle. Trente-deux clés par event, cinq cent douze caractères par valeur ; chaînes, nombres, booléens et `null` uniquement.
- **Consentement** : le SDK démarre en `consent: "pending"` et ne crée aucun identifiant avant `setConsent("granted")`.
## Démarrer
- [Démarrage rapide](https://sarutobi.ascencia.re/docs) : récupérer la clé du site, installer le paquet, brancher le provider, vérifier la réception du premier event.
- [Comment ça fonctionne](https://sarutobi.ascencia.re/docs/fonctionnement) : le trajet d'un event du SDK au dashboard, la latence des rollups, ce que répond chaque écran, et pourquoi visite, session et personne sont trois choses distinctes.
- [Next.js](https://sarutobi.ascencia.re/docs/nextjs) : App Router et Pages Router, `disabled` réévalué à chaque rendu, Content Security Policy, `NEXT_PUBLIC_SARUTOBI_SITE_ID`.
- [React et autres frameworks](https://sarutobi.ascencia.re/docs/react) : le hook `useSarutobi()`, l'usage hors composant, Vue, Svelte, vanilla, SPA et rendu côté serveur.
- [Sans bundler](https://sarutobi.ascencia.re/docs/script) : la balise `