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

Ga4 Analytics Data Bundle Laravel Package

freema/ga4-analytics-data-bundle

Symfony bundle for pulling Google Analytics 4 Data API reports into your PHP application. It wraps GA4 credentials and reporting queries in configurable services, making it easier to fetch metrics and dimensions without boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

  • composer require freema/analytics-data-bundle:^1.1.2. There is no Flex recipe — the README used to promise one and the recipe endpoint was removed from composer.json in this release, so register the bundle manually (Symfony bundles.php) or, in a Laravel app, bind the client/config in a service provider and resolve it from the container.
  • Requirements: PHP 8.1–8.5, Symfony 5.4 / 6.4 / 7.4, current Guzzle 7.x. The old choose_handler() fallback is gone, so don't pin an ancient Guzzle.
  • First thing to read is the client config: one entry per GA4 property (property ID + service-account JSON path), plus the cache pool, cache.prefix, and lifetime. Credentials are a Google Cloud service account that must additionally be granted Viewer on the GA4 property itself.
  • First use case: pull a period report (sessions / active users / conversions) for a property into a dashboard, cached for the day. Second: isTransactionInAnalytics($transactionId) for order reconciliation in a scheduled command.

Implementation Patterns

  • One client per property. Define a named client for each GA4 property rather than swapping property IDs on a shared client. Since 1.1.2 the cache keys are scoped to the client's property and honour cache.prefix, so two properties can no longer read each other's numbers. In Laravel, expose each as a singleton/contextual binding (analytics.marketing, analytics.shop).
  • Segregate environments with the prefix. cache.prefix was silently ignored before this release; set it per environment (e.g. analytics_staging) so staging reports can't warm production keys, and so a shared Redis store stays readable.
  • Dashboard caching. A 24h TTL is fine for daily aggregates; wrap the call in your own repository/service so you can warm the cache in a scheduled command right after deploy (see Gotchas).
  • Transaction reconciliation. A scheduled job (->hourly() / ->everyFifteenMinutes()) checking recent orders. Because a failed check is no longer cached as false, a transient API error retries properly on the next run — but that also means your polling now costs real API calls; add your own short-TTL negative cache if you check the same order in a tight loop.
  • Cache invalidation. AnalyticsCache::clear() is now scoped to a single client's entries — safe (and intended) to wire to an admin "refresh data" button. It no longer flushes the app's whole cache.app pool, so don't rely on it as a general-purpose flush.
  • Testing. The package no longer ships its tests/tooling, so stub at your boundary: fake the cache store (Cache::fake() / array store), and mock the analytics client interface or the HTTP layer rather than hitting GA4. Assert on the cache keys being property-scoped if you have multi-tenant reporting.

Gotchas and Tips

  • Upgrading is code-free but not cache-free. Old entries are simply not read after the upgrade (keys changed twice: property scoping + prefix). First calls per report will hit the API — expect a burst of quota consumption and possible 429s. Flush the stale keys or warm the cache in a post-deploy command.
  • The bug this release fixes was a correctness bug, not a perf bug. If you ran ≤1.1.1 with multiple properties, any report you cached in the last 24h may belong to a different property. Treat historical cached numbers in multi-client setups with suspicion before comparing period-over-period.
  • isTransactionInAnalytics() false vs. failure. Genuine "no such transaction" results are still cached for the lifetime; only failures are excluded now. Combined with GA4's ingestion delay (transactions can take hours to appear), keep reconciliation tolerant — poll for a window rather than a single check, or bypass the cache for the first few hours of an order's life.
  • Credentials path resolution. Relative paths resolve from the project root, not the bundle/config directory. Use absolute paths (base_path('storage/...') in Laravel) — the README's path examples were only fixed in this release, so older blog posts and copied snippets are misleading.
  • Access errors are usually GA4-side. A 403 despite a valid service account almost always means the account lacks the property-level Viewer role (GCP IAM alone is not enough), or the property ID is wrong.
  • PHP 8.5 compatibility. setAccessible() was removed, so this release is safe on 8.5 and you won't see the deprecation notice — but tooling pinned to older PHPStan/PHPUnit in your project may still warn.
  • No vendored tests. You can't run the package's own suite from vendor/; if you need to patch a cache-key edge case, fork or use a path repository.
  • Extension points are your own wrappers: a repository/service around the client for cache warming, per-client bindings in the container, and a Cache decorator if you need per-report TTLs instead of the global lifetime.
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.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings