Read SDK
@vskstudio/takt-read is a server-only TypeScript SDK over the HTTP Read API. It wraps the Bearer-authenticated /api/v1/sites/{domain}/stats/* endpoints in typed methods, so you can pull your analytics into a backend, a cron job or an API route without writing HTTP by hand.
pnpm add @vskstudio/takt-read It has zero runtime dependencies, ships ESM + CJS, and needs Node.js ≥ 18 (native fetch).
Quick start
import TaktClient from '@vskstudio/takt-read'
const takt = new TaktClient({
apiKey: process.env.TAKT_API_KEY!, // secret — keep it server-side
domain: 'example.com',
baseUrl: 'https://app.taktlytics.com/api/v1',
timeoutMs: 30_000, // optional, default 30s
retries: 2 // optional, default 2 (retries 429 + 5xx with backoff)
})
const summary = await takt.stats.summary({ period: '30d' })
console.log(summary.visitors, summary.pageviews) baseUrl is required: point it at your Takt instance’s /api/v1 root. The constructor
validates its options and throws a TaktError (code: 'config_invalide') on bad input.
TaktClient options:
| Option | Type | Default | Role |
|---|---|---|---|
apiKey | string | — | API key with the stats:read permission |
domain | string | — | Site to query (bound to the key) |
org | string | — | Org slug owning domain; only needed by stats.export() |
baseUrl | string | — | Root of the Read API (…/api/v1) |
fetch | typeof fetch | global fetch | Custom fetch implementation |
timeoutMs | number | 30000 | Per-request timeout |
retries | number | 2 | Retries on 429/5xx/network with backoff |
Stats methods
All read endpoints live under takt.stats. Every method takes an optional final { signal } argument for cancellation via an AbortController.
| Method | Returns |
|---|---|
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) or StatsExportRow[] (JSON) |
const ac = new AbortController()
const realtime = await takt.stats.realtime({ signal: ac.signal })
// Several rankings in one request
const { breakdowns } = await takt.stats.breakdowns(['pages', 'sources'], { period: '30d' })
// Page ranking export (needs `org` on the client)
const csv = await takt.stats.export({ period: '30d' }) // raw CSV string
const rows = await takt.stats.export({ period: '30d', format: 'json' }) // StatsExportRow[] Query options
Read methods accept an optional StatsQuery: a period (day, 7d, 30d, month, 6mo, 12mo) or an explicit from/to range, plus tz, country, interval, compare, limit and segment filters.
await takt.stats.timeseries({
period: '30d',
interval: 'day',
tz: 'Europe/Paris',
compare: true, // include the previous period
segment: [
{ dim: 'browser', op: 'is', val: 'Firefox' },
{ dim: 'page', op: 'contains', val: '/blog', join: 'or' }
]
}) Error handling
Non-2xx responses throw a TaktError carrying the HTTP status and the API’s error code.
The SDK also raises config_invalide on bad options, timeout when a request exceeds timeoutMs, and erreur_reseau on network failure.
import { TaktError } from '@vskstudio/takt-read'
try {
await takt.stats.summary()
} catch (err) {
if (err instanceof TaktError && err.code === 'quota_api_depasse') {
// monthly API quota exhausted (HTTP 402)
}
} 402 (quota_api_depasse).
Ingestion is never affected. Prefer natural language? See the MCP server.