Privacy-focused analytics for React, Next.js, and React Native.
π Full Documentation Β· API Reference Β· Troubleshooting
npm install react-fathom fathom-client// App.tsx or layout.tsx
import { FathomProvider } from 'react-fathom'
function App() {
return (
<FathomProvider siteId="YOUR_FATHOM_SITE_ID">
<YourApp />
</FathomProvider>
)
}// Any component
import { useFathom } from 'react-fathom'
function MyComponent() {
const { trackEvent } = useFathom()
return <button onClick={() => trackEvent('signup-click')}>Sign Up</button>
}Pageviews are tracked automatically.
Fathom Analytics is a privacy-focused alternative to Google Analyticsβno cookies, no consent banners, GDPR compliant by default.
The official fathom-client works, but:
| Problem | react-fathom solution |
|---|---|
| Web onlyβno React Native | Full React Native support with offline event queuing |
| Next.js App Router requires boilerplate | NextFathomProviderApp works directly in Server Component layouts |
| Imperative API only | Hooks (useFathom, useTrackOnMount, useTrackOnVisible) and declarative components (<TrackClick>, <TrackVisible>) |
| No tree-shaking | Fully tree-shakeableβbundle only what you use |
New to Fathom? Get a $10 credit with this referral link.
- π Privacy-first Fathom Analytics integration
- βοΈ Hooks API and declarative tracking components
- π± React Native with offline queuing and navigation tracking
- β‘ Next.js App Router and Pages Router support
- π€οΈ React Router v6+ and Remix support
- π Gatsby support with @reach/router integration
- π§ TanStack Router support with type-safe routing
- π Debug mode for development with event subscription hooks
- π³ Tree-shakeable, fully typed (TypeScript)
// app/layout.tsx
import { NextFathomProviderApp } from 'react-fathom/next'
export default function RootLayout({ children }) {
return (
<html>
<body>
<NextFathomProviderApp siteId="YOUR_SITE_ID">
{children}
</NextFathomProviderApp>
</body>
</html>
)
}π Full Next.js guide
// pages/_app.tsx
import { FathomProvider } from 'react-fathom'
import { NextFathomTrackViewPages } from 'react-fathom/next'
function MyApp({ Component, pageProps }) {
return (
<FathomProvider siteId="YOUR_SITE_ID" clientOptions={{ auto: false }}>
<NextFathomTrackViewPages />
<Component {...pageProps} />
</FathomProvider>
)
}π Full Next.js guide
// App.tsx or root.tsx
import { BrowserRouter } from 'react-router-dom'
import { FathomProvider } from 'react-fathom'
import { ReactRouterFathomTrackView } from 'react-fathom/react-router'
function App() {
return (
<BrowserRouter>
<FathomProvider siteId="YOUR_SITE_ID" clientOptions={{ auto: false }}>
<ReactRouterFathomTrackView />
<Routes>...</Routes>
</FathomProvider>
</BrowserRouter>
)
}// gatsby-browser.js or Layout component
import { FathomProvider } from 'react-fathom'
import { GatsbyFathomTrackView } from 'react-fathom/gatsby'
export const wrapRootElement = ({ element }) => (
<FathomProvider siteId="YOUR_SITE_ID" clientOptions={{ auto: false }}>
<GatsbyFathomTrackView />
{element}
</FathomProvider>
)π Full Gatsby guide
// src/routes/__root.tsx
import { createRootRoute, Outlet } from '@tanstack/react-router'
import { FathomProvider } from 'react-fathom'
import { TanStackRouterFathomTrackView } from 'react-fathom/tanstack-router'
export const Route = createRootRoute({
component: () => (
<FathomProvider siteId="YOUR_SITE_ID" clientOptions={{ auto: false }}>
<TanStackRouterFathomTrackView />
<Outlet />
</FathomProvider>
),
})π Full TanStack Router guide
import {
useFathom,
useTrackOnMount,
useTrackOnClick,
useTrackOnVisible,
} from 'react-fathom'
function MyComponent() {
const { trackEvent, trackGoal } = useFathom()
// Track on mount
useTrackOnMount({ url: '/custom-page' })
// Track clicks
const handleClick = useTrackOnClick({ eventName: 'cta-click', _value: 100 })
// Track visibility
const ref = useTrackOnVisible({ eventName: 'hero-viewed' })
return (
<>
<div ref={ref}>Hero section</div>
<button onClick={handleClick}>Get Started</button>
<button onClick={() => trackGoal('purchase', 2999)}>Buy Now</button>
</>
)
}π Hooks API reference
import { TrackPageview, TrackClick, TrackVisible } from 'react-fathom'
function MyPage() {
return (
<>
<TrackPageview url="/landing" />
<TrackVisible eventName="section-viewed">
<section>Tracks when visible</section>
</TrackVisible>
<TrackClick eventName="signup-click">
<button>Sign Up</button>
</TrackClick>
</>
)
}npm install react-native-webviewimport { NativeFathomProvider } from 'react-fathom/native'
function App() {
return (
<NativeFathomProvider siteId="YOUR_SITE_ID" debug={__DEV__} trackAppState>
<YourApp />
</NativeFathomProvider>
)
}Enable debug mode to log tracking calls and subscribe to events for custom UI:
// Console logging during development
<FathomProvider siteId="YOUR_SITE_ID" debug={{ enabled: true }}>
// Subscribe to events programmatically
import { useDebugSubscription } from 'react-fathom'
function DebugPanel() {
const { events, debugEnabled, clearEvents } = useDebugSubscription({
maxEvents: 20,
onEvent: (event) => console.log('Tracked:', event)
})
if (!debugEnabled) return null
return (
<div>
{events.map(e => <div key={e.id}>{e.type}: {e.eventName || e.url}</div>)}
</div>
)
}Debug mode does not block actual trackingβevents are still sent to Fathom.
| Component | Use case |
|---|---|
FathomProvider |
Basic React apps |
NextFathomProviderApp |
Next.js App Router |
NextFathomTrackViewPages |
Next.js Pages Router (add inside FathomProvider) |
ReactRouterFathomTrackView |
React Router v6+ / Remix (add inside FathomProvider) |
GatsbyFathomTrackView |
Gatsby (add inside FathomProvider) |
TanStackRouterFathomTrackView |
TanStack Router (add inside FathomProvider) |
NativeFathomProvider |
React Native |
| Hook | Description |
|---|---|
useFathom() |
Returns trackPageview, trackEvent, trackGoal, and more |
useTrackOnMount(opts?) |
Track pageview when component mounts |
useTrackOnClick(opts) |
Returns click handler that tracks event |
useTrackOnVisible(opts) |
Returns ref; tracks when element becomes visible |
useDebugSubscription(opts?) |
Subscribe to debug events for custom UI |
| Component | Description |
|---|---|
<TrackPageview> |
Track pageview on mount |
<TrackClick> |
Track event on click |
<TrackVisible> |
Track when visible (IntersectionObserver) |
π Full API Reference
Events not appearing?
- Verify site ID matches your Fathom dashboard
- Check for ad blockers (test in incognito)
- Add
{ includedDomains: ['localhost'] }toclientOptions
Duplicate pageviews?
// Disable fathom-client's auto tracking when using NextFathomTrackViewApp
<FathomProvider siteId="..." clientOptions={{ auto: false }}>π Full Troubleshooting Guide
- π Getting Started
- βοΈ React Guide
- π€οΈ React Router Guide
- π Gatsby Guide
- π§ TanStack Router Guide
- β‘ Next.js Guide
- π± React Native Guide
- π API Reference
- π§ Troubleshooting
- π€ Contributing
MIT Β© Ryan Hefner