Product Feed Data vs GA4 Item Data on Magento 2: Why They Must Agree

|Dan Giura
Product Feed Data vs GA4 Item Data on Magento 2: Why They Must Agree

TL;DR

Two Magento modules describe the same catalog to Google. The feed says which products exist and what they cost. The analytics layer says which of them were viewed, added and bought. Nothing in either configuration forces the two descriptions to use the same identifiers, the same price basis or the same level of the product tree, and Google has one documented rule that turns any mismatch into a reporting failure rather than a rounding difference. This is the agreement checklist: what to compare, where each value is decided, and the one test order that answers all of it.

Key Takeaways

  • Google's cart data documentation is explicit: "Item IDs passed in the items array of your conversion tag must exactly match the id attribute in your Merchant Center feed" [1].
  • Cart Data for Google Ads is a PRO feature of the GA4 extension, configured with Enable Cart Data, Feed Country in CLDR territory codes and Feed Language in ISO 639-1 [6].
  • On the analytics side, two settings decide what your item identifier is: Product identifier [ SKU / ID ] and Child vs Parent. Both govern the dataLayer and the Measurement Protocol payloads [6].
  • Nothing in either configuration forces the two to agree. Agreement is a configuration you maintain, not a sync that happens.
  • Merchant Center IDs carry history: "If you change the ID, you'll overwrite your product and its history" [2]. Changing identity settings on either side breaks continuity on both reporting surfaces at once.
  • Price has three separate axes to align: tax treatment, currency scope, and sale price mapping. GA4's own item spec requires currency in ISO 4217 whenever value is present [5].
  • Where the documentation is silent about what your feed's id column holds, open the generated file under pub/media/weltpixel-feeds and read it rather than assuming a default [7].

The rule that makes this concrete

Most articles about data consistency argue from tidiness. This one has a documented requirement behind it.

Google Ads conversions with cart data give you item-level revenue, profit and cart-size reporting from your ad conversions. The precondition is a matching rule, stated in Google's documentation without qualification: "Item IDs passed in the items array of your conversion tag must exactly match the id attribute in your Merchant Center feed" [1]. Google also processes only sales of items from a Merchant Center account linked to the Google Ads account [1].

The GA4 extension ships this feature on the PRO tier as Cart Data for Google Ads, with three settings: Enable Cart Data, Feed Country using CLDR territory codes, and Feed Language using ISO 639-1 codes [6]. It arrived in v1.12.15 on December 14, 2023, alongside a Google Merchant Center integration that switches on with the cart data configuration [6].

So on a Magento 2 store running both the feed module and the analytics module, identifier agreement is not housekeeping advice. It is the documented condition for a feature you are already paying for.

Identifier parity: what each side is actually sending

Start here, because every other mismatch is easier to see once the identifiers line up.

The analytics side is decided by two settings. Product identifier [ SKU / ID ] chooses whether the product ID or the SKU goes to Google Analytics as the item identifier, and Child vs Parent chooses whether cart, checkout and success page events carry the child or the parent identifier [6]. Those two settings govern the browser dataLayer and the Measurement Protocol payloads together. There is no separate server-side identifier setting to get out of step with the client one.

The feed side is decided by attribute mapping. The feed module pre-configures attributes with their Magento equivalents, and you can remap, add or remove them, with removal blocked for attributes Google marks as required [7]. What the id column ends up containing depends on that mapping in your store.

Which is why the safe instruction is an observation rather than a rule of thumb: open the generated feed file under pub/media/weltpixel-feeds and read the id column. Two minutes of looking beats an assumption about defaults, and defaults are exactly the kind of thing that changed at some point in your store's history without anyone writing it down.

Google's own id specification is worth reading in full before you change anything, because it constrains both sides [2]:

  • Submit a unique ID for each different product, and use SKUs as IDs where possible.
  • Use a stable ID. Once assigned, do not change it. Changing it overwrites the product and its history.
  • Do not reuse or recycle an ID for a different product.
  • IDs are 1 to 50 characters, and two IDs that differ only by casing may be interpreted as the same product.

That history clause is the one merchants underestimate. A re-SKU project, or a flip of the Product identifier setting, severs continuity in Merchant Center and in GA4 item reports at the same time. Change identity deliberately, once, with a date you can point at later.

Price parity has three axes, not one

Prices can disagree in three independent ways, and each has its own home.

Axis Feed side GA4 side
Tax Price must match the landing page and checkout pages [3] Exclude Tax From Product Prices, Exclude Tax From Transaction, Exclude Shipping From Transaction [6]
Currency The currency of the target country, in ISO 4217 [3] Currency And Amount Scope, base or display currency [6]
Sale price Sale Price mapped from Magento's Special Price, plus any custom feed pricing rules [7] Whatever the storefront actually charges, as computed for the event

Google's price specification asks you to "submit an amount and currency that match the price on your landing page and the checkout pages", and states the consequence for getting it wrong: products are disapproved and you are told in your Merchant Center account [3]. GA4's item spec is looser but not silent: price is the monetary unit price of the item in the units of the specified currency parameter, quantity defaults to 1, and currency is required in ISO 4217 whenever a value is present [5].

The currency row is the one that produces a quiet, permanent drift. A store selling in several display currencies with GA4 configured on base currency, feeding Merchant Center in the target country's currency, will report two different per-item revenue figures forever, both of them internally consistent. Nothing errors. The totals just never agree.

Feed pricing rules deserve the same care. The feed module supports custom pricing rules and modifications [7], which is a legitimate merchandising tool and also a way to make the feed disagree with the storefront on purpose. Know what you changed, and check it against the landing page requirement above.

Variant parity, and why totals can agree while reports do not

This is the mismatch that survives every revenue reconciliation, because revenue is not where it shows.

The feed module supports configurable, simple and grouped products, generating per-variant entries with their own identifiers, and v1.16.0 improved how simple child products are inserted into the generated feed, including image and category inheritance from the configurable parent [7]. So a feed is commonly built at child granularity.

If the GA4 side is set to Parent, your analytics describes the catalog one level up from your feed. Order totals still match, because the money is the same. Item reports do not join: Shopping's item-level reporting is keyed to child IDs while GA4's item reports aggregate at parent, and cart data matching fails the exact-match rule from the first section [1].

Worth checking on the same pass: v1.17.4, released September 1, 2026, fixed an issue where zero-priced configurable child items were duplicated in the server-side purchase and add_payment_info events, inflating item counts [6]. If you audited item counts before that release and found them high, re-run the comparison on a current version before treating it as a configuration problem. Our article on what old dataLayer setups still get wrong covers the wider class of wrong item data on migrated stores.

Google edits your data whether you ask or not

There is a third voice in this agreement, and it belongs to Google.

Merchant Center automations can update the price, sale price, availability and condition attributes using structured data markup that Google's crawlers find on your website and Google's own data extractors, with the stated purpose of avoiding price, availability and condition mismatches [4]. With those automations disabled, mismatched products are subject to item-level disapprovals instead [4].

Read that carefully in the Magento context. Your on-page structured data is now part of the agreement. A store whose feed says one price, whose checkout charges another, and whose product markup says a third has given Google a vote in which number wins. The GA4 payload, computed from the actual order, is the one description in the set that reflects what the customer paid.

The test that settles it

One configurable product, one test order, four comparisons.

  1. Pick a configurable product with at least two variants and a current sale price.
  2. Open the generated feed under pub/media/weltpixel-feeds, or download it from the module's Manage Feeds grid, and note the id, price, and whether rows exist per variant [7].
  3. Place a test order for one variant and capture the purchase event's items array in DebugView or the dataLayer preview, with the order grid as confirmation that the event was sent, all covered in our guide to verifying GA4 events on Magento 2.
  4. Compare four fields: identifier, price, currency, and the level of the tree each side used.
Comparison Passes when
Identifier Feed id and GA4 item_id are the same string, including casing [1][2]
Price Both match what the landing page and checkout show, tax treatment included [3]
Currency Feed uses the target country's currency; GA4's scope setting produces the same one [3][6]
Granularity Both describe the same level, child or parent, for the same order [1]

Any row that fails names the setting to change, and the change belongs on one side only. Deciding which side is correct is a merchandising question, not a technical one: the feed answers to Google Shopping's requirements, and the analytics layer answers to how you want to read your own reports.

If the totals rather than the items are what disagree, that is a different investigation, and it lives in our article on GA4 and Magento sales reports that do not match.

FAQ

Does the feed module set my GA4 item IDs, or the other way around?

Neither. The two modules are configured independently, and nothing in either configuration forces the two to agree. The feed's id comes from its attribute mapping [7]; the GA4 item identifier comes from Product identifier [ SKU / ID ] and Child vs Parent [6]. Agreement is something you set and then verify.

What happens if the IDs do not match?

Google Ads cart data reporting fails its documented matching condition [1], so the item-level revenue and cart-size insights it provides do not populate for those items. GA4 keeps recording the purchase and its revenue, which is why this failure is easy to miss.

Should my feed be built per variant or per parent product?

Per variant is the common choice, and the feed module generates per-variant rows with their own ids; read your generated feed to confirm which identifier each row carries [7]. What matters for this article is that the GA4 side then sends child identifiers too. A mismatched pair is worse than either choice made consistently.

Can I change the product identifier setting to fix a mismatch?

You can, once, with your eyes open. Merchant Center IDs are history-bearing, and changing an ID overwrites the product and its history [2]. Expect a discontinuity in Shopping reporting and in GA4 item reports on the same date, and record that date somewhere you will find it in six months.

Is any of this specific to Magento?

The identifier and currency scope controls are. Product identifier [ SKU / ID ], Child vs Parent and Currency And Amount Scope are extension settings with no equivalent on a hosted platform that syncs its own catalog to Google. On Magento 2 you own both sides of the agreement, which is the cost and the point. The server-side tracking setup guide shows where these item settings sit in the wider configuration.

Cart Data for Google Ads and the base-vs-display currency scope are PRO features of the extension; the identifier controls (Product identifier, Child vs Parent) ship in the standard tier. Both sit in the Magento 2 Google Analytics 4 extension, currently v1.17.4, released September 1, 2026.

Run the test order on a configurable product rather than a simple one. Simple products agree by accident, and the disagreement you are looking for only exists where the tree has two levels.

Sources

  1. About conversions with cart data, Google Ads Help, retrieved September 7, 2026, https://support.google.com/google-ads/answer/9028254
  2. id [id] product data specification, Google Merchant Center Help, retrieved September 7, 2026, https://support.google.com/merchants/answer/6324405
  3. price [price] product data specification, Google Merchant Center Help, retrieved September 7, 2026, https://support.google.com/merchants/answer/6324371
  4. Allow Merchant Center to update product information automatically, Google Merchant Center Help, retrieved September 7, 2026, https://support.google.com/merchants/answer/3246284
  5. Recommended events, Google Analytics for Developers, retrieved September 7, 2026, https://developers.google.com/analytics/devguides/collection/ga4/reference/events
  6. WeltPixel Google Analytics 4 User Guide, v1.17.4, September 1, 2026, https://docs.weltpixel.com/GA4/User-Guide-WeltPixel-Google-Analytics-4.html
  7. WeltPixel Product Feed User Guide, v1.17.0, May 18, 2026, https://docs.weltpixel.com/ProductFeed/User-Guide-WeltPixel-Product-Feed.html

Ready to upgrade your tracking?

Server-side tracking for Magento and Shopify — accurate data, better attribution, full privacy compliance.