"Meta Pixel not tracking" is the most common ecommerce problem that lands in my inbox, and Shopify stores account for most of it. The symptoms vary: Purchase events missing in Events Manager, revenue in Ads Manager far below Shopify, events showing as unverified, Add to Cart firing twice, or a store that spent a month "learning" and never left the learning phase.
The causes are usually the same handful. This guide walks through diagnosing them in order, then sets up a clean Meta Pixel and Conversions API implementation through Google Tag Manager that works on modern Shopify checkout.
Step 1: Diagnose Before You Change Anything
Open your store with the Meta Pixel Helper extension and a tag debugger such as the Insighter Debugger. Walk through product page, add to cart, checkout and a test order. Note:
- How many pixels load. More than one pixel ID, or the same ID loading twice, means duplicates.
- Which events fire on each step. Expect PageView everywhere, ViewContent on products, AddToCart on add, InitiateCheckout at checkout, Purchase on the thank-you page.
- Whether events carry value, currency and content IDs. A Purchase without value is useless for ROAS.
- Events Manager, Test Events tab. Watch your test session arrive and look for warnings about missing parameters or deduplication.
- Events Manager, Diagnostics tab. It lists duplicate events, missing event IDs and match quality issues.
Write down what you find. Most stores have at least two of the following.
The Five Usual Causes
Cause 1: Duplicate pixels
The Facebook and Instagram channel app installed the pixel, a previous developer added it to the theme, and someone later added it in GTM. Every event fires two or three times. Meta's reporting inflates, and deduplication fails because the copies have no shared event ID.
Fix: choose one source. If you want GTM control, disconnect the pixel in the channel app's settings, search the theme code for fbq( and connect.facebook.net and remove it, then keep only the GTM implementation.
Cause 2: Checkout events never fire
Theme code does not run on Shopify checkout or the thank-you page. If the pixel only lives in theme.liquid, you get ViewContent and AddToCart and nothing after.
Fix: a Customer Events custom pixel that loads GTM and forwards checkout_started and checkout_completed to the data layer. The Shopify GA4 tracking guide on this site includes the full pixel code; the same data layer drives the Meta tags.
Cause 3: Missing or wrong values
The Purchase event fires with no value, a value in cents, or a currency that does not match the store.
Fix: map value to the order total as a decimal number, currency to the checkout currency code, and content_ids to the product or variant IDs that match your catalogue.
Cause 4: No Conversions API or no deduplication
Browser-only events lose iOS, ad-blocked and consent-declined purchases. Conversions API added without a shared event ID doubles everything instead.
Fix: send the same events server-side with an event_id equal to the order ID, and set the same eventID on the browser pixel event.
Cause 5: Poor Event Match Quality
Events arrive but Meta cannot match them to people, so attribution and optimisation suffer. Common on stores that never send advanced matching data.
Fix: include hashed email, phone, name and address fields with Purchase and InitiateCheckout, from the checkout data.
The Clean Setup
Base pixel in GTM
Create a Meta Pixel tag using the official template from the Community Template Gallery, enter your pixel ID, enable advanced matching, and fire it on All Pages. Add a consent requirement for ad_storage if you run a consent banner.
Storefront events
Using the data layer from the Shopify GA4 guide, fire:
- ViewContent on
view_itemwithcontent_ids,content_name,content_typeofproduct,valueandcurrency. - AddToCart on
add_to_cartwith the same parameters.
Checkout events from the custom pixel
In the Customer Events pixel, extend the checkout_completed push with customer fields for matching:
analytics.subscribe('checkout_completed', function (event) {
var c = event.data.checkout;
var a = c.shippingAddress || c.billingAddress || {};
window.dataLayer.push({
event: 'purchase',
ecommerce: { /* as in the GA4 guide */ },
user_email: c.email ? c.email.toLowerCase() : undefined,
user_phone: c.phone || (a.phone || undefined),
user_first_name: a.firstName || undefined,
user_last_name: a.lastName || undefined,
user_city: a.city || undefined,
user_zip: a.zip || undefined,
user_country: a.countryCode || undefined
});
});
Then in GTM, fire InitiateCheckout on begin_checkout and Purchase on purchase, with value, currency, content_ids, content_type, num_items, advanced matching from the user fields, and eventID set to the transaction ID.
Conversions API through server-side GTM
Send the purchase to a server-side GTM container, either by routing the GA4 event through it or from a Shopify orders/paid webhook as described in the Shopify server-side guide. Fire the Meta Conversions API tag there with the same event name, the same event_id, the hashed customer data and the fbp and fbc cookie values passed from the browser. Meta keeps one copy per event ID.
Testing
- Pixel Helper on the storefront: one pixel, correct events, no warnings.
- Place a test order. In Events Manager Test Events, confirm ViewContent, AddToCart, InitiateCheckout and Purchase arrive once each from the browser and once from the server, shown as deduplicated.
- Open the Purchase event details and confirm value, currency, content IDs and the matched parameters.
- After 24 hours, check Diagnostics for the Purchase event. Match quality should be noticeably higher than before, and duplicate warnings should be gone.
- Compare Ads Manager purchase counts with Shopify orders over a week. Expect a close match, not parity, because Meta only attributes purchases it can tie to an ad.
Common Mistakes When Fixing
- Removing the theme pixel but leaving the channel app connected.
- Setting
eventIDonly on the server event. - Sending the Purchase from both the thank-you page pixel and the webhook with different IDs.
- Forgetting advanced matching on the base pixel, so the fbp cookie is set but no user data flows.
Outcome
One pixel, every standard event once, real values and strong match quality, with Conversions API filling the gaps browsers leave. In most stores the Purchase count in Events Manager rises sharply after the fix, not because sales changed, but because Meta finally sees them.
