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 Tag Manager Bundle Laravel Package

oro/google-tag-manager-bundle

The Oro Google Tag Manager Bundle integrates GTM into Oro applications with configurable container settings and ecommerce event tracking, helping storefronts send page, product, and order data to analytics and marketing tags with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

This is not a Laravel package — it is an OroPlatform/OroCommerce Symfony bundle (oroinc namespace) for injecting Google Tag Manager and pushing e-commerce dataLayer events from an Oro storefront. Drop the idea of a service provider; the install target is an Oro application.

Verify before installing:

composer show oro/google-tag-manager --all   # check "type" (symfony-bundle / oro-bundle) and requires

Expect hard version constraints against oro/platform and oro/commerce. Pin it to match your platform minor version — Oro bundles are released in lockstep and will not float across majors.

Install (inside an Oro app):

composer require oro/google-tag-manager
php bin/console oro:platform:update --env=prod
php bin/console cache:clear --env=prod

Where to look first, in this order:

  1. Resources/config/oro/system_configuration.yml — the real API surface. This tells you the config keys, labels, and scopes (global / website) you'll toggle in the admin UI.
  2. Resources/views/ — the Twig snippet and where the dataLayer bootstrap is rendered.
  3. Resources/public/js/ — the RequireJS module(s) that push events. This is where the event contract lives.
  4. Resources/config/oro/layouts.yml or Resources/views/layouts/ — how the block is injected into head / before_body_end.
  5. DependencyInjection/Configuration.php and Resources/config/services.yml — anything you can decorate.

First working use case: enable the integration in System → Configuration (look for the Google Tag Manager group under Sales/Commerce/Marketing), paste your GTM-XXXXXXX container ID, save with the correct scope, clear cache, then load the storefront and confirm the snippet appears once in <head>. Verify a real signal end-to-end by placing a test order and watching window.dataLayer in the console alongside GTM Preview mode.

Implementation Patterns

Configuration-driven, not code-driven. The intended workflow is: admin sets container ID per website scope, the bundle renders the container snippet and emits a baseline dataLayer. Resist hardcoding the ID in your theme — you'll lose multi-website support and the ability to disable GTM per storefront.

Server-rendered dataLayer payloads. The common pattern is to render page-specific e-commerce context into dataLayer from Twig (product SKU, name, price, category on a product page), then let the JS module push events on interaction:

{# conceptual — match the actual template in Resources/views #}
<script>
  window.dataLayer = window.dataLayer || [];
  dataLayer.push({
    ecommerce: null
  });
  dataLayer.push({
    event: 'view_item',
    ecommerce: { items: [{ item_id: '{{ product.sku }}', item_name: '...', price: {{ price }} }] }
  });
</script>

Use GA4 event names (view_item, add_to_cart, begin_checkout, purchase) rather than legacy UA naming; the bundle's JS may still use UA-era names depending on version — normalize in your own layer if so.

Layout overrides are the extension point. Inject or reorder the GTM block through a layout theme file rather than editing vendor templates:

# Resources/views/layouts/<theme>/layout.yml
layout:
  actions:
    - '@setBlock': { id: gtm_container, ... }   # or move/remove the existing block

Override the Twig template by placing the same relative path in your own bundle — Oro's template resolution gives your bundle priority. Keep the vendor file untouched so upgrades stay clean.

Service decoration for behavioural changes. If the bundle exposes services (e.g. a data provider or block type), decorate with decorates: in your services.yml instead of subclassing. That's the only upgrade-safe way to alter what gets pushed.

Consent gating. Do not render the container unconditionally. Pair with a cookie-consent bundle and wrap the snippet behind a consent check, or use GTM's own consent mode (gtag('consent', 'default', …)) rendered before the container. This is a legal requirement in the EU and the bundle will not do it for you.

QA loop. GTM Preview mode → connect to your storefront URL → click through product → cart → checkout. In parallel, keep a console tab open logging dataLayer. Clear Oro cache after every template or layout change; the layout cache is aggressive and will serve stale markup silently.

If you're porting the concept to Laravel (the realistic path for a Laravel developer): mirror the contract, not the code. One Blade partial in resources/views/layouts/, one config/gtm.php with the container ID, one small JS module that owns dataLayer.push, and the same GA4 event taxonomy. That gets you 90% of the value in a fraction of the coupling.

Gotchas and Tips

  • Wrong framework. Installing this into a Laravel project will either fail on oro/platform constraints or install dead weight that never boots. It is a Symfony bundle for Oro. If this appears in a Laravel dependency graph, something is misconfigured upstream.
  • License is NOASSERTION. No machine-readable SPDX identifier. Open LICENSE in the repo before you ship anything commercial — Oro packages are typically OSL-3.0, which has copyleft-flavoured obligations on distribution. Get this reviewed rather than assumed.
  • Version lockstep. Upgrading OroPlatform without upgrading this bundle (or vice versa) is the most common breakage. Pin both together in composer.json and treat them as a unit.
  • Cache is the #1 source of "it doesn't work." cache:clear plus oro:platform:update after config or layout changes. In prod, check var/cache/prod timestamps before debugging code — you're often debugging stale Twig.
  • Config scope surprises. A container ID set at global scope can be silently overridden (or not inherited) at website scope. Verify which scope the admin form writes to before concluding the ID is missing.
  • Double-counting. If your theme already hardcodes the GTM snippet, you get two containers and duplicated pageviews. Search your theme for googletagmanager.com before enabling.
  • ecommerce object leakage. dataLayer persists across pushes. Always dataLayer.push({ ecommerce: null }) before a new e-commerce event, or GTM merges stale items into cart/purchase payloads.
  • Purchase event duplication. The success page can be refreshed, re-firing purchase. Deduplicate with a transaction ID check server-side or a sessionStorage guard — the bundle won't do it for you.
  • CSP blocks everything quietly. Add googletagmanager.com to script-src and google-analytics.com / analytics.google.com to connect-src in Oro's CSP config. Failures show only in the browser console, not in PHP logs.
  • Thin ecosystem signal. 2 stars, 0 dependents, low opportunity score. Expect minimal documentation and no community answers — read Resources/config/oro/system_configuration.yml and the JS module as the authoritative spec. Budget time to fork; keep your overrides in your own bundle so a fork stays optional.
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.
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
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle