TL;DR

  • PostHog has a native Shopify installation: paste the JS snippet into theme.liquid before </head>
  • Follow PostHog's eCommerce event spec (Product Added, Cart Viewed, Order Completed are the three that matter most) for funnel and cohort analysis to work without custom setup
  • Cart abandonment: fire Cart Viewed, then build a funnel to Order Completed. The drop-off cohort is your abandonment segment. Watch their sessions with session replay.
  • Anonymous-to-identified stitching happens via posthog.identify() at login or checkout, PostHog merges the full session history automatically
  • A/B test checkout flows with PostHog feature flags. Pass the variant as an event property on Order Completed to compare conversion rates.
  • WooCommerce has an official PostHog plugin. Custom storefronts (Next.js, Nuxt, SvelteKit) use the standard JS or Node SDK.

Each section below covers one piece of the implementation with the exact code that makes it work.

Why PostHog fits eCommerce differently than GA4

Google Analytics 4 was built for web traffic measurement. PostHog was built for product analytics. That distinction matters in eCommerce.

GA4 gives you sessions, sources, and conversion events. PostHog gives you user-level behavioural funnels, session recordings of individual cart sessions, feature flags to run checkout experiments, and SQL-level access to your raw event data. You can watch a specific user's cart session, see exactly where they dropped off, and then A/B test a fix, all in one platform.

The practical difference shows up at three points. Abandonment analysis uses session replay on the drop-off cohort. Experimentation runs feature flag A/B tests on the checkout UI. Customer-level data ties every event to a single user across sessions through PostHog's person profiles. GA4 can tell you your cart abandonment rate. PostHog can show you the sessions that explain it.

Both tools are free at low volume. PostHog starts charging above 1M events per month. For most eCommerce teams, running both, GA4 for traffic/acquisition, PostHog for product behaviour, is the right call.

Installing PostHog on your storefront

The installation differs by platform, but the core pattern stays constant. Paste the PostHog JS snippet into your site's global head, then add purchase-specific event calls to your checkout confirmation.

Shopify (theme.liquid)

Open your Shopify admin, go to Online Store, then Themes, then Actions, then Edit code. Open theme.liquid and paste the PostHog snippet immediately before the closing </head> tag.

Shopify: theme.liquid, PostHog init before </head>
<script>
  !function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+" (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys onSessionId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
  posthog.init('<ph_project_api_key>', {
    api_host: 'https://us.i.posthog.com',
    autocapture: true,
  });
</script>

Autocapture handles clicks, page views, and form interactions automatically. You still need to add manual events for purchase-specific data, which is covered in the next section.

Purchase confirmation in Shopify (thank_you.liquid)

Shopify's thank_you.liquid template (or the Additional Scripts field in checkout settings) fires on the order confirmation page. Add the Order Completed event there.

Shopify: order confirmation, Order Completed event
<script>
posthog.capture('Order Completed', {
  order_id: '{{ order.order_number }}',
  revenue: {{ order.total_price | divided_by: 100.0 }},
  currency: '{{ order.currency }}',
  products: [
    {% for line_item in order.line_items %}
    {
      product_id: '{{ line_item.product_id }}',
      name: '{{ line_item.title | escape }}',
      price: {{ line_item.price | divided_by: 100.0 }},
      quantity: {{ line_item.quantity }},
      sku: '{{ line_item.sku | escape }}'
    }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
});
</script>

WooCommerce

WooCommerce has an official PostHog plugin available in the WordPress plugin directory. Install it, enter your PostHog project API key, and it handles snippet injection and basic purchase event tracking automatically. For custom event properties beyond the defaults, add a filter hook to the plugin's event payload.

Custom storefronts (Next.js, Nuxt, SvelteKit)

Use the posthog-js npm package. Initialize it in your app's root component and call posthog.capture() directly in your event handlers.

JavaScript: posthog-js init in Next.js app root
import posthog from 'posthog-js'

if (typeof window !== 'undefined') {
  posthog.init('<ph_project_api_key>', {
    api_host: 'https://us.i.posthog.com',
    capture_pageview: false, // handle manually with Next.js router
  })
}

// In your router event handler:
router.events.on('routeChangeComplete', () => {
  posthog.capture('$pageview')
})
PostHog Shopify web analytics installation documentation page
PostHog's official Shopify installation guide at posthog.com/docs/web-analytics/installation/shopify

PostHog's eCommerce event schema

PostHog publishes a standard eCommerce event specification that covers every stage of the purchase journey. You are not required to use these exact names, but following the spec means PostHog's funnel templates, CDP destination connectors, and data warehouse schemas work without extra configuration.

The events that drive most of the useful analysis are the ordering events. The table below covers the core set.

Event name When to fire Key properties
Product Viewed User lands on a product detail page product_id, name, price, category
Product Added User adds item to cart product_id, name, price, quantity, cart_id
Cart Viewed User opens the cart page or drawer cart_id, value, currency, products array
Checkout Started User proceeds to checkout order_id, value, products array
Payment Info Entered User submits payment details order_id, payment_method
Order Completed Order confirmed (server-side or confirmation page) order_id, revenue, currency, products array, coupon
Order Refunded Refund processed order_id, revenue, products array

Beyond ordering events, the spec also covers browsing (Products Searched, Product List Viewed, Product List Filtered), promotions (Promotion Viewed, Promotion Clicked), wishlisting, sharing, and reviews. Implement the ordering events first, they power funnel analysis, revenue dashboards, and abandonment cohorts. Add the rest as your analytics maturity grows.

The Product Added event in full

This is the event most teams get wrong by omitting the products array. Without it, you cannot break down cart abandonment by product or identify which SKUs drive the most cart additions versus purchases.

JavaScript: Product Added with full properties
posthog.capture('Product Added', {
  product_id: 'SKU-4821',
  name: 'Merino Wool Crew Neck',
  category: 'Apparel / Knitwear',
  brand: 'Brand Name',
  variant: 'Navy / M',
  price: 89.00,
  quantity: 1,
  currency: 'USD',
  cart_id: getSessionCartId(),   // consistent ID for this cart session
  position: 3,                   // position in the product list the user came from
  url: window.location.href,
  image_url: 'https://cdn.example.com/images/sku-4821-navy-m.jpg'
})

Keep the cart_id consistent across all cart events in the session. Use a UUID stored in localStorage or your cart service. This is what ties Product Added, Cart Viewed, and Checkout Started together in funnel analysis.

Cart abandonment analysis with session replay

PostHog's session replay is what separates cart abandonment analysis from cart abandonment guessing. Other tools give you the drop-off rate. PostHog lets you watch the sessions that explain it.

Building the abandonment funnel

In PostHog, navigate to Insights, then create a Funnel. Set the steps as follows, then the funnel shows you exactly how many users reached each step and where the biggest drops occur.

  • Step 1: Product Added (user put something in the cart)
  • Step 2: Cart Viewed (user opened the cart)
  • Step 3: Checkout Started (user clicked proceed to checkout)
  • Step 4: Order Completed (purchase confirmed)

The drop between Cart Viewed and Checkout Started is typically where the most value is recoverable, the user has engaged with the cart but not committed. That is your primary abandonment segment.

Watching the abandonment sessions

From the funnel, click the drop-off number between any two steps. PostHog creates a cohort of users who completed step N but not step N+1. Click through to session replays filtered to that cohort. You get recordings of the exact sessions where people abandoned.

You are watching for a few specific patterns. Rage clicks on the proceed button, confusion at address forms, hesitation at the shipping cost reveal, payment method gaps. Fifteen sessions will tell you more than the aggregate data alone.

PostHog eCommerce event specification documentation showing the full list of standard eCommerce events
PostHog's eCommerce event spec, the standard event names and property schemas that power funnel and cohort analysis

Identifying shoppers: anonymous to customer

Most eCommerce traffic is anonymous. PostHog handles the anonymous-to-identified transition through posthog.identify(), which merges the full session history onto a single user profile.

When to call identify()

There are two natural moments in an eCommerce flow where identity becomes known. Handle both of them.

  • Account login or registration: call posthog.identify() with the user's internal ID. Do not use email as the distinct_id, use a hashed or opaque internal ID to keep PII out of PostHog.
  • Guest checkout completion: call posthog.identify() with a hashed order or customer ID so the purchase event is tied to a consistent identity even without account creation.
JavaScript: identify at login and at guest checkout
// At account login / registration
posthog.identify(
  user.id,  // internal numeric or UUID — not email
  {
    account_created: user.createdAt,
    plan: user.plan || 'guest',
    total_orders: user.orderCount,
  }
)

// At guest checkout completion (no account)
const guestId = 'guest-' + sha256(order.email + order.id)
posthog.identify(guestId, {
  guest_checkout: true,
  first_order_date: new Date().toISOString(),
})

// Then immediately fire the purchase event
posthog.capture('Order Completed', { order_id: order.id, revenue: order.total, ... })

PostHog merges all events captured under the anonymous distinct_id before the identify() call with the new identified profile. The full browse-to-purchase journey appears on one user record, including all product views, cart interactions, and the purchase itself.

Group analytics for B2B eCommerce

For B2B storefronts where multiple users belong to one buying account, use PostHog's group analytics to track behaviour at the account level. Call posthog.group() after identifying the user.

JavaScript: group call for B2B account-level tracking
posthog.group('company', account.id, {
  name: account.name,
  plan: account.plan,
  account_value: account.annualValue,
  industry: account.industry,
})

With group analytics active, every event fired by any user in that account rolls up to the account profile. You can build funnels, cohorts, and dashboards at the account level, not just the individual user level.

Revenue tracking and refund handling

Accurate revenue in PostHog comes from three things. Fire Order Completed server-side, or on a page the user cannot skip. Pass the right properties on every order event. Handle refunds with a matching Order Refunded event.

The most common mistake is firing Order Completed only on the thank-you page. Users who close the tab before the page loads create a gap. Fire the event server-side from your order webhook as a backup.

Node.js: server-side Order Completed via PostHog Node SDK
import { PostHog } from 'posthog-node'
const client = new PostHog('<ph_project_api_key>', { host: 'https://us.i.posthog.com' })

// In your order webhook handler
async function handleOrderConfirmed(order) {
  client.capture({
    distinctId: order.customerId || 'guest-' + hashEmail(order.email),
    event: 'Order Completed',
    properties: {
      order_id: order.id,
      revenue: order.totalAmount,
      subtotal: order.subtotal,
      shipping: order.shippingCost,
      tax: order.taxAmount,
      discount: order.discountAmount,
      coupon: order.couponCode || null,
      currency: order.currency,
      products: order.lineItems.map(item => ({
        product_id: item.productId,
        name: item.title,
        price: item.unitPrice,
        quantity: item.quantity,
        sku: item.sku,
      })),
    },
  })
  await client.flush()
}

For refunds, fire Order Refunded with the same order_id and the refunded amount. PostHog does not automatically net refunds against revenue in its dashboards, so subtract the Order Refunded events from your revenue totals in your HogQL queries.

A/B testing checkout flows with feature flags

PostHog's feature flags are the right tool for checkout experiments. A single flag, a 50/50 rollout, and a conversion metric is all you need to run a statistically valid checkout test.

PostHog product analytics funnels documentation page showing funnel analysis configuration
PostHog's funnel analysis, where you build the cart-to-purchase funnel and identify the abandonment drop-off steps

Setting up a checkout A/B test

Create a multivariate flag in PostHog's Feature Flags section. Give it two variants, control and test. Set each to 50% rollout. In your checkout component, check the flag and render the appropriate UI.

JavaScript: feature flag checkout A/B test
const checkoutVariant = posthog.getFeatureFlag('checkout-flow-v2')

// Render based on variant
if (checkoutVariant === 'test') {
  renderNewCheckoutFlow()
} else {
  renderDefaultCheckoutFlow()
}

// Pass variant on Order Completed so PostHog can compare
posthog.capture('Order Completed', {
  order_id: order.id,
  revenue: order.total,
  currency: order.currency,
  checkout_variant: checkoutVariant,   // 'control' or 'test'
  products: order.lineItems,
})

In PostHog's Experiments section, create an experiment tied to the flag. Set the success metric as Order Completed. PostHog calculates statistical significance and shows you the conversion rate for each variant as the test runs.

What makes a good checkout experiment

Test one thing at a time. The high-impact variables are well established. The number of checkout steps, single-page versus multi-step. The placement and copy of the security trust badge. The default payment method shown, and the shipping estimate display. Run each test until you reach 95% statistical significance before declaring a winner. PostHog's experiment dashboard tells you when you are there.

Important: Do not use PostHog's managed reverse proxy for checkout pages if you are in a HIPAA or PCI scope. See PostHog's data collection docs for the full scope of what the JS SDK captures by default on checkout pages.

Building your eCommerce dashboards in PostHog

Three dashboards cover 90% of eCommerce analytics needs. A revenue dashboard, a funnel dashboard, and a customer behaviour dashboard. Build them in that order. Build them in that order.

Revenue dashboard

Create a new dashboard and add these Insight cards to it. Each uses the Order Completed event as its source.

  • Daily revenue: Sum of the revenue property on Order Completed events, grouped by day
  • Average order value: Average of revenue on Order Completed
  • Orders per day: Count of Order Completed events by day
  • Revenue by product: Sum of revenue, broken down by the products.name property
  • Refund rate: Count of Order Refunded divided by count of Order Completed, as a percentage

These five cards give you a complete revenue picture without needing to leave PostHog or export to a spreadsheet.

Funnel dashboard

Add the purchase funnel (Product Added, Cart Viewed, Checkout Started, Order Completed) as one card, and a separate funnel for the checkout steps alone (Checkout Started, Payment Info Entered, Order Completed) as another. The checkout funnel tells you whether you have a checkout form problem separate from a cart problem.

Customer behaviour dashboard

The third dashboard answers the question revenue data alone cannot. Who are your customers, and how do they behave differently from each other?

  • Repeat purchase rate: count of users with 2+ Order Completed events divided by total unique purchasers
  • Time to second purchase: average days between a user's first and second Order Completed events
  • Top products by unique buyers: count of distinct users who fired Product Added per product_id, not just total add-to-cart volume
  • New vs returning purchaser split: segment Order Completed by whether it is the user's first or subsequent purchase
  • Revenue by acquisition channel: join Order Completed with the $initial_referring_domain person property to see lifetime value by source

All five of these are buildable in PostHog's Insights using HogQL for the more complex calculations. The repeat purchase rate and time-to-second-purchase cards are the ones most eCommerce teams look at daily once they have them, they are the leading indicators of whether retention is improving, and they tell you faster than monthly cohort analysis whether a change you made is working.

Where to start if you are setting this up today

The sequencing is what most teams get wrong. Implementing everything at once means you end up with partial data everywhere and complete data nowhere. Work through these in order and you have something working and validated at each step before adding the next layer.

Start with the snippet and autocapture. Paste PostHog into your storefront and open the Activity tab in your dashboard. Confirm events are coming in. This takes 15 minutes and is the only prerequisite for everything that follows.

Add Product Added, Order Completed, and Cart Viewed next. These three events are the foundation of every meaningful eCommerce analysis in PostHog. Get them firing correctly with the right properties before adding anything else. Verify the counts match your order management system. If they do not, find the gap before moving on.

Build the purchase funnel. Once event counts are clean, create the funnel in PostHog Insights. The funnel exists so you can click into the drop-off and watch session replays of cart sessions. That is where the actual insight lives, not in the aggregate number.

Enable session replay on cart and checkout pages. Watch fifteen recordings of sessions from users who did not complete a purchase. You will surface more actionable UX findings in an hour than weeks of quantitative analysis would show you.

Build the revenue dashboard, then add identify(). Five Insight cards give you the daily revenue view your team needs. Once that is working, close the anonymous-to-customer gap with posthog.identify() at login and checkout completion.

The whole setup, done properly, takes two to three weeks. Rushing the event taxonomy in week one creates data quality problems that compound for months. Get the foundation right and the rest follows.

FAQ

Does PostHog work with Shopify out of the box?

Yes. PostHog has an official Shopify installation guide that walks through pasting the JS snippet into theme.liquid. Autocapture picks up clicks and page views automatically. Purchase events require a few additional lines on the order confirmation page or via the thank_you Liquid template. The PixieHog Shopify app also handles this automatically for stores that want a no-code setup.

What is PostHog's eCommerce event spec and do I have to follow it?

PostHog's eCommerce event spec is a set of standardized event names and property schemas. You are not required to use these names, but following the spec means PostHog's CDP destination templates and funnel templates work without custom configuration. It also makes your data portable if you later pipe it to a data warehouse.

How do I track cart abandonment in PostHog?

Fire Cart Viewed when a user opens their cart, and Order Completed on successful purchase. Build a funnel from Cart Viewed to Order Completed. Users who hit Cart Viewed but not Order Completed within your chosen window are your abandonment cohort. Session replay on that cohort shows exactly what happened in their cart sessions.

Can PostHog track anonymous shoppers and then connect them to a purchase?

Yes, through PostHog's identify() call. Before checkout, a visitor is anonymous with a generated distinct_id. When they log in or complete a guest checkout, call posthog.identify() with their user or order ID. PostHog merges the anonymous session history with the identified profile, so the full browse-to-purchase journey appears on one user record.

How do I A/B test checkout flows in PostHog?

Use PostHog feature flags with the multivariate option. Create a flag with two variants (control and test), roll each to 50%, and render different checkout UI based on the variant. Fire Order Completed with the variant name as a property so PostHog can compare conversion rates. PostHog's experiments dashboard handles statistical significance automatically.

Sources

PostHog Setup Service

Need your PostHog eCommerce setup done right?

ProductQuant's PostHog setup engagement covers SDK installation, event taxonomy design, purchase funnel build, session replay configuration, and first dashboards, ready for your team to use from day one.

Jake McMahon

About the Author

Jake McMahon is a product analytics strategist and founder of ProductQuant, working with B2B SaaS and eCommerce teams to build analytics stacks that produce decisions, not just dashboards.

The event schemas, funnel patterns, and A/B testing approaches described here reflect implementation work on live eCommerce storefronts using PostHog.

Next Step

Get your eCommerce analytics stack producing decisions.

Most eCommerce teams know their abandonment rate. Few know which cart sessions caused it, which SKUs drive abandonment, or which checkout variant converts better. PostHog answers all three. ProductQuant sets it up.