HubSpot · Web Pixels API replacement · confidence: medium
Dies 2026-08-26
// Wave4-Hotel7 (2026-08-20): HubSpot post-checkout identify + purchase-event
// replacement. The legacy HubSpot Tracking Code (`_hsq.push(['identify', {...}])`
// followed by `_hsq.push(['trackEvent', {id: 'purchase', ...}])`) was pasted
// into Shopify Additional Scripts / checkout.liquid by hundreds of B2B-adjacent
// DTC stores using HubSpot Marketing Hub for lifecycle email + nurture flows.
// Additional Scripts stops executing after checkout on 2026-08-26 -- from that
// date, HubSpot never sees the buyer's email/order and cannot fire the
// post-purchase workflow that upsells / requests a review / segments the
// contact as a customer instead of a lead.
//
// Two variants: pick ONE.
//
// ============================================================
// VARIANT A -- BROWSER-SIDE (Shopify Web Pixels sandbox).
// Uses the HubSpot Tracking Code that Shopify already loads if you've added
// hs-scripts.com/{hubId}.js to your theme.liquid <head> (which continues to
// work -- theme.liquid execution is NOT deprecated). Web Pixels sandbox
// exposes the shared `_hsq` global through window when the tracker is loaded
// in theme scope; we push identify + custom purchase event from inside
// analytics.subscribe('checkout_completed').
// ============================================================
analytics.subscribe('checkout_completed', (event) => {
const { checkout } = event.data;
if (!checkout || !checkout.email) return;
// If HubSpot's tracker hasn't loaded yet (adblock / slow network),
// fall back to Variant B server-side path instead of silently no-op.
const hsq = (window && window._hsq) ? window._hsq : null;
if (!hsq) return;
hsq.push(['identify', {
email: checkout.email,
firstname: checkout.shippingAddress ? checkout.shippingAddress.firstName : undefined,
lastname: checkout.shippingAddress ? checkout.shippingAddress.lastName : undefined,
}]);
hsq.push(['trackCustomBehavioralEvent', {
name: 'pe_purchase',
properties: {
order_id: checkout.order ? String(checkout.order.id) : checkout.token,
value: Number(checkout.totalPrice.amount),
currency: checkout.totalPrice.currencyCode,
item_count: (checkout.lineItems || []).length,
},
}]);
hsq.push(['trackPageView']);
});
// ============================================================
// VARIANT B -- SERVER-SIDE (HubSpot Custom Behavioral Events API).
// Use if: (a) you have any backend that receives Shopify's orders/paid
// webhook, or (b) you want ad-blocker-proof, single-source-of-truth
// attribution. HUBSPOT_PRIVATE_APP_TOKEN is a HubSpot Private App token
// scoped to `behavioral_events.event_definitions.read_write` + `crm.objects.contacts.write`.
// Docs: https://developers.hubspot.com/docs/api/analytics/custom-events
// ============================================================
//
// // Shopify webhook: orders/paid
// export async function handleShopifyOrderPaidForHubspot(order) {
// await fetch('https://api.hubapi.com/events/v3/send', {
// method: 'POST',
// headers: {
// 'Authorization': `Bearer ${process.env.HUBSPOT_PRIVATE_APP_TOKEN}`,
// 'Content-Type': 'application/json',
// },
// body: JSON.stringify({
// eventName: 'pe' + process.env.HUBSPOT_ACCOUNT_ID + '_purchase',
// email: order.email,
// occurredAt: order.created_at,
// properties: {
// order_id: String(order.id),
// value: Number(order.total_price),
// currency: order.currency,
// item_count: order.line_items.length,
// },
// }),
// });
// }What this does NOT cover
What this does NOT cover: HubSpot's pre-checkout page-view tracking (that still works via theme.liquid's tracker), form submissions, chat conversations, or the HubSpot Ads Pixel (which is a separate script, ads.hubspot.com/analytics.js, and has its own Additional Scripts breakage surface -- track separately). Also does not migrate abandoned-cart nurture workflows if those were triggered by _hsq events set from checkout stages before checkout_completed -- those need Web Pixels analytics.subscribe('checkout_started') hooks.
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.