# DfGtagManager — Complete documentation

> DfGtagManager is a Shopware 6.7 plugin that injects a Google Tag Manager container, emits the complete GA4 e-commerce events, handles Consent Mode v2 through the native Shopware cookie banner, pushes…

- Page: <https://www.datafirefly.com/en/documentation/google-tag-manager-shopware-ga4-consent-mode-enhanced-conversions/>
- Language: en
- Last updated: 2026-07-01
- Other languages: [fr](https://www.datafirefly.com/documentation/google-tag-manager-shopware-ga4-consent-mode-enhanced-conversions/index.md), [es](https://www.datafirefly.com/es/documentation/google-tag-manager-shopware-ga4-consent-mode-enhanced-conversions/index.md), [de](https://www.datafirefly.com/de/documentation/google-tag-manager-shopware-ga4-consent-mode-enhanced-conversions/index.md), [it](https://www.datafirefly.com/it/documentation/google-tag-manager-shopware-ga4-consent-mode-enhanced-conversions/index.md), [pl](https://www.datafirefly.com/pl/documentation/google-tag-manager-shopware-ga4-consent-mode-enhanced-conversions/index.md), [nl](https://www.datafirefly.com/nl/documentation/google-tag-manager-shopware-ga4-consent-mode-enhanced-conversions/index.md), [pt](https://www.datafirefly.com/pt/documentation/google-tag-manager-shopware-ga4-consent-mode-enhanced-conversions/index.md)
- Index: <https://www.datafirefly.com/en/documentation/llms.txt>

DfGtagManager is a Shopware 6.7 plugin that injects a Google Tag Manager container, emits the complete GA4 e-commerce events, handles Consent Mode v2 through the native Shopware cookie banner, pushes SHA-256 hashed Enhanced Conversions, and aligns the data layer with your Google Merchant Center feed. This documentation covers installation, complete configuration, and verification.

## Requirements

- Shopware 6.7.0 or newer
- PHP 8.2 minimum
- SSH or Shopware admin access to install the ZIP
- A Google Tag Manager account (recommended) or at minimum a Google Analytics 4 account
- For Enhanced Conversions: a Google Ads account with conversion campaigns configured

## Installation

Three methods are available depending on your environment.

### From the Shopware admin

1. In the back-office: **Extensions → My extensions → Upload extension**
2. Select the `DfGtagManager.zip` file
3. Click **Install** then **Activate**
4. Clear the cache: **Settings → System → Caches & indexes → Clear and rebuild**

### From the command line (recommended in production)

```
cd /path/to/shopware
unzip DfGtagManager.zip -d custom/plugins/
bin/console plugin:refresh
bin/console plugin:install --activate DfGtagManager
bin/console assets:install
bin/console cache:clear
```

**Tip.** After `assets:install`, the `df-gtag-manager.js` file is published to `public/bundles/dfgtagmanager/` and becomes accessible via the Twig asset helper. No webpack or TypeScript build step is required.

## Configuration

Open the configuration: **Extensions → My extensions → DataFirefly Google Tag Manager → ⋮ menu → Configure**. Pick the target sales-channel at the top — each sales-channel can have its own independent configuration.

### General settings

- **Enable plugin**: master toggle. Turn off to disable all injection without uninstalling.
- **Debug mode**: writes `[DfGtag]`-prefixed logs to the browser console (add_to_cart, remove_from_cart, consent update…). Enable only in test environments.

### Google Tag Manager

- **GTM Container ID**: format `GTM-XXXXXXX`. Available in [tagmanager.google.com](https://tagmanager.google.com), top right of your container. Leave empty if you don't use GTM — the plugin will fall back to the `gtag.js` loader if a GA4 Measurement ID is set.
- **Server-side GTM URL** (optional): URL of your server-side Tag Manager loader (e.g. `https://gtm.yourdomain.com`, no trailing slash). See [Server-side GTM](#server-side-gtm) below.

### Google Analytics 4

- **GA4 Measurement ID**: format `G-XXXXXXXXXX`. Available in GA4 under **Admin → Data streams → Web**. Used as a `gtag.js` fallback when no GTM container is set, and pushed to the dataLayer for GTM tags.
- **Send automatic page_view event**: enabled by default. Disable if you prefer to trigger `page_view` manually from GTM.

### Consent Mode v2

- **Enable Consent Mode v2**: emits `gtag consent default` before GTM loads, with the seven Consent Mode v2 categories. See [Consent Mode v2 in detail](#consent-mode-v2).
- **Default consent state**:
   - _Denied_ — recommended for EU/GDPR. No analytics or advertising cookie is dropped before user acceptance.
   - _Granted_ — reserve for non-EU visitors or stores restricted to a professional audience not subject to GDPR.
- **Enable url_passthrough**: preserves `gclid`, `_gl`, `dclid` parameters across pages even when cookies are denied. Useful for multi-touch attribution.
- **Enable ads_data_redaction when denied**: redacts advertising identifiers sent to Google Ads when the user declines. Further reduces the tracking surface.

### Enhanced Conversions

- **Enable Enhanced Conversions**: pushes a `user_data` object with email, phone, first name, last name, street, city, postal code, all hashed SHA-256 server-side, on the checkout _confirm_ and _finish_ pages. See [Enhanced Conversions in detail](#enhanced-conversions).

### Google Shopping / Merchant Center

- **item_id source**: determines what the plugin pushes as `item_id` in each GA4 item. This value **must** match the `id` field of your Merchant Center feed. Three options:
   - _Product number (SKU)_ — recommended, the most common format in XML/CSV Merchant Center feeds.
   - _Shopware UUID_ — useful if you generate your feed directly from the Shopware database.
   - _EAN / GTIN_ — useful if your feed uses international barcodes.
- **Default Google product category**: value pushed to `google_product_category` when neither the product nor its category defines one. Google format (e.g. `Apparel & Accessories > Clothing`).
- **Default brand**: used as a fallback in `item_brand` when the product has no manufacturer assigned.

### Events

Each GA4 event can be enabled individually. Untick the ones you don't want.

- **view_item** — product detail page
- **view_item_list** — category page and search results
- **add_to_cart** — click on the add-to-cart button (JavaScript listener)
- **remove_from_cart** — line removal in cart or offcanvas
- **view_cart** — cart page
- **begin_checkout** — checkout confirm page
- **purchase** — finish page after order
- **search** — search results page
- **login / sign_up** — account form submissions

## Consent Mode v2 in detail

Consent Mode v2 is Google's official mechanism for handling user consent. Since March 2024, Google Ads requires it for advertisers targeting the European Economic Area — without it, you lose access to remarketing and conversion measurement.

### Load order

The plugin guarantees the following order on every storefront page:

1. Initialize `window.dataLayer` and the `gtag()` stub
2. Emit `gtag consent default` with the seven Consent Mode v2 categories and `wait_for_update: 500`
3. Emit `url_passthrough` and `ads_data_redaction` if enabled
4. Push the page's GA4 events (view_item, view_cart…) to the dataLayer
5. Load the GTM script (or `gtag.js` as fallback)

**Why wait_for_update: 500?** This tells Google to wait up to 500 ms after page load before firing denied-mode hits — enough time for your cookie banner to collect the user's answer and for the plugin to push a `gtag consent update`. Without this delay, all initial hits are emitted in denied mode even if the user accepts immediately.

### Integration with the Shopware cookie banner

The plugin decorates `CookieProviderInterface` and registers two virtual cookies in the native banner groups:

- `df-gtag-analytics` in the **Statistics** group — controls `analytics_storage`
- `df-gtag-ads` in the **Marketing** group — controls `ad_storage`, `ad_user_data`, `ad_personalization`

When the user saves their preferences, Shopware fires the `CookieConfiguration_Update` event. The plugin's JavaScript controller listens to it, reads the two virtual cookie values, and immediately fires the matching `gtag consent update`.

### Third-party banner compatibility

If you use Cookiebot, CookieFirst, OneTrust or Axeptio instead of the native Shopware banner, you have to fire `gtag consent update` yourself from the third-party banner with the correct categories. The plugin doesn't block this — it only handles the initial `consent default` and listens for the Shopware event.

## Enhanced Conversions in detail

Enhanced Conversions improve Google Ads measurement accuracy by sending first-party user data (email, phone, name, address) SHA-256 hashed at conversion time. Google then reconnects these conversions with signed-in Google users, which typically restores 10 to 30% of conversions previously lost to cookie blockers, cross-device or browser switching.

### Normalization applied

The plugin normalizes each field per Google specification before hashing:

- **Email**: lowercased, trimmed, then SHA-256
- **Phone**: E.164 (automatic country prefix from the billing address ISO, e.g. `+33612345678`), then SHA-256
- **First name, last name, street, city**: lowercased, trimmed, then SHA-256
- **Postal code**: lowercased, trimmed; for US, truncated to the first 5 digits before hashing
- **Country**: ISO-2 code in uppercase, not hashed

### dataLayer payload

On `begin_checkout` and `purchase` events, the plugin pushes:

```
{
  "event": "purchase",
  "ecommerce": { ... },
  "user_data": {
    "sha256_email_address": "...",
    "sha256_phone_number": "...",
    "address": {
      "sha256_first_name": "...",
      "sha256_last_name": "...",
      "sha256_street": "...",
      "sha256_city": "...",
      "postal_code": "...",
      "country": "FR"
    }
  }
}
```

### GTM configuration

1. In your GTM container, create or edit your **Google Ads Conversion Tracking** tag
2. Section **Include user-provided data from your website** → **Manual configuration**
3. Create eight Data Layer Variables pointing to:
   - `user_data.sha256_email_address` → mapped to **Email (hashed)**
   - `user_data.sha256_phone_number` → mapped to **Phone (hashed)**
   - `user_data.address.sha256_first_name` → **First name (hashed)**
   - `user_data.address.sha256_last_name` → **Last name (hashed)**
   - `user_data.address.sha256_street` → **Street (hashed)**
   - `user_data.address.sha256_city` → **City (hashed)**
   - `user_data.address.postal_code` → **Postal code**
   - `user_data.address.country` → **Country**
4. Save and publish the container

**Warning.** Google requires the values to already be hashed on the site side — do not apply GTM's _SHA-256 Hash_ variable to these values, they come out of the plugin already hashed. Double hashing would make matching impossible.

## Google Shopping and Merchant Center feed

For GA4 and Google Ads to correctly match e-commerce events with your Shopping products, every item in the dataLayer must use the same `item_id` as the one in your Merchant Center feed.

### Fields pushed in each item

- `item_id` — configurable source (SKU / UUID / EAN)
- `item_name` — product name in the active language
- `item_brand` — manufacturer name, or default brand if unset
- `item_category` to `item_category5` — full breadcrumb starting from the deepest category
- `google_product_category` — see below
- `price`, `quantity`, `currency`
- `mpn` — Manufacturer Part Number when set on the product
- `gtin` — EAN when set
- `discount` — computed from the difference between list price and sale price

### Per-product google_product_category

You can override the Google Shopping category for a product or a category via a custom field:

1. In the back-office: **Settings → System → Custom fields → Create new set**
2. Technical name: `df_google_product_category`, type **Text**
3. Assign this set to **Product** and/or **Category** entities
4. On each product or category, set the Google value (e.g. `Sporting Goods > Athletics > Football > Football Balls`)

The plugin looks for the value in this order: product custom field → deepest-category custom field → global default from the configuration.

## Server-side GTM

Server-side tagging routes GTM traffic through a domain you control, which bypasses browser blockers, protects user data, and improves resilience against cookie policy changes.

### Requirements

- A server-side GTM container set up (see [Google documentation](https://developers.google.com/tag-platform/tag-manager/server-side))
- A dedicated domain or sub-domain pointing to your Tag Manager server, e.g. `gtm.yourdomain.com`

### Activation

In the plugin configuration, section **Google Tag Manager**, set **Server-side GTM URL** with your domain _without trailing slash_:

```
https://gtm.yourdomain.com
```

The GTM script and noscript iframe will automatically point to your server instead of `www.googletagmanager.com`.

## Verification

### Google Tag Assistant

1. Install the Chrome extension **Tag Assistant Companion**
2. Open [tagassistant.google.com](https://tagassistant.google.com), click **Add domain** and enter your storefront URL
3. Navigate to a product page, add to cart, go to checkout — every step should appear in the assistant with the matching GA4 events

### GA4 DebugView

In GA4: **Admin → DebugView**. Events appear in real time as soon as Debug mode is active in the plugin or the `debug_mode=true` parameter is sent.

### Plugin debug mode

Enable **Debug mode** in the configuration and open the browser console. You will see:

```
[DfGtag] consent update { analytics_storage: "granted", ad_storage: "denied", ... }
[DfGtag] add_to_cart { item_id: "SW10001", item_name: "...", price: 129, quantity: 1 }
[DfGtag] remove_from_cart { ... }
```

### Validation checklist

- On home: consent default emitted before the GTM script (order in the head)
- On a product page: `view_item` with `item_id`, `item_brand`, `item_category`, `google_product_category`
- On add-to-cart: `add_to_cart` with the same item
- On the cart: `view_cart` with every item
- On confirm page: `begin_checkout` with hashed `user_data`
- On finish page: `purchase` with `transaction_id`, `value`, `tax`, `shipping`, `currency`, `items` and hashed `user_data`
- On cookie acceptance: `consent update` with granted categories

## Troubleshooting

### Events don't appear in GA4 DebugView

- Verify the GA4 Measurement ID is correct in the configuration
- Verify the GA4 Configuration tag is created and published in your GTM container
- Verify the tag's trigger covers all pages (_All Pages_)
- Clear the Shopware cache and reload the page with a _hard reload_ (Ctrl+F5)

### Enhanced Conversions don't match

- Verify no additional transformation (GTM's SHA-256 Hash variable) is applied to `user_data` variables — values come out already hashed
- Verify the phone's E.164 format in the dataLayer (with country prefix starting with `+`)
- Verify the `country` field is ISO-2 uppercase (`FR`, not `France`)
- Wait 24 to 48 hours after activation: Google Ads needs this delay for the first sync

### consent update not fired when user accepts

- Confirm the banner in use is the native Shopware one
- Open the browser console in debug mode and verify the `CookieConfiguration_Update` event is fired when the user saves the banner
- Verify the `df-gtag-analytics` and `df-gtag-ads` cookies appear in the banner and are ticked

### item_id doesn't match my Merchant Center feed

- Open your XML/CSV feed and look at the `` field for a product
- In the plugin configuration, pick the `item_id` source that produces exactly the same value (SKU, UUID or EAN)
- If your feed uses a prefix (e.g. `shopware_SW10001`), you'll need a GTM tag that prefixes the value before sending to Google Ads

### The plugin doesn't load on some pages

- Verify the current sales-channel has **Enable plugin** ON in its specific configuration
- Some custom pages (custom CMS landing pages) may not trigger the standard Page Loaded Events. In this case, the GTM container is still loaded via the header pagelet.
