Shopify SEO. Measurement
Shopify GA4 Audit: Prove the Funnel Works Before You Judge SEO
Written by Ram Kr Shukla, SEO and growth consultant, Google Analytics certified.
Quick answer
If your Shopify GA4 tracking isn’t working, one test proves it fast. Pull view_item, add_to_cart, begin_checkout and purchase for the same 28 days, as event counts and as users. Each step must be larger than the next. If add_to_cart comes in below purchase, the funnel’s broken, whatever a one day screenshot says. Then check which measurement IDs receive which events, whether collection pages send item_list_name and item_list_id, and how much of your traffic is bots. Until all four checks pass, judge SEO on Search Console clicks and GA4 landing page sessions.
Here’s the number that ended an argument. Over four weeks, an Indian cosmetics store I audited recorded 107 add_to_cart events in GA4. Over the same four weeks it recorded 1,587 purchases.
You can’t buy more things than you put in a cart. Not fifteen times more.
The store’s tech team pushed back anyway. They sent a screenshot with add_to_cart at 31 and said tracking was fine. Their screenshot covered a day or two. My numbers covered 28 days, with view_item, add_to_cart, begin_checkout and purchase side by side. Once everyone looked at the same window, there wasn’t anything left to debate, and the fix shipped.
This is the audit I now run on any store before I use its GA4 data to judge SEO. It sits inside my Shopify SEO work, and it’s deliberately hands on: eight checks, what each looks like when it fails, and what to measure SEO on while it’s broken. If you want the reporting layer that sits on top of clean data, read what a real Shopify SEO report contains and how to read an e-commerce SEO report without being fooled. This post is about whether the numbers underneath are true.
Why SEO Gets Judged on Broken Data
Most SEO verdicts on a Shopify store lean on GA4 somewhere. Did the new collection copy lift cart adds? Did the blog help any orders? Does organic convert better than paid? Every one of those questions assumes the events fire, land in the property you’re reading, and carry the parameters that say where they came from.
On the store above, none of that held at the start. view_item recorded 901 events from 170 users in four weeks. That’s on a store doing thousands of orders a month. Any page level conclusion drawn from that window would’ve been fiction, and some had already been drawn.
GA4 doesn’t warn you. Reports load, charts look normal, and purchases look plausible. On this store checkout ran through a third party checkout app whose events fired correctly the whole time, so the bottom of the funnel looked healthy while the top was nearly empty. Nobody noticed until someone tried to credit a page.
Already suspicious of your organic numbers for other reasons, like untagged paid traffic or parameters rewriting the source? That’s a separate problem, covered in why your organic traffic numbers are lying to you. This audit checks the ecommerce events themselves.
What Shopify’s Google & YouTube App Should Be Sending
You can’t call something missing until you know what should be there. If GA4 is connected through Shopify’s Google & YouTube app, Google’s reference for the app’s event parameters lists these events, mapped from Shopify’s own standard customer events such as product_viewed, product_added_to_cart and checkout_completed.
| GA4 event | What it records | Funnel role |
|---|---|---|
| page_view | Any page view | Traffic |
| view_item_list | A collection page view | Discovery |
| view_item | A product page view | Step 1 of the test |
| add_to_cart | A product added to the cart | Step 2 of the test |
| remove_from_cart | A product removed from the cart | Context |
| view_cart | A cart page view | Context |
| begin_checkout | Checkout started | Step 3 of the test |
| add_shipping_info | Shipping or address details entered | Checkout progress |
| add_payment_info | Payment details entered | Checkout progress |
| purchase | Order completed | Step 4 of the test |
| search | A storefront search | Context |
Event list from Google’s Shopify event parameter reference. The funnel role column is how this audit uses each one.
Three details on that page matter for the audit.
- Some events are newer than your history. Google’s Shopify setup help page says the app now sends view_item_list, remove_from_cart, view_cart and add_shipping_info, and adds new data to five events it already collected. A gap in older months might just be the period before those events existed.
- Every event carries a shopify_event_name parameter. Google suggests using it to filter the newer event data out of reports if you need to. It’s also handy for telling app events apart from ones a theme script or GTM sends with the same GA4 name.
- select_item isn’t on the list. In Google’s ecommerce measurement guide, select_item is the click from a list to a product, and item_list_id and item_list_name ride on the items in select_item and add_to_cart. If the app doesn’t send select_item, that link has to come from a custom pixel or GTM.
Two platform rules also explain a lot of “it worked in the old theme” complaints. Shopify runs app pixels and custom pixels in a sandbox that can’t pick up events by scraping the page, and in markets that need consent, pixels run only after the visitor grants it (see Shopify’s pixels overview). Separately, on the store I audited, the add to cart buttons inside blog product blocks sat in a shadow DOM. A GTM click trigger built on a CSS selector would never have seen them.
The One Line Test: Every Step Bigger Than the Next
Here’s the whole test. Over the same 28 days, view_item has to be larger than add_to_cart, which has to be larger than begin_checkout, which has to be larger than purchase. Check it twice: once on event count, once on users. The free GA4 funnel checker runs this test on your own numbers, right in your browser.
Here’s how that store looked in two consecutive four week windows.
| Event | Broken window | After the fix |
|---|---|---|
| view_item | 901 (170 users) | 413,745 (69,609 users) |
| add_to_cart | 107 (56 users) | 71,762 (24,539 users) |
| begin_checkout | 3,991 | 22,656 (15,479 users) |
| purchase | 1,587 | about 7,200 |
Event counts, with total users where captured. Anonymised client data.
In the broken window, three things fail at once. add_to_cart is about 15 times below purchase. begin_checkout is about 37 times above add_to_cart. And 170 users viewing products can’t produce 1,587 orders.
After the fix, the order holds. Roughly 17% of product view events led to a cart add event, 32% of cart adds to a checkout, and 32% of checkouts to a purchase. I wouldn’t treat those ratios as a benchmark for your store, because price point, traffic mix and buy it now buttons all move them. The test is about order, not size.
Why the one day screenshot lost the argument
The tech team’s screenshot wasn’t faked. add_to_cart really did show 31 on the day they picked. It still proved nothing, for three reasons.
- The window was too short. A day or two of data swings with campaigns, sales and weekends. A tag that fires for one shopper in twenty still produces a non zero number on any given day.
- It showed one event alone. 31 cart adds means nothing until you see purchases for the same day next to it.
- It didn’t match the window being discussed. My 107 covered 28 days. You can’t rebut a 28 day number with a one day number.
So the rule I give every client now: never send one event in isolation. Always send all four funnel events together, last 28 days, events and users. It turns a debate into a reading.
The legitimate exceptions, and their limits
A funnel can bend for real reasons. Shopify’s dynamic checkout buttons let shoppers skip the cart and go straight to checkout, so on a store where most buyers tap Buy it now, begin_checkout can sit close to add_to_cart or even above it. Checkout links in emails or ads skip the product page too.
Those explain a narrow gap. They don’t explain purchase at fifteen times add_to_cart on a store where the cart is the main path. If you suspect the buy now path, put a test order through it in DebugView and see which events it fires. Then you’ll know how much of the gap it can account for.
The opposite failure matters too. A step that’s suspiciously high, like purchase above begin_checkout or page_view doubling overnight, usually means two tags counting the same action. Google warns that a single action can be counted more than once when several Google tags are set up, or when tracking existed before the Google & YouTube app went in.
How to Audit Shopify GA4, Step by Step
Run these in order. Each one depends on the window and the property you fixed in the steps before it.
For step 2, a funnel exploration set to an open funnel gives you the same four steps as a chart, but the plain event table is quicker to screenshot and harder to argue with. For step 8, Google’s DebugView guide covers turning on debug mode through Tag Assistant.
Two Measurement IDs, Two Different Funnels
Steps 4 and 5 found the second big problem on that store. Its collection pages carried two GA4 measurement IDs. Blog pages carried a third. Inside the store’s Google pixel settings, events were mapped to IDs one by one, and the mapping wasn’t the same for every event.
| Event | ID A | ID B |
|---|---|---|
| page_view | Yes | Yes |
| add_to_cart | Yes | Yes |
| add_payment_info | Yes | Yes |
| view_item_list | Yes | No |
| view_cart | Yes | No |
| add_shipping_info | Yes | No |
Read from the store’s pixel settings. Real IDs replaced with letters.
Think about what that does to a report. If the property you read is fed by ID B, collection page product impressions never arrive, while cart adds from those same pages do. Collections look like they sell without ever being seen. Any SEO conclusion about collection pages from that property is built on a hole.
One pattern worth checking on your own store: view_item_list, view_cart and add_shipping_info are three of the four events Google lists as newer additions to the app. When events get added later, it’s easy for them to be mapped to one destination and not the other. That’s a hypothesis to test in step 5, and I haven’t proven it’s why this store split.
The fix is mostly a decision. Pick the property you report from and send every ecommerce event to its measurement ID. A second ID can stay if someone can say who reads it and why. Write that down, because the next agency or developer will add a third.
Item List Parameters: Why Collection Pages Can’t Get Credit
This is the check most audits skip, and it’s the one that decides whether collection SEO can ever be proven in GA4.
Three pieces work together. view_item_list says a list of products was seen. item_list_name and item_list_id say which list it was. select_item says which product the shopper clicked from that list. When the list name also travels on the items in add_to_cart and purchase, GA4 can tell you which collection, search page or blog block a cart add came from.
On the store I audited, item_list_name, item_list_id and select_item appeared zero times on collection pages. Zero on blog pages too, which had 66 links to product pages on a single post and fired nothing but page_view. So a cart add that started on a complexion product collection looked exactly like one that started on the homepage. Even where view_item_list did land, the list was unnamed.
Google doesn’t join this up for you after the fact. For promotions, its ecommerce setup guide says that to measure a purchase after someone views or clicks a promotion, you add the promotion ID or name to every later ecommerce event. In practice I treat item lists the same way: the list name has to be on the item when the cart add and the purchase fire, or there’s nothing to group by.
What I ask a developer for, in priority order:
- Fire view_item_list on every collection page and on every blog product block, with item_list_id and item_list_name set. Something like
blog_[slug]andBlog: [title]for blog blocks keeps them readable. - Fire select_item when a product in a list is clicked, carrying the same list fields.
- Carry the list fields onto the items in add_to_cart.
- Persist the list onto the cart line, through line item properties or cart attributes, so the purchase items can carry it too. If checkout runs through a third party app, confirm what survives the handoff before promising list level revenue.
Until that ships, measure collection SEO on Search Console clicks and position, plus GA4 landing page sessions for collection URLs. That’s a real limit, because collections are usually where the money is. On the fashion store in my Shopify SEO case study, collection pages drove more than 70% of organic revenue. For what makes those pages rank in the first place, see Shopify collection page SEO, and for one collection type with its own tracking quirks, influencer and creator collection pages.
Bot Traffic: 1,261 Sessions, 13 of Them Engaged
GA4 already removes traffic from known bots and spiders. You can’t switch that off, and you can’t see how much it removed. So whatever’s in your reports got past that filter, and on a Shopify blog a lot gets past it.
Here’s the blog landing page traffic on the same store, split by country.
| Country | Sessions | Engaged | Avg. time | Orders |
|---|---|---|---|---|
| United States | 5,887 | 1.7% | 3.9 sec | 0 |
| India (home) | 871 | 33% | 89 sec | 4 |
Blog landing page sessions. Smaller rows from Singapore, Brazil, Vietnam, Argentina and Romania followed the US pattern, at under 4 seconds each. The full country breakdown, and what GA4 can and cannot filter, is in bot traffic in GA4.
An Indian cosmetics store with almost seven times more US blog sessions than Indian ones, at under four seconds each. Those aren’t shoppers. India was the only segment behaving like people, and its blog conversion rate worked out to about 0.46%, which is an ordinary blog number. Google defines an engaged session as one that lasts longer than 10 seconds, has a key event, or has two or more page views, so a 1.7% engagement rate means 98 sessions in 100 did none of those.
It also wrecks prioritisation. The blog post with the most sessions, 1,261, had 13 engaged sessions at 4.6 seconds. Another post with 233 sessions had 92 engaged sessions at 57 seconds. Rank by sessions and you’d invest in the wrong one. Rank by engaged sessions and the second post wins by a factor of seven.
So for step 7: filter every report to the countries you sell to, and rank pages on engaged sessions. Don’t rank on total sessions at all. If you’re deciding how much to spend on the blog against category pages, blog traffic vs category traffic covers that trade off.
The SEO Metrics to Use While GA4 Is Broken
Some of this takes weeks to fix, and some of it, like query level revenue, can’t be fixed by anyone. You still need to judge SEO in the meantime. These are the numbers I use, in order.
1. Search Console clicks, impressions and position, split brand and non-brand
Search Console doesn’t depend on your tags at all. It’s the cleanest SEO number you have. Split it by brand and non-brand, because brand clicks mostly measure demand that already existed.
| Segment | Impressions | Clicks | CTR | Avg. position |
|---|---|---|---|---|
| Non-brand | 225,897 | 2,553 | 1.13% | 7.14 |
| Brand | 22,642 | 2,509 | 11.08% | 4.97 |
Home market only, four weeks. Anonymised client data.
Non-brand pulled ten times the impressions of brand for about the same clicks, at a tenth of the CTR and two positions lower. That gap is the SEO opportunity, and it’s visible without a single GA4 event.
One thing confuses people: brand plus non-brand came to 5,062 clicks against 7,173 for the whole site in the same market. Nothing’s broken. Search Console leaves anonymised queries out of query tables, and drops them entirely once you filter by query, so query rows always sum short of the site total. Quote the split as a ratio. More on why the split matters in branded vs non-branded traffic.
2. GA4 landing page sessions and orders, organic only
Landing page sessions survive most event breakage, because they come from page_view and the session’s source. Filter to Organic Search and your home market, then read sessions and transactions by landing page. Pages that only rank for non-brand terms, like blog posts and most collections, are the closest honest proxy for non-brand SEO value.
3. Channel level orders, labelled as such
On that store, Paid Social was about 75% of home market sessions and 58% of orders. Organic Search was about 3.5% of sessions and 6.4% of orders, with a 4.72% conversion rate against 1.94% for Paid Social. That’s a good organic story. It only stays good if nobody puts Search Console clicks next to all channel GA4 orders on one unlabelled row of scorecards, where every order looks like an SEO result.
What you can’t measure, in any tool
Non-brand revenue. Search Console has the query. GA4 has the session and the order. There’s no key that joins a query to a session, so nobody can tell you which orders came from non-brand searches. Anyone quoting a non-brand revenue figure is estimating, and you shouldn’t agree to a target framed that way.
And prefer transactions to revenue when item data is shaky. After the fix on that store, one product line still showed zero item revenue despite about 1,800 units purchased. Any revenue split by product understated that line. Transaction counts weren’t affected, so the dashboard reports counts.
After the Fix: What to Watch For
Don’t compare the first clean window to the broken one and call it growth. When upper funnel events come back, every period on period arrow in GA4 turns green for a few weeks, because the comparison period was missing data. Wait until both windows sit after the fix before you read a trend. The arithmetic for that date, and what to report until it arrives, is in why GA4 comparisons show fake growth after a tracking fix.
Re-run the order test every month. It’s a few minutes’ work, and it’s the fastest way to spot a theme update, a new app or a consent change that quietly broke a tag. If you’re also running crawls against the store to check templates, throttle them first, or Shopify will start refusing requests: see crawling Shopify without 429 errors.
If you’d rather have someone run this audit and write the developer brief, that’s part of my GA4 conversion tracking work.
Shopify GA4 Audit FAQ
Why is my Shopify GA4 tracking not working?
The usual causes are a second Google tag sending duplicate or partial events, events routed to a measurement ID your reports don’t read, a theme or GTM trigger that can’t see the add to cart button, and consent settings that stop pixels from running. Start with the order test: view_item, add_to_cart, begin_checkout and purchase over the same 28 days. The step that breaks the order tells you where to look.
Why is add_to_cart lower than purchase in GA4?
Because add_to_cart isn’t firing for most shoppers, or it’s going to a different measurement ID. Buy it now buttons that skip the cart can narrow the gap, but they can’t make purchases outnumber cart adds by a wide margin on a store where the cart is the main path. On one store I audited it was 107 cart adds against 1,587 purchases, and the cause was tracking.
Does the Shopify Google and YouTube app send view_item_list?
Yes. Google’s help page for the app lists view_item_list for collection views, along with view_cart, remove_from_cart and add_shipping_info, and its parameter reference shows item_list_id and item_list_name on view_item_list. It doesn’t list select_item, so the click from a list to a product isn’t covered by the app alone.
How do I check which GA4 measurement ID gets which event?
Connect Tag Assistant to your store, then view a collection, open a product, add to cart, view the cart and start checkout. Tag Assistant shows each hit and the destination it went to. Record the result as a grid of events against IDs, then confirm in GA4 Admin, Data streams which ID feeds the property you report from.
Why does Item list name show (not set) in GA4?
Because the events reaching your property don’t carry item_list_name on their items. Either the list events aren’t firing, they’re going to a different measurement ID, or they fire without the list parameters. Until that’s fixed, GA4 can’t tell you which collection or blog block a cart add came from.
How do I filter bot traffic out of Shopify GA4 reports?
GA4 already removes known bots and you can’t see how many it removed, so what’s left got past that filter. Break sessions down by country and look at engaged sessions and engagement time. Filter reports to the countries you actually sell to, and rank pages on engaged sessions instead of total sessions.
Can I measure non-brand SEO revenue in GA4?
No. Search Console has the query and GA4 has the session and the order, and there’s no key that joins a query to a session. Report non-brand clicks, impressions and position from Search Console, and organic orders from GA4, as two separate numbers. Landing pages that only rank for non-brand terms are the closest honest proxy.
How long after fixing tracking can I trust GA4 data?
Give it a full 28 days after the fix ships, then run the order test on that window alone. Any window that includes days before the fix mixes broken and working data, and period on period comparisons will show gains that are really just the tracking coming back.
Tags: Shopify SEOGA4Ecommerce TrackingSEO Reporting
Written by Ram Kr Shukla
SEO and growth consultant with 20+ years in the field across 50+ brands, working as a consultant or Fractional Chief Digital Officer. Google Analytics and Google Ads certified. Audits Shopify measurement before judging any SEO result, and works daily in GA4, Search Console and Looker Studio.




