SDK de lecture
@vskstudio/takt-read est un SDK TypeScript côté serveur au-dessus de l'API HTTP de lecture. Il encapsule les endpoints /api/v1/sites/{domain}/stats/* (authentifiés par clé Bearer) dans des méthodes typées, pour rapatrier tes statistiques dans un backend, un cron ou une route d'API sans écrire le HTTP à la main.
pnpm add @vskstudio/takt-read Il a zéro dépendance runtime, fournit ESM + CJS et nécessite Node.js ≥ 20 (fetch natif).
Démarrage rapide
import TaktClient from '@vskstudio/takt-read'
const takt = new TaktClient({
apiKey: process.env.TAKT_API_KEY!, // secret: à garder côté serveur
domain: 'exemple.com',
org: 'mon-org', // optionnel, requis seulement par stats.export() et stats.exportResult()
timeoutMs: 30_000, // optionnel, 30s par défaut
retries: 2 // optionnel, 2 par défaut (réessaie 429 + 5xx avec backoff)
})
const resume = await takt.stats.summary({ period: '30d' })
console.log(resume.visitors, resume.pageviews) baseUrl est optionnel : il vaut par défaut la racine de l’API de lecture hébergée
(https://taktlytics.com/api/v1). Renseigne-le pour viser un autre hôte (un proxy first-party,
un environnement de test) en gardant le préfixe /api/v1, par exemple https://proxy.exemple.com/api/v1. Le http:// simple n’est accepté que sur la boucle locale
(localhost, 127.0.0.1, [::1]) ; tout autre hôte doit être en https://. Le constructeur valide ses options et lève une TaktError (code: 'config_invalide') en
cas d’entrée invalide.
Options de TaktClient :
| Option | Type | Défaut | Rôle |
|---|---|---|---|
apiKey | string | aucun | Clé d’API avec la permission stats:read |
domain | string | aucun | Site interrogé (lié à la clé) |
org | string | aucun | Slug de l’org propriétaire de domain ; requis seulement par stats.export() et stats.exportResult() |
baseUrl | string | https://taktlytics.com/api/v1 | Racine de l’API de lecture (…/api/v1) |
fetch | typeof fetch | fetch global | Implémentation de fetch personnalisée |
timeoutMs | number | 30000 | Délai par requête |
retries | number | 2 | Réessais sur 429/5xx/réseau avec backoff |
Méthodes de stats
Tous les endpoints de lecture vivent sous takt.stats. Chaque méthode accepte un dernier
argument optionnel { signal } pour l’annulation via un AbortController.
| Méthode | Renvoie |
|---|---|
stats.summary(query?) | StatsSummary |
stats.timeseries(query?) | StatsTimeseries |
stats.breakdown(query & { dimension }) | StatsBreakdown |
stats.breakdowns(dimensions, query?) | StatsBreakdowns |
stats.realtime() | StatsRealtime |
stats.goals(query?) | StatsGoals |
stats.funnels(query?) | FunnelReports |
stats.properties(event, query?) | string[] |
stats.propertyBreakdown(event, key, query?) | PropertyBreakdown |
stats.propertyBreakdownBatch(request, query?) | PropertyBatchResponse |
stats.revenue(event, query?) | RevenueByCurrency |
stats.export(query?) | string (CSV) ou StatsExportRow[] (JSON) |
stats.exportResult(query?) | StatsExportResult<string> (CSV) ou StatsExportResult<StatsExportRow[]> (JSON) |
const ac = new AbortController()
const realtime = await takt.stats.realtime({ signal: ac.signal })
// Plusieurs classements en une requête
const { breakdowns } = await takt.stats.breakdowns(['pages', 'sources'], { period: '30d' })
// Export du classement des pages (nécessite `org` sur le client)
const csv = await takt.stats.export({ period: '30d' }) // chaîne CSV brute
const rows = await takt.stats.export({ period: '30d', format: 'json' }) // StatsExportRow[] L’export est borné côté serveur à 999 lignes et 256 Ko, en CSV comme en JSON. Quand la borne
coupe des lignes, l’API pose l’en-tête X-Takt-Truncated: true et le corps reste une chaîne CSV
ou un tableau JSON. stats.export() renvoie ce corps tel quel. stats.exportResult(), disponible
depuis takt-read 0.6.0, renvoie { data, truncated } pour savoir s’il manque des lignes :
const { data, truncated } = await takt.stats.exportResult({ period: '30d', format: 'json' })
if (truncated) {
// data ne contient que les premières lignes : resserrez la période ou le segment
} truncated vaut false si l’en-tête vaut false ou est absent. data a le même type que le
résultat de stats.export() pour le même format.
Options de requête
Les méthodes de lecture acceptent un StatsQuery optionnel : une period (day, 7d, 30d, month, 6mo, 12mo) ou un intervalle explicite from/to, plus tz, country, interval, compare, limit et des filtres segment.
await takt.stats.timeseries({
period: '30d',
interval: 'day',
tz: 'Europe/Paris',
compare: true, // inclut la période précédente
segment: [
{ dim: 'browsers', op: 'is', val: 'Firefox' },
{ dim: 'pages', op: 'not', val: '/blog', join: 'or' }
]
}) dimension et segment[].dim prennent une StatsDimension : pages, sources, countries, regions, cities, os, browsers, devices, utm_source, utm_medium, utm_campaign (au pluriel : page ou source ne sont pas valides). segment[].op vaut is ou not.
Gestion des erreurs
Les réponses non-2xx lèvent une TaktError portant le statut HTTP et le code d’erreur de
l’API. Le SDK lève aussi config_invalide sur des options invalides, timeout quand une
requête dépasse timeoutMs, et erreur_reseau en cas de panne réseau.
import { TaktError } from '@vskstudio/takt-read'
try {
await takt.stats.summary()
} catch (err) {
if (err instanceof TaktError && err.code === 'trop_de_requetes') {
await new Promise((resolve) => setTimeout(resolve, 10_000))
}
} 429 (trop_de_requetes) : attends le délai
de l'en-tête Retry-After avant de réessayer.
En amont, la passerelle plafonne aussi chaque adresse IP à 20 requêtes par seconde (pointes jusqu'à 100) : ce 429-là a un corps HTML et pas de Retry-After, attends une seconde. L'ingestion n'est jamais affectée.
Tu préfères le langage naturel ? Vois le serveur MCP.