liberusoftware/analytics-google-api
A Laravel package for integrating Google Analytics APIs into your PHP applications, providing a convenient wrapper to query analytics data and connect your app to Google's reporting services with minimal setup.
Minimal install:
composer require liberusoftware/analytics-google-api
Then confirm what the package actually ships before writing application code. There is no dependents signal and the repository is effectively undocumented at the registry level, so the first 10 minutes should be source inspection:
composer.json — check extra.laravel.providers / aliases for auto-discovery, and the exact namespace.src/ — find the adapter/presenter class and any contracts. The description says “presentation adapter”, so expect a class that maps Google Analytics API responses into view-friendly structures rather than a full analytics SDK.config/ — publish it (tag name is package-specific; try php artisan vendor:publish --provider="Liberu\AnalyticsGoogleApi\...ServiceProvider").README / tests/ — the tests are the best usage documentation for an unstarred package.Typical setup:
php artisan vendor:publish --tag=analytics-google-api-config
// config/analytics-google-api.php (illustrative — confirm keys in src/config)
return [
'credentials' => env('GOOGLE_APPLICATION_CREDENTIALS'),
'property_id' => env('GA4_PROPERTY_ID'), // "properties/123456789"
'cache_ttl' => 300,
];
Put the service-account JSON outside the repo and point GOOGLE_APPLICATION_CREDENTIALS at it. Share the GA4 property with the service-account email in the Google Analytics admin UI.
First use case — a dashboard card showing the last 28 days:
use Liberu\AnalyticsGoogleApi\...; // confirm exact class in src/
$adapter = app(/* adapter class */::class);
$report = $adapter
->property(config('analytics-google-api.property_id'))
->dateRange(now()->subDays(28), now())
->metrics(['sessions', 'totalUsers', 'screenPageViews'])
->dimensions(['date'])
->get();
return view('dashboard.analytics', ['report' => $report]);
If the package exposes a facade or a Presentable/Adapter contract, resolve that instead of the concrete class — that is the seam you will want later.
Wrap it, don’t sprinkle it. The package is a presentation adapter, not an application service. Put it behind your own AnalyticsService or repository so controllers and Blade templates never see Google-specific arrays:
final class AnalyticsService
{
public function __construct(private /* adapter */ $adapter) {}
public function trafficSummary(int $days = 28): TrafficSummary
{
$rows = $this->adapter
->dateRange(now()->subDays($days), now())
->metrics(['sessions', 'totalUsers'])
->get();
return TrafficSummary::fromRows($rows);
}
}
Always cache. Google Analytics calls are slow, quota-bound, and almost never need to be real-time. Cache the normalized DTO, not the raw response:
$summary = Cache::remember(
"analytics:traffic:{$propertyId}:28d",
now()->addMinutes(15),
fn () => $this->service->trafficSummary(28)
);
Present in one place. If the package provides its own presenter/view model, use it for the dashboard and keep raw report handling in the service. If it only returns arrays, build your own TrafficSummary DTO with fromRows() and let Blade consume that.
Multi-property / multi-tenant. Instantiate or configure the adapter per tenant rather than relying on a single global config value. A small factory is cleaner than mutating config at runtime:
final class AnalyticsFactory
{
public function forProperty(string $propertyId): /* adapter */
{
return app(/* adapter */::class, ['propertyId' => $propertyId]);
}
}
Move heavy reports to jobs. Anything spanning >90 days or multiple dimensions belongs in a queued job or scheduled command that writes to a local table or cache key. Dashboards should read your data, not Google’s, on every page load.
Scheduling:
$schedule->call(fn () => app(AnalyticsService::class)->refreshDaily())
->dailyAt('06:00')
->withoutOverlapping();
Testing. Bind a fake implementation of the adapter contract in your test case:
$this->app->bind(/* adapter contract */::class, FakeAnalyticsAdapter::class);
If there is no contract, add one in your app and bind the package class to it — this is the single most valuable thing you can do with an unknown package.
Blade integration. Prefer a component that takes a DTO:
<x-analytics.traffic-card :summary="$summary" />
Avoid calling the adapter directly from a Blade template; it makes caching and error handling much harder to reason about.
NOASSERTION. Treat this as unresolved for commercial use until you read LICENSE in the repo. Get a legal check before shipping it in a client project.composer require liberusoftware/analytics-google-api:^x.y) and read the source before upgrading. The release date metadata (2026-10-26) looks anomalous — verify the actual tag in the repo.bootstrap/providers.php. Also check whether the config tag differs from the package name.properties/123456789, not the old UA-XXXXX view ID. Most “it returns empty” bugs are a property-ID mismatch or the service account not being granted Viewer access on the property.PERMISSION_DENIED) for bad credentials and 429 (RESOURCE_EXHAUSTED) for quota pressure. Do not retry 403s. Wrap calls in try/catch, log the Google error payload, and fall back to cached data so the dashboard degrades gracefully.GOOGLE_APPLICATION_CREDENTIALS or a secret manager, and ensure the path is readable by the web/queue user. Clear config cache after changing env values: php artisan config:clear.Europe/London, the last bucket will drift. Pass explicit DateTimeInterface objects rather than strings.vendor/.Log::debug() the request parameters and the raw response before normalization. Confirm the underlying Google client works independently with a one-line call in php artisan tinker; that separates “package broken” from “credentials broken” quickly.src/ and the service provider’s register()/boot() methods.How can I help you explore Laravel packages today?