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.
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.choose_handler() fallback is gone, so don't pin an ancient Guzzle.cache.prefix, and lifetime. Credentials are a Google Cloud service account that must additionally be granted Viewer on the GA4 property itself.isTransactionInAnalytics($transactionId) for order reconciliation in a scheduled command.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).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.->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.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.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.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.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.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.vendor/; if you need to patch a cache-key edge case, fork or use a path repository.Cache decorator if you need per-report TTLs instead of the global lifetime.How can I help you explore Laravel packages today?