widop/google-analytics-bundle
Symfony bundle that simplifies Google Analytics integration. It provides configuration for your tracking ID and Twig helpers for rendering the analytics snippet, making page-view tracking easy to add with minimal setup.
Install and register the bundle. Add widop/google-analytics-bundle to composer.json (it is a Symfony2-era bundle, so expect symfony/* constraints around 2.3–2.8). Register new Widop\GoogleAnalyticsBundle\WidopGoogleAnalyticsBundle() in AppKernel.php.
Provision the service account. In the Google API Console create a Service Account, enable the Analytics API, generate a P12 key, note the service-account email ([email protected]), and then add that email as a user on the Google Analytics property (Read & Analyze, or Edit for tracking).
Configure the bundle. Minimum config in config.yml:
widop_google_analytics:
client_id: [email protected]
private_key_path: %kernel.root_dir%/config/analytics.p12
profile_id: UA-XXXXXXX-1
First use case. In a controller, push a server-side hit — the canonical entry point is the tracker service:
$this->get('widop_google_analytics.tracker')
->trackPageView('Thank you', '/checkout/thank-you');
This is the sweet spot: a hit that originates on the server (postback, webhook, order confirmation) where the browser JS snippet never ran.
Look first at the bundle's DependencyInjection/Configuration.php and the Model/Tracker class — they define every config key and method you can call.
Inject the tracker, don't use the container. Type-hint Widop\GoogleAnalyticsBundle\Model\TrackerInterface in your own services. This also makes it swappable for a test double.
Server-side ecommerce. The tracker mirrors the Measurement Protocol closely: trackTransaction(...) followed by one trackItem(...) per line item. Do the transaction call first, items after, and skip items entirely if the transaction failed — otherwise you get orphan items with mismatched revenue.
Event tracking from jobs and listeners. Backend workflows (subscription renewed, refund issued, invite accepted) map cleanly to trackEvent($category, $action, $label, $value). Wrap this in a small AnalyticsReporter service and call it from an event listener rather than scattering $this->get(...) calls across controllers.
Reporting alongside tracking. The bundle also exposes an analytics/reporting service built on the Core Reporting API. A common pattern is a lightweight dashboard controller that queries sessions/events by date range using the same service account.
Read/write separation. Keep tracking fire-and-forget and reporting synchronous. If you can, push tracking hits onto a queue (Symfony's kernel.terminate listener or a message bus) so a slow Google endpoint never blocks a checkout response.
Environment guard. Disable tracking in test/dev via a bundle config flag or by binding a no-op tracker. You do not want staging hits polluting production reports.
UA- Measurement Protocol and Core Reporting API. New properties are GA4 (G-XXXX / Data API), which this bundle cannot talk to. Treat it as legacy-maintenance only; for greenfield work use the google/analytics-data client directly.setAssertionCredentials with a .p12. Recent google/apiclient prefers a JSON key via setAuthConfig(). Mismatched versions produce cryptic invalid_grant errors — pin google/apiclient alongside the bundle.profile_id is the view ID, not the account or property. It must match UA-XXXXXXX-N where N is the view.cid (or uid) explicitly, each hit may be treated as a new session, inflating user counts. Set a stable ID derived from your own user record.widop_google_analytics.tracker alias in your bundle's services.yml to add retries, logging, or user-ID injection, and use a compiler pass if you need to swap the HTTP client.google/apiclient directly (or a small Measurement Protocol wrapper) rather than trying to bridge the bundle — you'd only be pulling in the tracker/model classes and discarding everything that made it a bundle.How can I help you explore Laravel packages today?