jeffersongoncalves/laravel-gtm
Laravel GTM is a lightweight package for adding Google Tag Manager to Laravel apps. Set your container ID in config, and the package injects the GTM script and noscript fallback into your layouts, so you can manage analytics and marketing tags from the GTM dashboard without editing Blade templates.
Architecture fit. This package sits in the server-render path — it emits inline <script> blocks (the GTM snippet plus whatever other tags it manages) directly into Blade output. That placement is precisely what CSP breaks, so the 3.1.0 change is an architectural alignment rather than a new capability: it lets the package participate in Laravel's existing nonce mechanism (Vite::cspNonce()) instead of forcing teams to keep 'unsafe-inline' in script-src. Because it reads the same nonce source Vite already uses, inline scripts emitted by the package and the Vite-generated bundles share one consistent value — no second nonce authority, no divergence. It also pairs with laravel-security-headers 2.1, which is the component actually emitting the policy header, so the two are designed to be adopted together.
Integration feasibility. Low. The release note is explicit that behaviour is unchanged when no nonce is set, which makes this an additive, opt-in change with no config migration and no call-site changes. Realistically the work is: (a) bump the Composer constraint, (b) confirm a nonce is being generated and registered before views render, (c) flip the policy from 'unsafe-inline' to 'nonce-{nonce}'. The one ordering constraint to verify is that the nonce must be set (typically in middleware or a service provider) before the Blade template executes — any code path that renders tags before the nonce is established will silently emit a nonce-less script.
Technical risk. Moderate but well-bounded, and concentrated in CSP semantics rather than in the package.
'unsafe-inline' is removed, a missing or empty nonce means scripts are blocked with no server-side error — the site renders but analytics/GTM silently stop. This is the highest-impact failure mode and it is introduced by the adoption, not the upgrade.gtm.js tag covers the container script, but tags that GTM itself injects at runtime are outside the package's control. Those require 'strict-dynamic' or container-side configuration. This is the single most likely source of "it worked in staging, half our pixels died in prod" incidents.Key questions.
Vite::cspNonce() returns null/empty — render without the attribute, or skip the tag?'strict-dynamic' and for GTM-injected tags?Stack fit. A native Laravel package reading Laravel's native nonce API, complementary to a Laravel-native security-headers package. No bespoke middleware, no custom nonce store, no proxy-layer changes. It fits the standard Blade + Vite rendering model; anything outside that model (SPA front ends, separate marketing sites) is unaffected and out of scope.
Migration path. Treat as a minor, backward-compatible upgrade with an opt-in behavioural change. Two distinct steps that should be scheduled separately: the version bump (zero-risk, no config change, can ship on the normal release cadence) and the CSP tightening (behavioural, needs verification, should be a deliberate change with its own ticket and rollback plan). Do not bundle them into one deploy.
Compatibility. Backward compatible within 3.x for apps without a nonce — verify the constraint allows a clean composer update from the currently pinned version. Confirm the Laravel/PHP support matrix against our runtime before scheduling. The pairing with laravel-security-headers 2.1 should be treated as a tested combination, not an assumption.
Sequencing.
'unsafe-inline'.^3.1; confirm no behaviour change in staging (no nonce present yet).'unsafe-inline' as a temporary fallback; verify scripts carry the attribute in page source.'unsafe-inline' on a non-production environment first; run full tag-firing validation (browser console, CSP report endpoint, tag manager preview/debug).Maintenance. Small, single-purpose surface with low ongoing cost. The recurring obligation is governance rather than code: any future inline script added by any team must carry the nonce, so a lightweight review check ("no new inline scripts without nonce") is worth institutionalising. Nonce plumbing code should be owned centrally, not per-feature.
Support. Expect a shift in the shape of incidents rather than an increase in volume: CSP violations are silent to the server and loud only in the browser console. Without a report-to/report-uri endpoint, first-line support will get vague "analytics is broken" tickets with no server-side signal. Standing up CSP reporting before removal of 'unsafe-inline' is the single highest-value operational investment here. Runbooks should map "tags not firing" to "check nonce in page source" as step one.
Scaling. No runtime performance cost. The scaling consideration is infrastructural: per-response nonces are fundamentally incompatible with shared HTML caching, so any CDN or response-cache tier in front of these pages needs to be understood and reconfigured or excluded. This should be surfaced to whoever owns caching before rollout, not discovered during a traffic spike.
Failure modes.
'strict-dynamic' is absent → partial analytics loss, easy to miss.Ramp-up. Low for anyone who has worked with CSP; genuinely confusing for anyone who has not. The concepts to land with the team are the nonce lifecycle (generate per response, register before render, reference in both markup and header) and 'strict-dynamic'. Budget roughly half a day of engineering for the change itself and a comparable amount of QA to validate tag firing across the tag estate, plus a short written explainer so on-call can diagnose violations without escalation.
How can I help you explore Laravel packages today?