Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Fathom Dashboard Widget Laravel Package

devlogx/filament-fathom-dashboard-widget

A Filament widget that brings Fathom analytics into your admin dashboard, showing key traffic stats and site metrics at a glance. Drop it into any panel to give your team quick visibility into visits, pageviews, and referrers without leaving the app.

View on GitHub
Deep Wiki
Context7

Getting Started

devlogx/filament-fathom-dashboard-widget is a Filament dashboard widget that pulls stats from the Fathom Analytics API and renders them alongside your other Filament widgets. 1.0.0 is the first tagged release — treat it as the API baseline, not as a delta from anything.

Minimum path to a working widget:

  1. Install into an app that already has Filament set up:
    composer require devlogx/filament-fathom-dashboard-widget
    
  2. Publish the config (the tag name is the usual Filament convention — confirm with php artisan vendor:publish and pick the package's entry if the tag differs):
    php artisan vendor:publish --tag="filament-fathom-dashboard-widget-config"
    
  3. Get credentials from Fathom: Settings → API for the key, and the numeric Site ID from the site's settings page (not the domain name).
  4. Add the env vars and clear config cache:
    FATHOM_API_KEY=xxxxxxxxxxxxxxxx
    FATHOM_SITE_ID=123456789
    
    php artisan config:clear
    
  5. Register the widget in your panel provider:
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->widgets([
                \Devlogx\FilamentFathomDashboardWidget\Widgets\FathomDashboardWidget::class,
            ]);
    }
    
  6. Load /admin and look at the dashboard.

Where to look first: the published config file. It tells you which env keys the package actually reads, the default cache TTL, and whether the API base URL is overridable — that one file answers 80% of the questions you'll have on day one.

First real use case: replace the vague "traffic is fine" feeling with a number on the dashboard your content team already looks at. A pageviews/visitors/uniques tile for the last 7 and 30 days covers most of what people want before they open Fathom itself.

Implementation Patterns

Register per panel, not globally. Filament widgets are panel-scoped. If you run ->discoverWidgets(), verify the package widget is actually discovered — packages often ship widgets outside the panel's default discovery path, in which case explicit registration is required.

One widget instance per site. The most common real pattern for agencies: several sites, one dashboard. Subclass the widget and hard-code or inject the site ID:

class ClientAStatsWidget extends FathomDashboardWidget
{
    protected static ?string $heading = 'Client A — last 30 days';

    protected function getSiteId(): string
    {
        return config('services.fathom.sites.client_a');
    }
}

Whether getSiteId() exists as an overridable method depends on the 1.0.0 internals — check the class before relying on it; setting the site via the config key per-widget or via a constructor property is the fallback.

Tenancy / multi-tenant panels. Resolve the site ID from Filament::getTenant() rather than config, so each tenant sees only their own traffic. Pair this with a canView() override so a tenant can't render a widget bound to another tenant's site ID.

Cache deliberately. The dashboard is the highest-traffic page in most admin panels and every widget render is an API call. Set the TTL in config to match your tolerance for staleness — 5–15 minutes is normal; 60 seconds will burn through Fathom's rate limit on a busy team. If the widget supports Filament's pollingInterval, use minutes, not seconds.

Pair with Filament's own stats. Keep the package widget for Fathom-specific numbers (pageviews, uniques, avg. duration, bounce rate) and use StatsOverviewWidget for anything you already have in the database. Mixing sources in one widget makes the "why don't these numbers match" conversation worse.

Test with Http::fake(). The widget is just an HTTP client under the hood. Fake the Fathom aggregation endpoint to assert your widget renders a given payload, and to assert it degrades gracefully on a 401/429:

Http::fake([
    'api.usefathom.com/*' => Http::response(['data' => [/* ... */]]),
]);

Custom rendering. If the package ships publishable views (vendor:publish --tag=...-views), publish them rather than editing vendor files — you'll want the layout to match your panel's other widgets anyway.

Gotchas and Tips

  • The API key is account-wide, the site ID is per-site. A valid key with the wrong site ID returns an empty result set, not an error. If the widget renders zeros, check the site ID before you check anything else — grab it from the Fathom URL when you're viewing that site's dashboard.
  • Empty response vs. failure look identical. A 403, an expired key, a rate-limited request, and a genuinely quiet week can all render as a blank tile. Wrap the API call in a try/catch, log the exception, and show an explicit "unable to load analytics" state. Do this during integration, not after the first incident.
  • Local dev will 401 or hang. Either put a real key in .env on your machine or short-circuit the widget in local (return early from canView()), otherwise every dashboard load makes a live outbound call and slows down your test suite.
  • php artisan config:cache in deploy scripts will freeze whatever env values existed at build time. If the widget shows stale or missing data immediately after a deploy, this is almost always why.
  • Timezone mismatch. Fathom aggregates by the site's configured timezone; Filament's charts and your APP_TIMEZONE may not agree. "Today" can differ by a day at the edges. Settle on one — usually set the Fathom site to UTC and label the widget period explicitly ("last 30 days", not "this month").
  • Self-hosted Fathom uses a different host (https://fathom.yourdomain.com). Check whether 1.0.0's config exposes a base URL override; if not, that's a hard blocker and worth a PR upstream.
  • Rate limits are real. Fathom throttles per-key. One dashboard refresh with three instances of the widget is three calls; add polling and it multiplies. Cache is not optional at any real team size.
  • Filament v3 vs v4. 1.0.0's composer.json constraints tell you which Filament versions are supported. If you're on v4 and the package only allows ^3.0, don't force it — widget APIs changed around lazy loading and the HasWidgets registration path.
  • Authorization. Override canView() to gate on a permission or role. Analytics data is business-sensitive; it shouldn't be visible to every user who can reach /admin.
  • Debugging checklist, in order: config('...fathom.api_key') is non-null → the site ID matches the Fathom URL → a manual curl against api.usefathom.com/v1/aggregations with the same key returns data → the widget's cache key has been cleared (php artisan cache:clear) → storage/logs/laravel.log for the caught exception.
  • Extension points to lean on: the published config (TTL, base URL, env key names), the widget class itself (subclass for headings, site IDs, canView(), column selection), and the published Blade view for layout. If the site ID and time range are only settable via config in 1.0.0, subclassing plus a per-instance property is the cleanest way to get multiple sites on one dashboard without forking.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo