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

Google Analytics Bundle Laravel Package

happyr/google-analytics-bundle

HappyR Google Analytics Bundle integrates Google Analytics tracking into Symfony applications. Configure your tracking ID and render the analytics snippet from Twig templates, keeping analytics setup centralized and easy to manage across environments.

View on GitHub
Deep Wiki
Context7

Getting Started

The bundle is a thin Symfony wrapper around the Universal Analytics Measurement Protocol — a server-to-server HTTP POST to google-analytics.com/collect. It exists so your backend can report things a browser tag can't see (webhooks, queued jobs, API-only conversions, refunds).

First contact:

  1. composer require happyr/google-analytics-bundle — this brings in the underlying GA HTTP client as well.
  2. Register the bundle in config/bundles.php (Symfony) and create config/packages/happyr_google_analytics.yaml with at minimum a tracking_id (UA-XXXXX-Y) and a way to resolve a client_id.
  3. Read DependencyInjection/Configuration.php first — it is the real documentation, and it tells you exactly which services are aliased (happyr.google_analytics.client, the tracker, the client-ID provider).
  4. Then read the Tracker class: it is the entire public surface, and it maps 1:1 onto Measurement Protocol hit types (pageview, event, exception, timing, social, transaction).

Laravel caveat up front: this is a Symfony bundle, so there is no package discovery and no publishable config. You will either run Symfony, or pull the underlying client in directly and skip the bundle entirely. For a Laravel app the realistic "first use case" is: a queued listener that fires an event hit when something happens server-side — e.g. order.refunded, trial.started, webhook.received — where you cannot rely on a JS snippet.

Implementation Patterns

Inject the tracker, not the client. The tracker is the intended seam. Type-hint the tracker (or resolve it from the container) and call the named hit methods rather than assembling payload arrays yourself. That keeps you insulated if the payload builder changes.

Solve client ID once, centrally. This is the single most important design decision. The Measurement Protocol requires a client_id to stitch hits into a session. Options, in order of preference:

  • Reuse the _ga cookie value the browser tag already set (GA1.2.XXXXXXXXXX.YYYYYYYYYY) — best attribution continuity.
  • Fall back to your authenticated user ID hashed into a stable UUID.
  • Generate and persist a UUID per session in your session store.

Wrap this in a small ClientIdProvider implementation and bind it; the bundle supports supplying a provider precisely because the naive "new UUID per request" makes every hit its own session and destroys your reports.

Always send from a queue. The tracker performs a synchronous outbound HTTP call. In a controller this adds tens to hundreds of milliseconds and, worse, couples your response time to Google's availability. Dispatch a job (SendAnalyticsHit) and let it run on a worker; make the job idempotent and cap retries at 1–2.

Decorate for environments. Bind a no-op implementation of the tracker in local/testing, and a recording fake in tests. Because the real tracker swallows failures, you cannot assert on outcomes — so assert on what your application asked to send, not on what Google accepted.

Use the debug endpoint in staging. Configure debug mode so hits go to /debug/collect, which returns validation errors instead of a silent 200. Run every new hit type through it once; it catches malformed categories, oversized values, and bad client IDs immediately.

Gate on consent. Server-side hits are still personal data processing. If your tracking requires consent, check the flag before dispatching the job — do not send and then attempt to delete.

Gotchas and Tips

The core problem: Universal Analytics is shut down. UA properties stopped processing hits in 2023, and this bundle speaks UA Measurement Protocol v1 only. The endpoint, the v=1 parameter, the UA- tracking ID, and the hit shapes all belong to a protocol Google no longer accepts. GA4 uses Measurement Protocol v2: a different URL (/mp/collect), api_secret + measurement_id instead of tracking_id, and a nested events[] payload. Nothing here works against a GA4 property without forking the client. Treat this as a reference implementation to learn from, not a dependency to adopt.

Silent failures are the norm. The protocol returns 204 No Content on success and also on many rejections. There is no error to catch in production. If a hit isn't appearing in reports, the answer is almost always the debug endpoint, not your logs.

Client ID drift is the top reporting bug. If your provider changes the ID between the pageview and the event (new session, cookie not read on an API route), the event lands as a new user with no preceding pageview. Log the resolved client ID at debug level on every hit.

Latency and timeouts. The underlying HTTP client has no aggressive default timeout. Set one explicitly (2–3s) so a stalled connection to Google cannot pin a queue worker.

Payload limits. Hits are capped around 8KB; long labels and URLs get truncated server-side without complaint. Batch endpoints exist (/batch, up to 20 hits) but the bundle does not expose them — if you need throughput you are writing your own sender anyway.

Extension points, if you do fork or wrap it: the client-ID provider interface, the HTTP client (swappable for a fake or a proxy), and the tracker itself (decoratable to add batching, consent checks, or a GA4 adapter on the same interface). Those three seams are the bundle's real value.

Version constraints. Last release 2020, targeting Symfony 3/4-era APIs and older PHP. On modern Symfony or any Laravel version, expect to resolve the internals manually rather than through the bundle.

Don't use it for money-critical attribution. Fire-and-forget analytics with no acknowledgement is fine for dashboards and coarse funnels. Anything you reconcile against revenue belongs in your own database, with GA as a secondary destination.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource