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 Laravel Analytics Laravel Package

andreaselia/filament-laravel-analytics

Filament plugin that brings Laravel Analytics into your admin panel, letting you view Google Analytics data without leaving Filament. Adds analytics widgets and pages so you can display traffic, visitors, and other key metrics directly in your dashboard.

View on GitHub
Deep Wiki
Context7

Getting Started

This package renders Google Analytics (GA4) traffic widgets inside a Filament panel. It is a thin display layer over spatie/laravel-analytics, so the real setup work is on the Google side, not the Laravel side.

  1. Install it and check the transitive dependency.

    composer require andreaselia/filament-laravel-analytics
    

    Confirm spatie/laravel-analytics landed in composer.json. If the plugin pulled an old or oddly pinned version, require it explicitly so you control the upgrade path.

  2. Provision credentials before writing any panel code. This is where most of the time goes:

    • Create a Google Cloud service account, enable the Google Analytics Data API, download the JSON key.
    • Add the service-account email as a Viewer on the GA4 property (not just the Cloud project).
    • Note the numeric GA4 property ID (Admin → Property Settings). The old UA- tracking ID will not work.
  3. Publish and configure.

    php artisan vendor:publish --tag="filament-laravel-analytics-config"
    
    // config/analytics.php
    'property_id' => env('ANALYTICS_PROPERTY_ID'),
    'service_account_credentials_json' => storage_path('app/analytics/service-account-credentials.json'),
    'cache_lifetime_in_minutes' => 60 * 24,
    
  4. Register the plugin in the panel provider that should see analytics (check the README for the exact plugin class/namespace for your version — it changed across early releases):

    public function panel(Panel $panel): Panel
    {
        return $panel->plugin(FilamentLaravelAnalyticsPlugin::make());
    }
    
  5. Prove the Google pipe works before debugging Filament. In tinker or a test, call the underlying package directly:

    use Spatie\Analytics\Facades\Analytics;
    use Spatie\Analytics\Period;
    
    Analytics::fetchTotalVisitorsAndPageViews(Period::days(7));
    

    If that throws, the problem is credentials/permissions and no amount of widget debugging will help.

First use case: a stakeholder-facing "Traffic" page on the dashboard — visitors and page views for the last 30 days plus a top-pages list. That single page is most of the day-to-day value; build it first and treat everything else as additive.

Implementation Patterns

Panel-scoped, one property per panel. Register the plugin only on the panel that should show analytics. In multi-panel or multi-tenant apps, don't make the property ID dynamic on the fly — register the plugin conditionally per panel and keep the property in config/env. Per-tenant properties get painful fast because the service account must be a Viewer on every property.

Use the bundled filters before writing code. v1.1.0 added filtering (e.g. date-range selection) and merged the views into a single Blade file. For a standard "traffic overview," the built-in filters are usually enough. Practical consequences:

  • Each filter state is a distinct query, so cache keys fan out. Keep cache_lifetime_in_minutes meaningful (a day or so) and use a shared cache store if you run more than one web node.
  • GA4 has a data-freshness lag (~24–48h on standard properties). Don't build a "today so far" view on top of the filters and then be surprised it looks stale — set expectations in UI copy.
  • Filter selections are per-request UI state; don't assume they persist across visits.

Split the "canned page" from custom charts. Use the plugin for the standard page; for anything bespoke (funnels, conversion widgets, per-post page views) write your own Filament widget that calls spatie/laravel-analytics directly. Mixing both is the pragmatic choice: you get the free page and full control where it matters, without forking vendor code.

Cache deliberately — quota is the real constraint.

// config/analytics.php
'cache' => [
    'store' => env('ANALYTICS_CACHE_STORE', 'redis'),
],

GA4 quota errors are the most common production incident with this stack. A shared, persistent store is the cheapest insurance: array in tests, redis/database in production, never file on a multi-node deploy.

Keep analytics out of local and non-production environments. Analytics calls in local either fail (no credentials) or burn quota. Gate registration:

->plugin(FilamentLaravelAnalyticsPlugin::make())
// ...
->when(fn () => app()->isProduction(), ...)

and hide the page from non-admins via a policy, gate, or canAccessPanel.

Authorization is on you. The plugin exposes navigation/page config, but access control is not implicit. Define a gate (e.g. Gate::define('viewAnalytics', ...)) and guard the page/widget so analytics isn't visible to every panel user by default.

Treat it as a read-only convenience layer. For anything requiring first-party event data — funnels, cohorts, retention — this package is the wrong tool; a dedicated product-analytics platform belongs there. Keep the boundary explicit so nobody tries to force it into a reporting system of record.

Gotchas and Tips

  • The 403 that isn't a bug. User does not have sufficient permissions for this property almost always means the service-account email wasn't added as a Viewer on the GA4 property, or you're using a UA- property ID instead of the numeric GA4 ID.
  • SERVICE_DISABLED means the API isn't enabled. A 403 PERMISSION_DENIED containing that string means the Analytics Data API wasn't turned on in the Cloud project. Easy to miss because the credentials JSON is otherwise valid.
  • Resolve credential paths absolutely. storage_path(...) is safest. Relative paths resolve from the working directory and break under queue workers, Octane, or a different deploy root.
  • v1.1.0 consolidated the Blade views — a real upgrade hazard if you published them. Earlier versions shipped multiple partials; this release merges them into one file. If you overrode individual blades, re-publish with --force, diff, and re-apply customizations, or your overrides will silently stop being used.
  • Cache confusion during development. Set ANALYTICS_CACHE_STORE=array or clear the analytics cache while iterating, otherwise you'll chase phantom "my change didn't apply" bugs caused by a 24-hour cached response.
  • Timezone drift. The app timezone and the GA4 property timezone can differ, so "yesterday" totals won't match the GA UI. Set the property timezone deliberately and document it.
  • Debug outside Filament. When things get flaky, reproduce with Analytics::fetchTopPages(...) in tinker or a test and log the exception. Filament's error surface hides the underlying Google client message, which is where the actionable detail lives.
  • Prefer your own widgets over editing vendor views. The view consolidation in v1.1.0 shows how quickly internal Blade structure moves. Publishing config and views is the supported customization path; fork only as a last resort.
  • Pin the version and read changelogs. This is a small, single-maintainer package with a thin release cadence. Pin it in composer.json, treat view overrides as something to re-check on every bump, and budget for vendoring or forking if it becomes load-bearing.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package