A fully-typed unofficial TypeScript SDK for interacting with the Fathom Analytics API. Works in any JavaScript runtime environment that supports the Fetch API, including browsers, Node.js (v18+), Bun, Deno, Cloudflare Workers, and more.
- 🔒 Full TypeScript support with accurate type definitions
- 🚀 Support for all Fathom Analytics API endpoints (as of writing)
- 📊 Detailed response types for all API resources
- 🔄 Promise-based API with async/await support
- 📈 Smart pagination for listing resources
- 🔍 Comprehensive methods for sites, events, reports, and more
- ⚡ Works in any JavaScript runtime with Fetch API support
- 🔮 Full support for current API capabilities and versioning for future proofing
Use your favorite package manager and registry (npm, jsr, and GitHub Packages) to install the package:
npm install @mackenly/fathom-api
yarn add @mackenly/fathom-api
pnpm add @mackenly/fathom-api
deno add jsr:@mackenly/fathom-api
import * as fathom_api from "jsr:@mackenly/fathom-api";
bun add @mackenly/fathom-api
Get an API token from your Fathom Analytics account settings and use it to create a new client.
Warning
Use permissions to restrict the API token to only the necessary operations (ex: Admin
, All sites (read only)
, Site specific
)
import FathomApi from '@mackenly/fathom-api';
// Create a new client with your API token
const fathom = new FathomApi({
token: 'your-api-token',
// Optional parameters
// version: 'v1',
// baseUrl: 'https://api.usefathom.com'
});
// Example: Get account information
async function getAccountInfo() {
try {
const account = await fathom.api.account.get();
console.log('Account:', account);
} catch (error) {
if (error instanceof FathomApiError) {
console.error('API Error:', error.message);
} else {
console.error('Error:', error);
}
}
}
getAccountInfo();
// List all sites
const sites = await fathom.api.getAllSites();
// Get a specific site
const site = await fathom.api.sites.get('SITEID');
// Create a new site
const newSite = await fathom.api.sites.create({
name: 'My New Website'
});
// Update a site
const updatedSite = await fathom.api.sites.update('SITEID', {
name: 'Updated Website Name',
sharing: 'private',
share_password: 'password123'
});
// Wipe site data
const wipedSite = await fathom.api.sites.wipe('SITEID');
// Delete a site
const deletedSite = await fathom.api.sites.delete('SITEID');
// List all events for a site
const events = await fathom.api.getAllEvents('SITEID');
// Get a specific event
const event = await fathom.api.events('SITEID').get('EVENT_ID');
// Create a new event
const newEvent = await fathom.api.events('SITEID').create({
name: 'Newsletter Signup'
});
// Update an event
const updatedEvent = await fathom.api.events('SITEID').update('EVENT_ID', {
name: 'Updated Event Name'
});
// Wipe event data
const wipedEvent = await fathom.api.events('SITEID').wipe('EVENT_ID');
// Delete an event
const deletedEvent = await fathom.api.events('SITEID').delete('EVENT_ID');
// Get aggregation report for pageviews
const pageviewReport = await fathom.api.reports.aggregation({
entity: 'pageview',
entity_id: 'SITEID',
aggregates: 'visits,uniques,pageviews',
date_grouping: 'day',
field_grouping: 'pathname',
date_from: '2022-01-01',
date_to: '2022-01-31',
filters: [
{
property: 'pathname',
operator: 'is',
value: '/blog'
}
]
});
// Get aggregation report for events
const eventReport = await fathom.api.reports.aggregation({
entity: 'event',
entity_id: 'EVENT_ID',
aggregates: 'conversions,unique_conversions',
date_grouping: 'month'
});
// Get current visitors
const currentVisitors = await fathom.api.reports.currentVisitors({
site_id: 'SITEID',
detailed: true
});
This SDK is designed to support potential future API versions. The default version and, as of writing, the only version is v1, but you can specify a different version when creating the client or accessing the API:
// Specify version at initialization
const fathom = new FathomApi({
token: 'your-api-token',
version: 'v1'
});
// Or access a specific version after initialization
const v1 = fathom.version('v1');
new FathomApi(options: {
token: string; // Your Fathom API token
version?: 'v1'; // API version to use (default: 'v1')
baseUrl?: string; // API base URL (default: 'https://api.usefathom.com')
})
.api.account
- Account operations.api.sites
- Site operations.api.events(siteId)
- Event operations for a specific site.api.reports
- Report generation.api.*
- Variety of convenience methods for common operations
The SDK throws FathomApiError
instances for API errors. These include an error
property with the error message from the API and a status
property with the HTTP status code:
import { FathomApi, FathomApiError } from '@mackenly/fathom-api';
try {
const result = await fathom.api.sites.get('non-existent-site');
} catch (error) {
if (error instanceof FathomApiError) {
console.error(`API Error (${error.status}):`, error.error);
} else {
console.error('Unexpected error:', error);
}
}
List operations support pagination parameters:
const firstTwentySites = await fathom.api.sites.list({ limit: 20 });
Or to get all sites with automatic pagination:
const allSites = await fathom.api.getAllSites();
If you're using this browser in frontend code or other applications where you might want to not include your API key, you can create a server-side request proxy to forward requests to the Fathom API, validate incoming API keys, and add your Fathom API key for the actual request to Fathom. Here's an example:
In your client side code:
const fathom = new FathomApi({
token: 'temp_token',
baseUrl: 'https://your-proxy-server.com'
});
A Cloudflare Worker:
export default {
async fetch(request) {
// Only allow GET requests for this example
if (request.method !== 'GET') {
return new Response('Method not allowed', { status: 405 });
}
const url = new URL(request.url);
const targetUrl = new URL(url.pathname + url.search, 'https://api.usefathom.com');
const newHeaders = new Headers(request.headers);
let authHeader = newHeaders.get('Authorization');
// Modify this to validate incoming API keys (perhaps from a database)
if (authHeader && authHeader.includes('temp_token')) {
authHeader = authHeader.replace('temp_token', 'real_token');
newHeaders.set('Authorization', authHeader);
}
return await fetch(targetUrl.toString(), {
method: 'GET',
headers: newHeaders,
});
}
}
This library is tested for compatibility with:
- Node.js 18+
- Modern browsers (Chrome, Firefox, Safari, Edge)
- Cloudflare Workers
- Bun
- Deno
Warning
If running in a browser environment or anywhere that users could access the API token, it is recommended to use a server-side proxy to keep the token secure rather than exposing it directly in client-side code.
The library uses standard Web APIs and modern JavaScript features that are widely supported across JavaScript environments.
Contributions are welcome! Please feel free to submit a Pull Request.
This project is not affiliated with, part of, or endorsed by Fathom Analytics or Conva Ventures Inc. For Fathom issues or support requests not related to this package, please contact the Fathom team directly. For enterprise support for this package, please contact Tricities Media Group.