Fathom Analytics Event Tracking
Overview
Fathom Analytics is a privacy-first analytics platform designed to provide simple, fast, and ethical website analytics. With a script size under 2KB, Fathom focuses on essential metrics while maintaining complete GDPR, CCPA, and PECR compliance. No cookies, no personal data collection, and no invasive tracking.
Event tracking in Fathom is straightforward and powerful. Using the fathom.trackGoal() function, you can track custom events, conversions, and revenue without complex setup. Fathom is ideal for businesses that want actionable insights without compromising user privacy or site performance.
Event Model
How Fathom Events Work
Fathom uses a goal-based event model:
- Create a Goal in your Fathom dashboard (one-time setup)
- Get the Goal ID (an 8-character code like
ABCD1234) - Track the Goal using
fathom.trackGoal()
Basic Event Structure:
fathom.trackGoal('ABCD1234', 0);
Event with Revenue:
fathom.trackGoal('ABCD1234', 2999); // $29.99 in cents
Key Characteristics
- Lightweight and fast (under 2KB script)
- No cookies required
- No personal data collected
- Goal-based tracking system
- Revenue tracking built-in
- Events tied to pageviews in session
Limits
- Goal ID: 8 characters (automatically generated)
- Events: Unlimited (billed by monthly pageviews)
- Revenue: Integer values in cents (no decimal points)
- Concurrent Goals: Unlimited goals per site
Standard Events
Fathom automatically tracks pageviews. Additional tracking is goal-based and manual.
Automatic Pageview Tracking
<!-- Include the script - pageviews tracked automatically -->
<script src="https://cdn.usefathom.com/script.js" data-site="ABCDEFGH" defer></script>
Automatic pageviews include:
- Page URL
- Referrer source
- Device type (desktop, mobile, tablet)
- Browser
- Operating system
- Country (no city/precise location)
Single Page Applications (SPAs)
For SPAs, manually trigger pageviews on route changes:
// Track virtual pageview
fathom.trackPageview();
// Track with custom path
fathom.trackPageview({
url: '/virtual-page',
referrer: '/previous-page'
});
React Example:
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
function App() {
const location = useLocation();
useEffect(() => {
if (window.fathom) {
window.fathom.trackPageview();
}
}, [location]);
return <div>...</div>;
}
Vue.js Example:
// In your router configuration
router.afterEach((to, from) => {
if (window.fathom) {
window.fathom.trackPageview();
}
});
Custom Events (Goals)
Custom events in Fathom are called "Goals." Each goal must be created in the dashboard first.
Creating Goals in the Dashboard
- Log into Fathom Analytics
- Navigate to Settings > Goals
- Click Create Goal
- Enter a goal name (e.g., "Newsletter Signup")
- Copy the generated Goal ID (e.g.,
ABCD1234)
Basic Goal Tracking
// Simple goal tracking
fathom.trackGoal('ABCD1234', 0);
// Button click
fathom.trackGoal('SIGNUP01', 0);
// Form submission
fathom.trackGoal('CONTACT1', 0);
Goal Tracking with Revenue
Track monetary value with goals:
// Revenue in cents (integer only)
fathom.trackGoal('PURCHASE', 2999); // $29.99
// Large purchase
fathom.trackGoal('PURCHASE', 149900); // $1,499.00
// Subscription
fathom.trackGoal('SUBSCRIBE', 4900); // $49.00
Important: Revenue must be in cents as an integer, not dollars with decimals.
Implementation Examples
Button Clicks:
<button onclick="fathom.trackGoal('SIGNUP01', 0)">
Sign Up Free
</button>
Form Submissions:
document.getElementById('contact-form').addEventListener('submit', function(e) {
fathom.trackGoal('CONTACT1', 0);
// Form continues to submit...
});
Link Clicks:
<a href="/download.pdf" onclick="fathom.trackGoal('DOWNLOAD', 0)">
Download Guide
</a>
Feature Usage:
function enableDarkMode() {
// Enable dark mode logic...
fathom.trackGoal('DARKMODE', 0);
}
Goal Naming Best Practices
Good Goal Names:
- "Newsletter Signup" (clear and descriptive)
- "Purchase Complete" (specific action)
- "Trial Started" (clear event)
- "Contact Form Submit" (descriptive)
Avoid:
- "Goal 1" (not descriptive)
- "event_test_123" (unclear purpose)
- Very long names that get truncated in reports
Ecommerce Events
Fathom supports ecommerce tracking through goals with revenue values.
Product Browsing
// Product page view (pageview tracked automatically)
// Use goals for specific interactions
// Add to cart
fathom.trackGoal('ADDCART1', 0);
// Remove from cart
fathom.trackGoal('REMCART1', 0);
Checkout Process
// Checkout initiated
fathom.trackGoal('CHECKOUT', 0);
// Payment info entered
fathom.trackGoal('PAYMENT1', 0);
// Purchase completed
fathom.trackGoal('PURCHASE', 9999); // $99.99 in cents
Complete Purchase Example
// After successful payment
function handlePurchaseComplete(orderTotal) {
// Convert dollars to cents
const cents = Math.round(orderTotal * 100);
// Track purchase with revenue
fathom.trackGoal('PURCHASE', cents);
}
// Usage
handlePurchaseComplete(149.99); // Tracks $149.99
Subscription Events
// Trial started
fathom.trackGoal('TRIAL123', 0);
// Trial converted to paid
fathom.trackGoal('TRIALCV1', 2999); // $29.99/month
// Subscription upgraded
fathom.trackGoal('UPGRADE1', 4999); // $49.99/month
// Subscription cancelled
fathom.trackGoal('CANCEL01', 0);
Refunds
For refunds, track as a separate goal:
// Refund processed
fathom.trackGoal('REFUND01', 0);
// Note: Fathom doesn't support negative revenue values
// Track refunds as count-based goals for reporting
Revenue Tracking
Fathom's revenue tracking is simple but powerful.
Revenue Format
Correct Format (Cents as Integer):
fathom.trackGoal('PURCHASE', 2999); // $29.99
fathom.trackGoal('PURCHASE', 100); // $1.00
fathom.trackGoal('PURCHASE', 149900); // $1,499.00
Incorrect Format (Will Fail):
fathom.trackGoal('PURCHASE', 29.99); // ❌ Decimals not supported
fathom.trackGoal('PURCHASE', '2999'); // ❌ Strings not supported
fathom.trackGoal('PURCHASE', -500); // ❌ Negative values not supported
Converting Dollars to Cents
// Helper function
function dollarsToCents(dollars) {
return Math.round(dollars * 100);
}
// Usage
const orderTotal = 149.99;
fathom.trackGoal('PURCHASE', dollarsToCents(orderTotal));
Multiple Currency Support
Fathom stores revenue values as integers. For multiple currencies:
// Option 1: Create separate goals per currency
fathom.trackGoal('PURCHUS1', 2999); // USD purchases
fathom.trackGoal('PURCHEU1', 2499); // EUR purchases
fathom.trackGoal('PURCHGB1', 2199); // GBP purchases
// Option 2: Convert to single currency before tracking
function trackPurchase(amount, currency) {
const exchangeRates = {
'USD': 1.00,
'EUR': 1.10,
'GBP': 1.27
};
const usdAmount = amount * exchangeRates[currency];
const cents = Math.round(usdAmount * 100);
fathom.trackGoal('PURCHASE', cents);
}
Viewing Revenue Reports
- Log into Fathom dashboard
- Select your site
- Click on the goal with revenue tracking
- View:
- Total conversions
- Total revenue
- Average order value
- Revenue over time
Implementation Methods
1. Direct Script Embed (Recommended)
Basic Installation:
<!-- Add to <head> -->
<script src="https://cdn.usefathom.com/script.js" data-site="ABCDEFGH" defer></script>
With Custom Domain (Bypass Ad Blockers):
<!-- Using your own subdomain -->
<script src="https://stats.yourdomain.com/script.js" data-site="ABCDEFGH" defer></script>
With Excluded Domains:
<!-- Don't track on localhost or staging -->
<script src="https://cdn.usefathom.com/script.js"
data-site="ABCDEFGH"
data-excluded-domains="localhost,staging.yourdomain.com"
defer></script>
2. Manual Event Tracking in Code
Vanilla JavaScript:
// Wait for Fathom to load
window.addEventListener('load', function() {
if (window.fathom) {
// Track goal
fathom.trackGoal('SIGNUP01', 0);
}
});
// Or check if loaded
if (typeof fathom !== 'undefined') {
fathom.trackGoal('SIGNUP01', 0);
}
React Component:
import { useEffect } from 'react';
function SignupButton() {
const handleSignup = async () => {
try {
// Perform signup logic...
// Track successful signup
if (window.fathom) {
window.fathom.trackGoal('SIGNUP01', 0);
}
} catch (error) {
console.error('Signup failed:', error);
}
};
return (
<button onClick={handleSignup}>
Sign Up Free
</button>
);
}
Vue.js Component:
<template>
<button @click="handleDownload">Download Guide</button>
</template>
<script>
export default {
methods: {
handleDownload() {
// Track download
if (window.fathom) {
window.fathom.trackGoal('DOWNLOAD', 0);
}
// Trigger download...
window.location.href = '/guide.pdf';
}
}
}
</script>
3. Google Tag Manager
Setup:
Base Script Tag:
<script>
(function() {
var script = document.createElement('script');
script.src = 'https://cdn.usefathom.com/script.js';
script.setAttribute('data-site', 'ABCDEFGH');
script.defer = true;
document.head.appendChild(script);
})();
</script>
Event Tracking Tag:
<script>
window.fathom = window.fathom || function() {
(window.fathom.q = window.fathom.q || []).push(arguments)
};
fathom('trackGoal', '{{Goal ID}}', {{Revenue}});
</script>
4. WordPress Integration
Using a Plugin:
- Install "Fathom Analytics" plugin
- Enter your Site ID
- Goals are tracked manually in your theme
Manual Theme Integration:
<!-- Add to header.php before </head> -->
<script src="https://cdn.usefathom.com/script.js" data-site="ABCDEFGH" defer></script>
<!-- Track goal in your template -->
<button onclick="fathom.trackGoal('SIGNUP01', 0)">Sign Up</button>
Debugging & Validation
1. Browser Console
// Check if Fathom is loaded
console.log(typeof fathom); // Should output "function"
// Test goal tracking
fathom.trackGoal('TEST1234', 0);
console.log('Goal tracked');
2. Network Tab Inspection
DevTools Network Tab:
Filter: fathom
Look for: POST requests to cdn.usefathom.com/api/event
Status: 200 OK (successful)
Request Payload Example:
{
"site": "ABCDEFGH",
"goal": "ABCD1234",
"value": 0
}
3. Fathom Dashboard
Real-Time Validation:
- Log into Fathom dashboard
- Select your site
- Click "Current visitors" (top right)
- Perform action on your site
- See goal appear in real-time (refresh if needed)
Goal Reports:
- Navigate to your site dashboard
- Scroll to "Goals" section
- Click on specific goal to view details
- Verify conversions and revenue
4. Test Mode
Use excluded domains for testing:
<!-- Don't track localhost events in production -->
<script src="https://cdn.usefathom.com/script.js"
data-site="ABCDEFGH"
data-excluded-domains="localhost"
defer></script>
Or create a separate test site in Fathom for staging environments.
Best Practices
Goal Creation
Do:
- Create descriptive goal names
- Organize goals by category (Signups, Purchases, Downloads)
- Document goal IDs in your codebase
- Delete unused goals to keep dashboard clean
Don't:
- Create duplicate goals for the same action
- Use generic names like "Goal 1"
- Create goals without tracking them
Revenue Tracking
Do:
// Always convert to cents
const cents = Math.round(orderTotal * 100);
fathom.trackGoal('PURCHASE', cents);
// Handle edge cases
const safeCents = isNaN(cents) ? 0 : cents;
fathom.trackGoal('PURCHASE', safeCents);
Don't:
// Don't pass decimals
fathom.trackGoal('PURCHASE', 29.99); // ❌ Will fail
// Don't pass strings
fathom.trackGoal('PURCHASE', '2999'); // ❌ Will fail
// Don't pass negative values
fathom.trackGoal('PURCHASE', -500); // ❌ Not supported
Privacy & Compliance
Already compliant by default:
- No cookies used
- No personal data collected
- No cross-site tracking
- IP addresses anonymized
- GDPR/CCPA/PECR compliant out-of-the-box
Additional privacy:
<!-- Exclude tracking on sensitive pages -->
<script src="https://cdn.usefathom.com/script.js"
data-site="ABCDEFGH"
data-excluded-domains="admin.yourdomain.com"
defer></script>
Performance
Lightweight by design:
- Script size: under 2KB
- Loads asynchronously with
defer - Doesn't block page rendering
- Minimal performance impact
Optimization:
<!-- Use defer attribute (recommended) -->
<script src="https://cdn.usefathom.com/script.js" data-site="ABCDEFGH" defer></script>
<!-- Use custom domain for faster loads and ad blocker bypass -->
<script src="https://stats.yourdomain.com/script.js" data-site="ABCDEFGH" defer></script>
Error Handling
// Graceful error handling
function trackGoalSafely(goalId, value = 0) {
try {
if (window.fathom && typeof window.fathom.trackGoal === 'function') {
window.fathom.trackGoal(goalId, value);
} else {
console.warn('Fathom not loaded');
}
} catch (error) {
console.error('Goal tracking failed:', error);
}
}
// Usage
trackGoalSafely('SIGNUP01', 0);
Code Organization
Centralize goal tracking:
// analytics.js
export const Goals = {
SIGNUP: 'SIGNUP01',
PURCHASE: 'PURCHASE',
TRIAL: 'TRIAL123',
DOWNLOAD: 'DOWNLOAD'
};
export function trackGoal(goalId, value = 0) {
if (window.fathom) {
window.fathom.trackGoal(goalId, value);
}
}
// Usage in components
import { Goals, trackGoal } from './analytics';
trackGoal(Goals.SIGNUP, 0);
Testing Strategy
- Development: Use excluded domains or separate test site
- Staging: Create staging site in Fathom
- Production: Monitor goals in real-time after deployment
- Validation: Check network requests and dashboard
- Documentation: Maintain goal ID reference document
Additional Resources: