@kody/fathom-analytics
Read Fathom Analytics site stats, aggregation reports, and current visitors.
AGENTS.md
120 lines · 3.5 KB · Markdown@kody/fathom-analytics — agent notes
Human setup and intent live in README.md. This file is for
agents: imports, smoke execute snippets, and edge cases. Secrets by name
only — never paste token values. Do not disable live webhooks or jobs.
Auth
| Item | Value |
|---|---|
| Secret | FATHOM_ANALYTICS_API_TOKEN (user scope) |
| Placeholder | {{secret:FATHOM_ANALYTICS_API_TOKEN|scope=user}} |
| Header | Authorization: Bearer … |
| API base | https://api.usefathom.com/v1 |
| Approved host | api.usefathom.com |
Prefill save URL: https://kody.codes/account/secrets/new?name=FATHOM_ANALYTICS_API_TOKEN&description=Fathom%20Analytics%20API%20token&allowedHosts=api.usefathom.com&scope=user
Import paths
Single export surface — root dispatcher plus named helpers from the same module:
| Export | Import / call |
|---|---|
| root dispatcher | kody:@kody/fathom-analytics |
| named helpers | import { smokeTest, listSites, aggregate, getSiteTrafficSummary, getCurrentVisitors, request, … } from 'kody:@kody/fathom-analytics' |
Prefer static kody:@kody/fathom-analytics imports from execute. Do not lead
with packages.invoke.
Dispatcher actions: overview (default), smokeTest, request, getAccount,
getToken, listSites, getSite, listEvents, getEvent, aggregate,
getCurrentVisitors, getSiteTrafficSummary.
Smoke test (read-only)
Costs 2 API requests (pageviews against the plan).
import { smokeTest } from 'kody:@kody/fathom-analytics'
export default async function main() {
return await smokeTest()
// => { token: { name, abilities, expiresAt }, siteCount, sites: [{ id, name }] }
}Equivalent via dispatcher:
import fathom from 'kody:@kody/fathom-analytics'
export default async function main() {
return await fathom({ action: 'smokeTest' })
}Common snippets
Briefing-ready summary (costs 3 requests):
import fathom from 'kody:@kody/fathom-analytics'
export default async function main() {
const access = await fathom({ action: 'smokeTest' })
const siteId = access.sites?.[0]?.id
if (!siteId) return { access, summary: null }
return await fathom({
action: 'getSiteTrafficSummary',
siteId,
days: 7,
})
}Top paths by pageviews:
import { aggregate } from 'kody:@kody/fathom-analytics'
export default async function main() {
return await aggregate({
siteId: 'SITE_ID',
aggregates: 'pageviews,uniques',
fieldGrouping: 'pathname',
sortBy: 'pageviews:desc',
limit: 20,
dateFrom: '2026-07-01 00:00:00',
filters: [{ property: 'pathname', operator: 'is like', value: '/blog/*' }],
})
}Current visitors:
import { getCurrentVisitors } from 'kody:@kody/fathom-analytics'
export default async function main() {
return await getCurrentVisitors({ siteId: 'SITE_ID', detailed: true })
}Edge cases
- Every request counts as one pageview; prefer
getSiteTrafficSummaryover inventing three separate aggregations yourself. - Aggregation numeric fields are strings from the API;
getSiteTrafficSummaryconverts them to numbers. - Aggregation data is accurate from March 2021 onwards;
date_from/date_touse the site's reporting timezone. requeststays onhttps://api.usefathom.com/v1and retries 429/5xx honoringRetry-After.- List helpers default to
limit: 100and surfacehasMoreplus cursor hooks (startingAfter/endingBefore). - No dedicated mutation helpers — use
requestonly when the user explicitly asks to create/update/delete.