Mixpanel · Web Pixels API replacement · confidence: high
Dies 2026-08-26
// Wave4-Hotel7 (2026-08-20): Mixpanel Purchase event + Revenue charge
// replacement. Mixpanel is the second-most-common product-analytics
// platform after Amplitude for DTC + subscription commerce, especially
// for stores instrumenting subscription-billing / churn funnels. The
// legacy install pastes mixpanel.init(TOKEN) + mixpanel.track('Purchase',
// {...}) + mixpanel.people.track_charge(amount, {...}) into Shopify
// Additional Scripts. All three calls stop firing 2026-08-26.
//
// Two variants: pick ONE.
//
// ============================================================
// VARIANT A -- BROWSER-SIDE (Shopify Web Pixels sandbox).
// Loads the current Mixpanel JS library (mixpanel-2-latest.min.js) from
// cdn.mxpnl.com inside the pixel sandbox. MIXPANEL_PROJECT_TOKEN is the
// documented client-safe token (write-only, per-project rate-limited).
// ============================================================
(function loadMixpanel() {
if (window.mixpanel && window.mixpanel.track) return;
const s = document.createElement('script');
s.async = true;
s.src = 'https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js';
s.onload = () => window.mixpanel.init('MIXPANEL_PROJECT_TOKEN', { track_pageview: false, persistence: 'localStorage' });
document.head.appendChild(s);
})();
analytics.subscribe('checkout_completed', (event) => {
const { checkout } = event.data;
if (!checkout || !checkout.email || !window.mixpanel) return;
const distinctId = checkout.order
? String(checkout.order.customerId || checkout.order.id)
: checkout.email;
// Identify BEFORE track() so the Purchase event is attached to the
// logged-in profile (not the anonymous device_id).
window.mixpanel.identify(distinctId);
window.mixpanel.people.set({
$email: checkout.email,
$last_purchase: new Date().toISOString(),
});
// Revenue: track_charge populates the Mixpanel Revenue report and per-
// profile Lifetime Value. Fire it BEFORE the Purchase event so revenue
// is attached to the same profile+session.
window.mixpanel.people.track_charge(Number(checkout.totalPrice.amount), {
order_id: checkout.order ? String(checkout.order.id) : checkout.token,
currency: checkout.totalPrice.currencyCode,
});
window.mixpanel.track('Purchase', {
order_id: checkout.order ? String(checkout.order.id) : checkout.token,
total: Number(checkout.totalPrice.amount),
currency: checkout.totalPrice.currencyCode,
item_count: (checkout.lineItems || []).length,
// Mixpanel best-practice: flatten arrays of primitives, not deep object arrays --
// deep arrays cost more per event and cannot be filtered in Mixpanel's UI.
product_ids: (checkout.lineItems || []).map((li) => li.variant && li.variant.product ? String(li.variant.product.id) : null).filter(Boolean),
product_skus: (checkout.lineItems || []).map((li) => li.variant ? li.variant.sku : null).filter(Boolean),
product_names: (checkout.lineItems || []).map((li) => li.title),
});
});
// ============================================================
// VARIANT B -- SERVER-SIDE (Mixpanel Import API + Shopify webhook).
// Recommended -- Mixpanel's Import API is the authoritative path for
// financial events (invoicing, subscription renewals) and gives you
// audit-grade dedupe via $insert_id.
// Docs: https://developer.mixpanel.com/reference/import-events
// ============================================================
//
// // Shopify webhook: orders/paid
// export async function handleShopifyOrderPaidForMixpanel(order) {
// const auth = Buffer.from(process.env.MIXPANEL_SERVICE_ACCOUNT_USER + ':' + process.env.MIXPANEL_SERVICE_ACCOUNT_SECRET).toString('base64');
// await fetch('https://api.mixpanel.com/import?strict=1&project_id=' + process.env.MIXPANEL_PROJECT_ID, {
// method: 'POST',
// headers: {
// 'Authorization': `Basic ${auth}`,
// 'Content-Type': 'application/json',
// },
// body: JSON.stringify([{
// event: 'Purchase',
// properties: {
// distinct_id: String(order.customer ? order.customer.id : order.id),
// time: Math.floor(new Date(order.created_at).getTime() / 1000),
// $insert_id: 'shopify-order-' + order.id, // dedupe key
// order_id: String(order.id),
// total: Number(order.total_price),
// currency: order.currency,
// revenue: Number(order.total_price),
// },
// }]),
// });
// }What this does NOT cover
What this does NOT cover: Mixpanel Group Analytics (B2B account-level rollups), Mixpanel Session Replay (separate script), pre-purchase funnel events (Product Viewed / Added to Cart / Checkout Started -- those belong in theme.liquid or separate Web Pixels subscribers), or Mixpanel's Alias() flow for merging pre-login anonymous ids to a signed-in user (that must happen at login, not at checkout_completed).
Product-analytics + CDP + CRM · HubSpot, Segment, Amplitude, Mixpanel, PostHog — every DTC brand ships at least one of these and all break the same way Aug 26.