A Laravel package that provides Alpine.js directives and magic helpers for seamless Fathom Analytics event tracking in Blade templates and Livewire components.
- 🎯 Alpine.js Directives - Simple HTML attributes for tracking clicks, form submissions, downloads, and external links
- ✨ Magic Helper -
$fathommagic helper for programmatic tracking in JS - 🔥 Livewire Integration - dispatch tracking events from Livewire components
- 📊 Track E-commerce Values - Track conversions with values in cents
- Laravel 10+
- PHP 8.2+
- Alpine.js 3.x
- Livewire 3.x
- Fathom Analytics account with script included in your site
composer require kerkness/fa-wiredIf you're using Vite, or another build tool:
// In your app.js or main JavaScript file
import 'vendor/kerkness/fa-wired/dist/fa-wired.esm.js';
// Or with explicit import
import FaWired from 'vendor/kerkness/fa-wired/dist/fa-wired.esm.js';<!-- Your existing scripts -->
<script src="https://cdn.usefathom.com/script.js" data-site="YOUR-SITE-ID" defer></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<!-- fa-wired from vendor directory -->
<script src="{{ asset('vendor/kerkness/fa-wired/dist/fa-wired.js') }}"></script><script src="https://cdn.jsdelivr.net/gh/kerkness/fa-wired@latest/dist/fa-wired.js"></script>If you want to customize or host the JavaScript yourself:
php artisan vendor:publish --provider="Kerkness\FaWired\FaWiredServiceProvider" --tag="fa-wired-assets"This will copy the compiled JavaScript files to public/vendor/fa-wired/.
<button x-track-click="header cta">Get Started</button><form x-track-submit="newsletter signup">
<input type="email" placeholder="Enter email">
<button type="submit">Subscribe</button>
</form>// In your Livewire component
public function submit()
{
// Process form...
$this->dispatch('fathom-track', name: 'contact form submitted');
}<button x-track-click="button click">
Track Simple Click
</button><button x-track-click="{ event: 'premium button', value: 2500 }">
Track Click with Value ($25.00)
</button><form x-track-submit="newsletter signup">
<input type="email" placeholder="Enter email">
<button type="submit">Subscribe</button>
</form><!-- Auto-named download event -->
<a href="/files/guide.pdf" x-track-download>
Download User Guide
</a>
<!-- Custom event name -->
<a href="/files/pricing.pdf" x-track-download="pricing guide download">
Download Pricing
</a><a href="https://example.com" x-track-external="partner site visit">
Visit Partner Site
</a><button @click="$fathom.track('magic helper test')">
Simple Track
</button><div x-data="{ productPrice: 4999 }">
<button @click="$fathom.conversion('product purchase', productPrice)">
Track Conversion ($49.99)
</button>
</div><div x-data="{
trackingData: { clicks: 0 },
trackComplexEvent() {
this.trackingData.clicks++;
$fathom.track('complex interaction', this.trackingData.clicks * 100);
}
}">
<button @click="trackComplexEvent()">
Complex Tracking
</button>
</div><?php
namespace App\Livewire;
use Livewire\Component;
class ContactForm extends Component
{
public function submit()
{
// Process form...
// Track simple event
$this->dispatch('fathom-track', name: 'contact form submitted');
// Track with value (e.g., for lead scoring)
$this->dispatch('fathom-track',
name: 'high value lead',
value: 5000 // $50.00 in cents
);
}
public function purchaseSubscription($planPrice)
{
// Process purchase...
// Track conversion
$this->dispatch('fathom-conversion',
name: 'subscription purchased',
value: $planPrice * 100 // Convert to cents
);
}
public function registerUser()
{
// Process registration...
// Track form submission
$this->dispatch('fathom-form-submit', name: 'user registration');
}
}<button x-track-click="product view: {{ $product->name }}">
View {{ $product->name }}
</button>@if($user->isPremium())
<button x-track-click="{ event: 'premium feature used', value: 1000 }">
Premium Feature
</button>
@else
<button x-track-click="upgrade prompt shown">
Upgrade to Premium
</button>
@endif<div x-data="{
cart: { total: 0, items: [] },
addToCart(product, price) {
this.cart.items.push(product);
this.cart.total += price;
$fathom.track('add to cart: ' + product, price);
},
checkout() {
$fathom.conversion('checkout completed', this.cart.total);
}
}">
<p>Cart Total: $<span x-text="(cart.total / 100).toFixed(2)"></span></p>
<button @click="addToCart('Widget A', 1999)">
Add Widget A ($19.99)
</button>
<button @click="addToCart('Widget B', 2999)">
Add Widget B ($29.99)
</button>
<button @click="checkout()" x-show="cart.total > 0">
Checkout
</button>
</div>Alpine.store('fathom').track(eventName, value)
Alpine.store('fathom').click(eventName, value)
Alpine.store('fathom').submit(eventName, value)
Alpine.store('fathom').conversion(eventName, value)
Alpine.store('fathom').download(fileName, eventName)
Alpine.store('fathom').externalLink(url, eventName)$fathom.track(eventName, value)
$fathom.click(eventName, value)
$fathom.submit(eventName, value)
$fathom.conversion(eventName, value)
$fathom.download(fileName, eventName)
$fathom.externalLink(url, eventName)$this->dispatch('fathom-track', name: 'event name', value: 1000);
$this->dispatch('fathom-form-submit', name: 'event name', value: 1000);
$this->dispatch('fathom-conversion', name: 'event name', value: 1000);By default, auto-tracking is disabled. You can enable it like this:
// Enable auto-tracking for external links and downloads
FaWired.configure({
autoTrackExternalLinks: true,
autoTrackDownloads: true
});- Use descriptive, consistent names
- Avoid special characters and emojis
- Use lowercase with spaces or underscores
- Examples:
newsletter signup,product_purchase,file download
- Always provide values in cents (100 = $1.00)
- Use consistent currency across your site
- Set currency in Fathom dashboard settings
// User interactions
$fathom.track('button click: header cta');
$fathom.track('menu opened');
$fathom.track('search performed');
// Form submissions
$fathom.submit('contact form');
$fathom.submit('newsletter signup');
$fathom.submit('user registration');
// E-commerce
$fathom.conversion('product purchased', 2999);
$fathom.track('add to cart', 1999);
$fathom.track('checkout started');
// Content engagement
$fathom.track('video play');
$fathom.download('user-guide.pdf');
$fathom.externalLink('https://partner.com');- Events not tracking: Ensure Fathom script loads before fa-wired
- Console warnings: Check that
fathomobject exists globally - Livewire events not firing: Verify event names match exactly
Enable debug mode to see all tracking calls:
// Add this after fa-wired loads
Alpine.store('fathom').track = function(eventName, value = null) {
console.log('Tracking:', eventName, value); // Debug line
if (typeof fathom === 'undefined') {
console.warn('Fathom Analytics not loaded');
return;
}
const options = value ? { _value: value } : {};
fathom.trackEvent(eventName, options);
};Make sure scripts load in this order:
- Fathom Analytics script
- Alpine.js
- fa-wired
- Your custom scripts
The MIT License (MIT). Please see License File for more information.