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

Gtm Laravel Package

awcodes/gtm

A lightweight Laravel and Filament package for adding Google Tag Manager to your app. Set your GTM container ID, inject the required scripts, and push dataLayer events without editing your Blade views—a quick, clean analytics setup.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What is being assessed. awcodes/gtm is a single-purpose Laravel package that renders the two halves of a Google Tag Manager container into a Blade layout: x-gtm::script (the gtm.js loader, placed in <head>) and x-gtm::no-script (the <noscript> iframe, placed after <body>). It is driven by a published config/gtm.php exposing gtm.id and gtm.enabled, plus a per-component enabled prop. That is the entire surface area.

Architecture fit. Idiomatic and deliberately thin. No migrations, routes, middleware, queue workers, jobs, or meaningful service-provider logic. Output is static HTML emitted at render time, which puts it in the "cheap to adopt, cheap to remove" category — if the maintainer walks away, replacement is roughly an hour of pasting the same snippet into a layout partial. The real architectural fork is not "adopt a 5-star package" but "hand-maintain GTM snippet HTML and container IDs across every Blade layout, or standardise on one auditable component with a published config." The package makes standardising the cheaper path, which is the strongest argument in its favour. The boundary to state plainly: it renders tags; it does not define event schemas, validate the data layer, do server-side tagging, or push page_view on SPA transitions.

Integration feasibility. Low effort, one design point that needs a product decision. Adoption is composer require, publish config, wire gtm.id to an env var per environment, drop two components into the layout. The design point is the two-level enable gate: tags render only when both the per-component enabled prop and the gtm.enabled config value are true. This is a conservative safety model — config is the environment kill switch (local/CI/staging dark), the prop is the surface switch (app vs. admin vs. Filament panels, per tenant) — but it is also a silent-failure vector. A correctly wired deployment that renders nothing because one of two keys is false produces no error, no log line, and no failing test. v2.0.1 is the first release where the rule is explicitly documented in a new docs/ directory, which materially reduces the "why is there nothing in the page source" support load and lowers the bus factor on tag management.

Technical risk. Low blast radius, moderate verification signal. The v2.0.1 defect is a one-line config-key error: x-gtm::no-script read config('site.gtm.id') while the package publishes config/gtm.php, and no site namespace exists — so the fallback iframe emitted an empty container ID and reported nothing for visitors without JavaScript. x-gtm::script was unaffected, which is precisely why it survived: the prior suite rendered both components together and asserted the container ID appeared somewhere in combined output, which the healthy script tag satisfied on its own while the inert iframe passed beside it. That is a false-positive test, not a missing one. v2.0.1 replaces it with per-component assertions, a full matrix over enabled prop × gtm.enabled config, and a fix to the test environment (gtm.active vs gtm.enabled). Both are green flags for maintainer rigour, and both mean any pre-2.0.1 version carries less verification signal than its green badge implied — directly relevant if v2.0.0 was already certified internally.

What the bug cost the business. Every visitor without JavaScript was invisible to GTM: privacy-hardened browsers, link-preview and render services, older clients, some crawler/tooling traffic. The volume loss is thin but the trust implication is not — any historical baseline for "no-JS share of sessions" is an artefact of a broken tag, not a measurement, and must not be used to size capacity, argue channel mix, or set funnel-completion expectations. Expect a step change in reported volume for that segment after upgrade; brief dashboard owners before the deploy lands so it is not read as growth or as a tracking regression.

Key questions.

  1. What is the supported Laravel and PHP version matrix? Not stated in these notes; this gates adoption for any app on an older LTS line.
  2. Have we already certified v2.0.0 anywhere, and does any environment depend on it?
  3. Do we currently set a site.gtm.id config key or override the no-script view as a workaround? Both must be deleted in the same commit as the upgrade or we retain a dead key and a view that drifts from corrected upstream.
  4. Is there any consent gate in front of these components today? The enable flags gate rendering; they do not collect, store, or honour consent signals.
  5. Is any surface a SPA (Inertia/Vue/React)? If so, this covers initial load only and we need explicit page_view pushes elsewhere.
  6. Who is the named owner of this dependency and its upgrade cadence?

Integration Approach

Stack fit. Blade-first Laravel. The components compile into views and read from config, so they compose with any layout structure — application shell, admin panel, Filament panel — without per-template negotiation. Two operational realities follow from that: package auto-discovery must remain enabled (or the component namespace be registered manually), and config is cached in production, so config:cache must be rebuilt on every deploy. A stale cached gtm.id will mask both an environment change and the v2.0.1 fix itself.

Migration path. Two distinct migrations, and they should not be conflated:

  • Version migration (v2.0.0 → v2.0.1 or later). Patch release, no API change. The fix is a maintenance ticket, not a project. If we patched around the noscript bug locally, remove the workaround in the same commit.
  • Adoption migration (hand-maintained snippets → components). Audit every layout currently pasting GTM HTML or hardcoding a container ID; consolidate to a single source in the base layout; delete local overrides; confirm no surface renders the snippet twice.

Rollback is genuinely cheap in both cases: set gtm.enabled=false for an immediate kill switch, or revert the layout partial. That is worth stating to stakeholders — the blast radius of a bad deploy here is "no analytics for an hour," not "site down."

Compatibility. No stated Laravel/PHP support matrix in the release notes. Mitigate by pinning an exact constraint in composer.json (≥ 2.0.1, no wildcards, no dev branches), verifying against our specific Laravel/PHP pair in CI, and treating major-version bumps as review events rather than automatic merges. Five stars, zero dependents, and single-maintainer cadence are acceptable for a snippet renderer and disqualifying for anything load-bearing — this package must stay on the "rendering" side of that line.

Sequencing.

  1. Upgrade to ≥ v2.0.1 and certify the rendered output in CI or staging before any analytics work depends on it.
  2. Publish config/gtm.php, wire gtm.id to an env var, default gtm.enabled=false in .env.example.
  3. In staging, start with gtm.enabled=false and assert nothing renders. Then flip true and assert both the head script and the body noscript iframe contain a non-empty container ID.
  4. Delete any site.gtm.id shim and any overridden no-script view in the same commit.
  5. Production deploy with config cache rebuild, then a post-deploy check of rendered markup.
  6. Annotate the GA4 property and dashboards for the deploy window before it happens.
  7. Only then take up the analytics workstream that genuinely needs product judgement — event taxonomy, consent gating, SPA page_view pushes — none of which this package addresses.

Operational Impact

Maintenance. Near-static dependency; the risk is abandonment, not churn. Quarterly dependency triage is sufficient, with one guardrail: never certify a release on a green badge alone — check that per-component tests exist for the paths we rely on. If the package drops off, the exit is a layout partial containing the same two snippets, so the maintenance question is really "who owns the snippet," not "who owns the vendor relationship."

Support. The dominant support question will be "why is there no GTM markup on this page," and the answer is almost always the two-key gate. The new docs/ lowers that burden, but the internal runbook should be explicit and short: check gtm.enabled config, check the enabled prop, check whether config cache is stale, view source, check for a local override. This also answers a staffing question — a generalist Laravel engineer can own tag rendering in an afternoon — and separates it from the analytics engineering question, which is a different skill set.

Scaling. Negligible runtime cost: a view render and two config lookups per request; no external calls at render time (gtm.js loads client-side). It will not be a bottleneck at any traffic level we are likely to see. One scaling caveat worth flagging early: gtm.id is global config, so per-tenant or per-brand container IDs would require runtime config overrides. That is the point where the package stops being sufficient and we should expect to write our own thin wrapper.

Failure modes and mitigations.

  • Silent no-render from the two-level gate → post-deploy assertion that the container ID appears in both script and noscript output.
  • Empty container ID from a config-key mismatch (the v2.0.1 class of bug) → automated check asserting the ID is non-empty, not merely that markup exists.
  • Stale config cache masking an env change → config rebuild as a mandatory deploy step.
  • Tags firing before consent → compliance exposure the package happily enables; the gate is ours to build.
  • Production container leaking into non-prod and polluting the property → gtm.enabled=false as the default in all non-production env files.
  • SPA route changes untracked → inflated landing-page-only data; verify against a known navigation path before trusting funnel numbers.

Ramp-up. Low. One engineer afternoon for a Laravel-fluent developer, less with the docs. The honest risk in ramp-up is a false sense of completion: the package is simple, so adopting it feels like "tracking is done," when in fact deciding which events exist, verifying they fire, and honouring consent remain entirely ours. Sequence the dependency work as a prerequisite and budget the analytics discipline separately — otherwise we ship a correctly rendered container that measures the wrong things.

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.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment