TL;DR
GA4's recommended ecommerce event set runs from view_item_list through purchase and includes refund [1]. Shopify's Google channel covers the conversion-critical path reasonably well, but refund is not fired natively, which creates a gap in your purchase-to-refund funnel reporting. If you are running Smart Bidding or doing any attribution modeling, missing events or missing parameters are not cosmetic problems. They cause ROAS miscalculation and broken funnel visualization in GA4's purchase funnel report.
The Full GA4 Ecommerce Event Canon
Google defines the following recommended ecommerce events in order of a typical shopping journey [1][2]:
| Event | When it should fire | Shopify native? |
|---|---|---|
view_item_list |
Category / collection page renders | Yes [3] |
view_item |
Product detail page renders | Yes [3] |
select_item |
User clicks a product in a list | Yes [3] |
add_to_cart |
Item added to cart | Yes [3] |
remove_from_cart |
Item removed from cart | Not confirmed in Shopify docs |
view_cart |
Cart page or drawer viewed | Not confirmed in Shopify docs |
begin_checkout |
Checkout initiated | Yes [3] |
add_shipping_info |
Shipping step completed | Yes [3] |
add_payment_info |
Payment step completed | Yes [3] |
purchase |
Order confirmed | Yes [3] |
refund |
Order refunded | No [3] |
Everything in the "Not confirmed in Shopify docs" rows is based on Shopify's own documentation being silent on those events [3]. Not firing is the safe assumption when the docs are silent. The refund row is an explicit absence.
What Each Event Does, What Parameters It Expects, and What to Check
This section walks each event in funnel order. Each entry has three parts: what the event means, the required/recommended parameters per Google's spec [1], and the DebugView signal to verify.
view_item_list
Fires when a user sees a list of products, typically a collection page or a search results page.
Key parameters: item_list_id, item_list_name, items array (each item needs at minimum item_id, item_name, index, price).
Verify in DebugView: filter for view_item_list. Expand the event. Check that items is an array, not empty. Check that item_list_name matches the collection handle you are on.
view_item
Fires when a product detail page renders.
Key parameters: currency, value (the product price), items array with one entry containing item_id, item_name, price, quantity, and ideally item_brand, item_category.
Verify in DebugView: navigate to a product. The event should appear within 1-2 seconds of page load. If you see it duplicated (two view_item events for one page load), you have a double-fire issue, usually from a GTM tag running alongside the native channel pixel.
select_item
Fires when a user clicks a product card in a list.
Key parameters: item_list_id, item_list_name, items (single item with index).
This event is listed as confirmed in Shopify's documentation [3]. It is relatively low-value for conversion tracking but important if you want to measure click-through rate from collection pages to product pages inside GA4.
add_to_cart
Fires when a product is added to cart from any surface (PDP, quick-add, cart upsell).
Key parameters: currency, value, items array.
This is one of the most important events for funnel analysis and for creating audience segments in Google Ads. The value parameter should reflect the total value added (price multiplied by quantity), not a flat 1 [2].
Verify in DebugView: add a product with quantity 2. Check that value equals price * 2.
remove_from_cart
Shopify's documentation does not confirm this event fires via the native Google channel [3]. If you need it, it requires a custom implementation through Shopify's Customer events system or a GTM trigger on the remove button.
view_cart
Same situation as remove_from_cart. Not confirmed in Shopify's docs [3]. Some themes fire it via custom pixel snippets, but you cannot assume it is present without verifying.
begin_checkout
Fires when the user starts checkout (clicks "Proceed to checkout" or lands on the first checkout step).
Key parameters: currency, value, coupon, items array with full item details.
The coupon parameter is worth preserving here. If a user applies a discount code at checkout, you want that passed through to GA4 so you can segment conversion value by promotion.
add_shipping_info
Fires when the user completes the shipping step in checkout.
Key parameters: currency, value, coupon, shipping_tier, items.
shipping_tier should be the shipping method name (e.g., "Standard", "Express"). This lets you see in GA4 whether shipping method selection correlates with purchase completion.
add_payment_info
Fires when the user reaches the payment step.
Key parameters: currency, value, coupon, payment_type, items.
payment_type should be the payment method selected (e.g., "Credit Card", "Shop Pay", "PayPal"). This data is useful for identifying payment method abandonment rates.
purchase
Fires on the order confirmation page (Shopify's /thank_you page or the post-purchase page).
Key parameters: transaction_id, value, tax, shipping, currency, coupon, items.
transaction_id is the most critical parameter here. Without it, GA4 cannot deduplicate purchases. If a user refreshes the thank-you page, you get two purchase events with no way to collapse them into one order [2].
Verify in DebugView: complete a test order. Confirm transaction_id matches the Shopify order number.
refund
Not fired by Shopify's native Google channel [3]. If a customer requests a refund and you process it in Shopify admin, GA4 never hears about it. Your reported revenue stays higher than actual revenue, and any lifetime value calculation is wrong.
For a full implementation approach for refund events, see our article on tracking Shopify refunds in GA4.
What Shopify's Native Google Channel Actually Sends
The Shopify documentation confirms the events listed as "Yes" in the table above [3]. What it does not document in detail is the full parameter set for each event. That gap matters.
For example: purchase fires natively, but does it send shipping and tax as separate line items? Does it send item_category on the items array? Does it send item_variant? The Shopify docs are not explicit on every parameter.
Before you assume your GA4 data is complete, verify the parameter set in DebugView (steps below) or use GA4's Ecommerce Purchases report and check whether the "Item brand" and "Item category" dimensions are populated. If they show "(not set)", the parameters are not being sent.
If you are also using custom dimensions or custom metrics to extend your ecommerce data beyond GA4's defaults, the parameter coverage question matters even more. See our guide on GA4 custom dimensions and metrics on Shopify for how to register and capture those correctly.
Verify on Your Own Store
Step 1: Enable DebugView
In GA4, go to Admin (gear icon) → Data streams → your stream → Configure tag settings → Show all → Enable debug mode. Alternatively, install the GA4 DebugView Chrome extension and it handles the debug_mode parameter automatically.
Step 2: Trigger each event on your store Open your store in the same browser. Navigate to a collection page, click a product, add it to cart, proceed to checkout, and complete a test order using Shopify's Bogus Gateway (Settings → Payments → Test mode).
Step 3: Watch DebugView in real time In GA4, go to Admin → DebugView. You should see a timeline of events appearing on the left. Click each event to expand its parameters.
Step 4: Check the specific gaps For each event, confirm:
-
transaction_idis present onpurchase -
valueonadd_to_cartreflects quantity correctly -
itemsarray is not empty on any event -
item_idvalues match your Shopify product IDs or variant IDs (not "undefined")
Step 5: Check for remove_from_cart and view_cart
Remove an item from your cart. Watch DebugView. If no remove_from_cart event appears within 5 seconds, your store is not firing it. Same test for view_cart: visit your cart page and watch for the event.
Step 6: Test refund There is no automated test for refund because Shopify does not fire it. If you process a refund in Shopify Admin (Orders → select order → Refund), check DebugView. Nothing will appear. That is the gap.
Why Deduplication Matters More Than People Think
Every event in the canon above should fire once per user action. In practice, browser-only implementations fire duplicates when users refresh pages, when the checkout URL loads twice during Shop Pay redirects, or when GTM and the native pixel both run.
Deduplication works by matching event_id (a unique string you assign per event firing) between your browser pixel and your server-side event [2]. GA4 checks whether it has already received an event with that event_id for that session and drops the second one.
Without server-side forwarding, you have no deduplication. The native Shopify pixel fires browser-side only. If a user's browser blocks it (ad blockers, Safari ITP), the event is lost entirely. If the thank-you page reloads, you get a duplicate purchase.
Server-side forwarding solves both problems: it catches events that the browser dropped, and it sends the same event_id as the browser pixel so GA4 deduplicates cleanly.
Key Takeaways
- GA4 defines 11 recommended ecommerce events. Shopify's native Google channel fires 7 of them [3].
-
remove_from_cartandview_cartare not confirmed in Shopify's documentation [3]. Do not assume they fire without testing in DebugView. -
refundis explicitly absent from Shopify's native firing. Revenue reported in GA4 will not account for refunded orders unless you implement this separately. -
transaction_idon thepurchaseevent is not optional. It is how GA4 prevents duplicate revenue counting from thank-you page refreshes [2]. - The
valueparameter onadd_to_cartshould equalprice * quantity, not always 1. Verify this with a quantity-2 add-to-cart in DebugView. -
item_category,item_brand, anditem_variantare recommended parameters on theitemsarray but are not guaranteed to be populated by native Shopify tracking. Check your Ecommerce Purchases report for "(not set)" dimensions. - Browser-only tracking loses events to ad blockers and Safari ITP. Server-side forwarding with matching
event_idvalues is the fix for both data loss and duplication.
FAQ
Does Shopify's native Google channel fire all GA4 ecommerce events automatically?
No. Shopify's documentation confirms 7 of the 11 recommended events [3]. remove_from_cart and view_cart are not documented as firing natively. refund is explicitly absent. You need to verify the remainder in DebugView rather than assuming coverage.
What is the difference between begin_checkout and add_payment_info in GA4?
begin_checkout fires when the user initiates checkout (clicks "Proceed to checkout") [1]. add_payment_info fires when the user reaches and interacts with the payment step. The two events together let you see drop-off between those stages. A high rate of begin_checkout with low add_payment_info usually points to a shipping cost or address validation problem.
Why does GA4 show more purchases than Shopify's Orders report?
The most common cause is duplicate purchase events from thank-you page refreshes or multiple tracking sources firing without deduplication. GA4 only deduplicates if it receives the same event_id from two sources for the same session [2]. If your browser pixel fires without an event_id, every firing is treated as a new, unique event.
How do I track refunds in GA4 from Shopify?
Shopify does not fire a refund event natively [3]. The standard approach is to use Shopify's order webhook for refunds (the refunds/create webhook), capture the refund data server-side, and forward a refund event to GA4's Measurement Protocol with the original transaction_id. This is covered in detail in our refund tracking guide.
What parameters does GA4 require on the purchase event?
Google's spec marks currency and value as required for revenue reporting, and transaction_id as required for deduplication [1]. The items array is required for any product-level reporting. tax and shipping are recommended. Without tax and shipping, your GA4 revenue figure will match gross order value but you will not be able to break out net revenue inside GA4.
Track Every Event in the Canon, Server-Side
WeltPixel Conversion Tracking fires all GA4 recommended ecommerce events server-side from Shopify's order webhook on every plan (Explorer free with 100-order cap, and Plus at $39/month unlimited). Refund event tracking from Shopify's refund webhook is included on the Plus plan. Every server-side event carries the same event_id as the browser pixel so GA4 deduplicates automatically. You get one clean event per user action, even when the browser pixel is blocked.
Install WeltPixel Conversion Tracking on the Shopify App Store
Sources
- Google Developers. GA4 Recommended Events Reference. https://developers.google.com/analytics/devguides/collection/ga4/reference/events?client_type=gtag
- Google Developers. GA4 Ecommerce Implementation Guide. https://developers.google.com/analytics/devguides/collection/ga4/ecommerce
- Shopify Help Center. Tracking Ecommerce Events Using Analytics. https://help.shopify.com/en/manual/reports-and-analytics/google-analytics/tracking-ecommerce-events-using-analytics