Skip to main content
← BlogGOOGLE ADS11 MIN READ

Google Shopping Conversion Tracking: Merchant Center, Cart Data and Profit Bidding

Your feed and your conversion tag must agree: feed-matching item IDs, cart data, and COGS turn Shopping tracking into per-product profit reporting.

Ariful IslamAriful IslamFounder · computer engineer ·
inX
ACCURACY = REPORTED ÷ REALILLUSTRATIVE · 30 DAYS
Your store100%
GA482%
Meta68%
Google Ads91%
95%+ healthy85–95 leaking<85 broken

Most Shopping accounts I audit have conversion tracking that looks fine at the campaign level and is quietly broken at the product level. The campaign shows purchases. ROAS looks plausible. Then you open a per-product report and half your catalog shows zero conversions, because the item IDs your purchase event sends don't match the IDs in your feed. Google never warns you about this. It just stops connecting the dots.

Why does Google Shopping tracking run on two separate data systems?

Because Shopping and Performance Max retail campaigns are built on a product feed, not keywords, your tracking has two halves: Merchant Center knows what you sell, and conversion tracking knows what people bought. Merchant Center holds the feed — item IDs, titles, prices, currency, availability. The Google Ads conversion tag (or GA4 purchase event feeding an imported conversion) reports what happened after the click.

The two systems meet at exactly one point: the item ID. When a purchase event carries an items array, Google tries to match each item's id against the id column in your feed. Match, and you get product-level conversion data, cart reports, and profit metrics. No match, and the conversion still counts at the account level — which is why nobody notices — but every per-product view is running on incomplete data. Your bidding is too, since PMax allocates budget across products based on what it thinks each one converts.

Flow showing a site sending parent product IDs while the feed holds variant IDs, the join failing silently, per-product reports going dark, and the fix of sending the feed id.
The conversion still counts at account level, which is exactly why nobody notices the product-level data is gone.
  1. Site sends parent ID — Theme or app pushes SKU or product handle
  2. Feed holds variant ID — shopify_US_{productId}_{variantId}
  3. Join fails silently — Conversion still counts at account level
  4. Product data goes dark — PMax allocates budget on incomplete data
  5. Send the exact feed id — Test the items array against Merchant Center

Why should purchase events carry an items array with feed-matching IDs?

Because without item-level data, Google can only credit the product that was clicked — it has no idea what was actually in the order. Someone clicks your $12 phone case ad and buys a $900 phone. Click-based attribution sees a $912 conversion on the phone case. With an items array, Google sees the real basket.

Here's what a purchase should look like in the dataLayer:

dataLayer.push({
  event: "purchase",
  ecommerce: {
    transaction_id: "1042",
    value: 912.00,
    currency: "USD",
    items: [
      { item_id: "shopify_US_7351_41022", price: 12.00, quantity: 1 },
      { item_id: "shopify_US_8110_43987", price: 900.00, quantity: 1 }
    ]
  }
});

The item_id values are the whole game. They must be character-for-character identical to the id in Merchant Center. On Shopify, the Google channel feed typically submits IDs in the shopify_US_{productId}_{variantId} format — variant-level. Meanwhile plenty of themes and tracking apps push the SKU, or the bare product ID, or the parent product's handle into the dataLayer. Every one of those mismatches breaks the join silently.

Two-column comparison of a conversion without an items array, where a $12 phone case absorbs a $912 sale, against feed-matched items enabling cart reports and per-product profit.
Cart data only works if the items array, feed country, feed language and currency all match the feed you are running.
Without an items arrayWith feed-matched items
Google credits the clicked productGoogle sees the real basket
$12 phone case shows a $912 saleRevenue lands on the phone that sold
No units sold, no cross-sell viewCart reports and cross-sell revenue
No profit math possibleGross profit once cogs is in the feed

What does adding cart data to conversions actually get you?

Conversions with cart data tells Google Ads exactly which feed items were sold, at what price and quantity, so it can report products sold (not just products clicked), cross-sell revenue, and — once you add cost of goods to your feed — gross profit per product. You enable it by adding a few parameters to your Google Ads purchase conversion:

{
  merchant_id: "123456789",       // your Merchant Center ID
  aw_feed_country: "US",
  aw_feed_language: "EN",
  discount: 10.00,                 // order-level discount
  items: [
    { id: "shopify_US_7351_41022", price: 12.00, quantity: 1 }
  ]
}

Then add the cost_of_goods_sold [cogs] attribute to your Merchant Center feed. Now Google can compute revenue minus COGS for every order it tracked, and your reports gain columns most advertisers never see: gross profit, margin, units sold per product. That's profit bidding's foundation — you stop scaling products with impressive revenue at terrible margins and find the quiet ones where a mediocre ROAS is your most profitable spend.

The catch: cart data only works if the items array, feed country, feed language, and currency all match the feed you're actually running.

What do new-customer acquisition goals need from your tracking?

New-customer acquisition goals in Performance Max let you bid higher for new customers (or only for new customers), but they're only as good as Google's ability to tell new buyers from returning ones. That classification runs on data you supply: Customer Match lists of your existing buyers (hashed emails and phone numbers), the new-customer value you define, and optionally a flag your tracking sends marking a purchase as new-versus-returning.

This is where thin browser-only tracking hurts twice. If your purchase events are missing customer identifiers, Google can't reliably match buyers against your lists, so returning customers get counted — and bid for — as new. You end up paying an acquisition premium to re-acquire people who bought last month. Your order system already knows exactly who's new. The tracking just has to carry that knowledge to Google.

What are the classic ways Google Shopping conversion tracking breaks?

Four failures come up over and over in audits, and each one distorts a different number:

FailureWhat you seeThe fix
Feed vs. conversion currency or value mismatchROAS wildly off; profit math meaninglessOne currency end to end; decide once whether value includes tax and shipping, and match the feed's price basis
Item IDs differ (variant vs. parent, SKU vs. feed ID)Per-product reports show zero or partial conversionsSend the exact feed id in the items array; test against Merchant Center
Free listings vs. paid attribution confusionGA4 and Google Ads "don't match" for ShoppingFree product listing clicks don't get Ads conversion credit; compare like with like
Duplicate purchasesInflated conversions, especially on branded PLAsDeduplicate on transaction_id; stop the tag re-firing on thank-you page reloads

The duplicate problem deserves a second look because of where it lands. A customer completes checkout, then refreshes the order confirmation page, or returns to it from an email a day later. If your purchase tag fires again and nothing deduplicates it, that's two conversions from one order. And because branded product ads sit last in the path so often, the inflation concentrates in your branded Shopping campaigns — exactly where a flattering ROAS convinces you to shift budget toward traffic you were getting anyway.

Currency is sneakier. Merchant Center has rules about price basis — US feed prices exclude sales tax; most EU feed prices include VAT. If your conversion value uses a different basis than your feed, or a multi-currency store sends the shopper's display currency while the feed runs in another, every profit and ROAS figure downstream inherits the error.

Stack diagram: a Shopify order-created webhook, browser purchase event and customer identifiers feed a tagging server that builds the purchase and deduplicates on transaction_id.
The webhook payload carries the same variant IDs the feed is generated from, so item IDs match by construction.
LayerWhat sits there
InputsShopify order-created webhook, Browser purchase event, Customer email and phone
track.yourstore.comBuilds the purchase from the order payload and deduplicates on transaction_id
DestinationsGoogle Ads with cart data, GA4, Meta CAPI

Why does first-party server-side tracking fix all of this at once?

Because every failure above traces back to the same root: the browser is a bad witness to what happened in an order. Server-side tracking means your conversion data comes from a server you control — your own tagging server, running Google Tag Manager on a subdomain of your store — instead of relying only on a script in the shopper's browser. Plain terms: today, your numbers depend on a fragile piece of JavaScript firing on a thank-you page. Ad blockers stop it. Safari's tracking prevention limits its cookies. A slow page kills it. That's real purchases going unrecorded, and Smart Bidding optimizing on a partial picture.

For Shopping specifically, the server-side version has one benefit that beats everything else: the purchase event is built from the order webhook. When Shopify or WooCommerce fires its order-created webhook, that payload contains the exact line items — the same variant IDs, prices, and quantities the feed is generated from. No dataLayer to drift out of sync with the feed, no theme update silently swapping variant IDs for SKUs. Feed-accurate item IDs, guaranteed by construction, every order.

The rest follows. One server source of truth deduplicates on the order ID, so refresh-driven duplicate purchases and inflated branded ROAS disappear. Purchases blocked in the browser still arrive, because the webhook fires whether or not the shopper's browser cooperated. Customer identifiers ride along for new-customer classification and Enhanced Conversions. And it all runs as first-party data on your own subdomain, with you deciding what's shared per the visitor's consent — which is how you stay compliant without going blind.

Frequently asked questions

How do I know if my item IDs match my Merchant Center feed?

Place a test order, capture the purchase event in GTM preview or the browser's network tab, and compare each item ID against the id column in Merchant Center's product list. They must match character for character, including any prefix like shopify_US_.

Should my conversion value include shipping and tax?

Pick one basis and stay consistent, and match it to your feed's price basis — US feed prices exclude sales tax, most EU feed prices include VAT. Mixing bases is one of the most common causes of distorted ROAS and profit numbers.

Why does Google Ads show more Shopping conversions than GA4?

They attribute differently: Google Ads credits its own ad clicks, while GA4 models credit across all channels. Some gap is normal; a large one usually means duplicates or a broken event on one side.

Do free listings get conversion credit in Google Ads?

No. Clicks on free product listings don't spend budget and don't receive Google Ads conversion credit, so comparing total Shopping revenue in analytics against paid-campaign conversions will always look mismatched.

What is conversions with cart data?

It's a Google Ads feature where your purchase conversion also sends the Merchant Center ID, feed country and language, and the sold items with price and quantity. It enables cart reports, cross-sell insight, and — with cost of goods in your feed — per-product profit reporting.

Do I need server-side tracking for Google Shopping?

If you're spending real money on Shopping or Performance Max, yes. Browser-only tags lose orders to ad blockers and privacy features; a server-side setup built on order webhooks reports every order with feed-accurate item IDs.

Why is ROAS on my branded Shopping campaign so high?

Partly because branded clicks sit last in the purchase path and absorb credit, and often because duplicate purchase events inflate it further. Deduplicate on transaction ID before you trust that number enough to shift budget toward it.

  • google shopping
  • merchant center
  • ecommerce

How accurate is your conversion tracking?

PLATFORM-REPORTEDconversionsdivided byBACKENDreal orders or leadsequalsaccuracy
TRY IT · YOUR NUMBERS
68%Broken. Something is missing entirely. Worth a free audit.
Reading guides because something is broken?Book 30 minutes with Ariful. We'll find it on the call and send a written fix list within 24 hours.
Get my free audit →
Ariful Islam
WRITTEN BYAriful IslamFounder of Tracking Consulting and a computer engineer (Diploma, BSc, MSc in CSE). 300+ clients and 1,000+ tracking projects since 2019.
About Ariful →
FREE · 30-MIN CALL · WRITTEN AUDIT IN 24H

Want us to check your accuracy for you?

We look at your setup together on the call. Within 24 hours you get a written audit and a prioritized fix list you can hand to any developer. Not a fit? We'll say so.