takt

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).

Your read API key is a secret. Use this SDK server-side only — never ship it in a browser bundle.

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:

OptionTypeDefaultRole
apiKeystringAPI key with the stats:read permission
domainstringSite to query (bound to the key)
orgstringOrg slug owning domain; only needed by stats.export()
baseUrlstringRoot of the Read API (…/api/v1)
fetchtypeof fetchglobal fetchCustom fetch implementation
timeoutMsnumber30000Per-request timeout
retriesnumber2Retries 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.

MethodReturns
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)
  }
}
The SDK consumes the same metered Read API as direct HTTP calls: past your monthly API request quota the endpoints return 402 (quota_api_depasse). Ingestion is never affected. Prefer natural language? See the MCP server.