modera/backend-google-analytics-config-bundle
Laravel bundle that adds Google Analytics configuration fields to the Modera backend, letting administrators manage analytics settings from the admin panel without touching code.
Read this first: despite the bundle suffix and the "Laravel/PHP package" framing, this is a Symfony bundle for the Modera CMS backend, not a Laravel package. Installing it into a Laravel app with composer require modera/backend-google-analytics-config-bundle will pull Symfony/Modera dependencies your app has no kernel or container to boot. Your two realistic paths:
ModeraBackendSettingsBundle — install it there.Where to look first, in order:
composer.json — the pinned php and symfony/* / modera/* versions tell you immediately whether your Modera install is compatible. This is the fastest go/no-go gate.DependencyInjection/ and Resources/config/services.* — this is where the bundle registers its settings section as a tagged service. That tag is the entire mechanism — everything else is a form type and a translation string.Contributions/ or Config/ (naming varies across Modera bundles) — the class implementing the config-section interface plus its form type. This defines the actual fields (typically one tracking/measurement ID, maybe an enabled flag).Resources/translations/ — the section and field labels. Copy these verbatim if you're porting to Laravel.First use case: give a non-developer the ability to change the GA4 measurement ID (G-XXXXXXXXXX) without a deploy. That's it — the scope is a persisted string plus a form around it. Do not expect snippet injection, consent handling, or events from this package.
Laravel equivalent, if that's you (recommended):
GOOGLE_ANALYTICS_ID env var in config/services.php.regex:/^G-[A-Z0-9]+$/ rule.gtag.js once in your base layout guarded by @if(config('services.google_analytics.id')).Reading the config in Modera/Symfony (the day-to-day pattern). The bundle's value is a service the rest of your app consumes — not the admin form. Inject that service or pull the setting by key, rather than reaching into config files:
// Pseudocode — confirm exact interface from the source's Contributions class
$gaConfig = $this->get('modera_backend_google_analytics_config.provider')->getConfig();
$measurementId = $gaConfig->getTrackingId(); // may be UA- or G- depending on vintage
Then pass that value to your base Twig template and render the snippet in one place, never per-component.
Environment-aware separation. The pitch in the description is "keep staging and production tracking separate." In practice this means either the Modera settings key is scoped per environment, or you handle it by only rendering the tag when the stored value differs from production (or when a GA_ENABLED/APP_ENV guard passes). Verify which in the source — don't assume multi-tenant scoping exists.
Admin section contribution (Symfony path). The pattern is: register a form type that implements Modera's config-section interface, tag it as a service, and let ModeraBackendSettingsBundle discover it. You don't write routing or controllers — Modera's settings shell handles persistence and rendering. Your work is: form type with the fields, translation keys, and a service tag in services.yaml.
Admin settings field (Laravel path). Mirror the same surface — one persisted config value, editable by an admin, read by the layout:
// config/services.php
'google_analytics' => [
'id' => env('GOOGLE_ANALYTICS_ID'),
],
// resources/views/layouts/app.blade.php
@if($gaId = config('services.google_analytics.id'))
<script async src="https://www.googletagmanager.com/gtag/js?id={{ $gaId }}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ $gaId }}', { anonymize_ip: true });
</script>
@endif
Integration with consent management. This bundle does not solve consent. If you're on the Modera path, wire the snippet render behind your consent manager (OneTrust, Cookiebot, custom). On Laravel, gate the @if block by the same consent check that governs your cookie banner — do not render gtag.js unconditionally.
Multi-brand / multi-tenant. If a single backend powers multiple sites or brands, this bundle is a reference pattern, not a solution. You'd need per-tenant persistence (a settings table with a tenant_id column) and a per-request lookup — the package almost certainly stores a single global key-value.
UA vs GA4 is the biggest trap. Universal Analytics IDs (UA-XXXXX-X) have been dead since July 2023. If this bundle's form validation or the stored value assumes UA- format, it will save successfully and then send your analytics dashboards to nowhere — silent data loss, no error surfaced. Audit the source for G- (measurement ID) support before adoption, and prefer a validation rule that rejects UA-.
Container compile failure is a hard boot failure, not a soft degradation. If ModeraBackendSettingsBundle is missing or version-mismatched, the Symfony kernel won't boot. Run composer require --dry-run and a container-compile smoke test in an isolated Symfony skeleton before committing to the Symfony path.
It may not render the snippet at all. The description says "single place to store and manage" — that's persistence, not injection. Confirm in the source whether any template injects gtag.js, or whether your frontend must read the value and render it. The latter is common and means the bundle's entire job is the admin form.
Abandonware risk is real. 0 stars, 0 dependents, score 0.09. There's no battle-testing, no issue triage, no security response, no upgrade path. Treat it as vendored source you now own — fork, pin, and add it to your internal maintenance list. On a Laravel stack, don't adopt it at all; reimplementing is cheaper than the risk.
Silent analytics loss is the worst failure mode to guard. The form saves, the value looks right, and nothing ships to Google. Add a smoke assertion in your test suite that the googletagmanager.com script tag appears in rendered HTML when a config value is present.
Consent/privacy exposure is the highest-severity concern. If you add snippet rendering on top of this bundle without a consent gate, you've created a legal-review ticket. Check GDPR/consent-mode-v2 requirements before wiring the tag.
Config caching. In Symfony, the settings value is read through Modera's config layer, which typically caches. After changing the value in the admin UI, verify the change takes effect on the next request without a cache clear — if it doesn't, your admin UX is broken in a way no one will notice until marketing complains.
Extension points. If you're on the Modera path and need more than a single ID, the cleanest extension is a second contribution registered alongside this bundle's section — not forking the bundle. That keeps the upstream section untouched and your additions isolated.
Laravel developers: don't force it. The abstraction doesn't transfer. Use a native settings model (Filament/Blade form + config()/Setting::get()), validate G-[A-Z0-9]+, render the tag once in the layout behind a consent gate. Total effort: 1–2 days including consent handling — the entire functional payload of this bundle.
How can I help you explore Laravel packages today?