Installation
1 min
to install the chord web pixel on your shopify store ask the chord team for the full web pixel code (see the example below) navigate to settings > customer events in your shopify store select add custom pixel enter "chord analytics" as the name for your pixel select add pixel review the customer privacy settings, and see our guide to consent management docid\ dbkzuyyjshkx7dzhisfez to understand how these settings will impact your event tracking in the code text box, copy and paste the provided web pixel code before you publish the provided web pixel, you need to update the settings const variables at the very top of the javascript code see the configuration guide docid\ qmm8kz1wshyjhs9qbh0vm for a detailed explanation of each const variable after you've updated the const variables, select save once the pixel has been saved successfully, you can select connect to enable the pixel on your shopify store once you select connect , the pixel will immediately load and start tracking events, so make sure you finalize the pixel settings first const cdp write key = '' const cdp domain = 'https //production cdp ingest chord co' const chord oms id = '' const chord store id = '' const chord tenant id = '' const default locale = 'en us' const store domain = '' const pixel version = '1 0 0' let customerprivacystatus = init customerprivacy let currency = init data cart? cost? totalamount currencycode let locale = default locale function getstorefrontanonymousid() { return document cookie split('; ') find((c) => c startswith(' eventn id=')) ? split('=')\[1] } // ============================================================================ // cdp initialization (lazy — loads p js on first checkout event) // ============================================================================ let cdpinitialized = false function initcdp() { if (cdpinitialized) return if (!cdp write key || !cdp domain) return cdpinitialized = true window\ chordq = window\ chordq || \[] window\ chord = window\ chord || { identify ( args) => window\ chordq? push((cdp) => cdp? identify( args)), page ( args) => window\ chordq? push((cdp) => cdp? page( args)), track ( args) => window\ chordq? push((cdp) => cdp? track( args)), } const script = document createelement('script') script async = true script src = `${cdp domain}/p js` script setattribute('data init only', 'true') script setattribute('data namespace', 'chord') script setattribute('data write key', cdp write key) document head appendchild(script) const cdpuserid = window\ chord? user? ()? userid const userid = init data customer? id if (userid && userid !== cdpuserid) { const traits = getinitcustomertraits(init) cdpidentify(userid, traits) } } // ============================================================================ // consent management // ============================================================================ api customerprivacy subscribe('visitorconsentcollected', (event) => { customerprivacystatus = event customerprivacy }) ;(function identifyonload() { const customer = init data customer if (!customer? id) return const traits = {} if (customer email) traits email = customer email if (customer firstname) traits firstname = customer firstname if (customer lastname) traits lastname = customer lastname if (customer phone) traits phone = customer phone if (customer orderscount) traits orderscount = customer orderscount forward('identify', customer id, traits) })() // ============================================================================ // event subscriptions — all 13 shopify events // ============================================================================ // storefront only events (postmessage only) analytics subscribe('page viewed', (event) => { forward('page', { path event context document location pathname, url event context document location href, title event context document title, }) }) analytics subscribe('product viewed', (event) => { const { productvariant } = event data forward('track', 'product viewed', formatproduct(productvariant)) }) analytics subscribe('product added to cart', (event) => { const { cartline } = event data if (!cartline) return const product = formatcartline(cartline) forward('track', 'product added', { product, products \[product], }) }) analytics subscribe('product removed from cart', (event) => { const { cartline } = event data if (!cartline) return const product = formatcartline(cartline) forward('track', 'product removed', { product, products \[product], }) }) analytics subscribe('cart viewed', (event) => { const { cart } = event data if (!cart) return forward('track', 'cart viewed', { cart id cart id, currency cart cost totalamount currencycode, value cart cost totalamount amount, products cart lines map(formatcartline), }) }) analytics subscribe('collection viewed', (event) => { const { collection } = event data forward('track', 'product list viewed', { list id collection id, item list id collection id, list name collection title, item list name collection title, products collection productvariants map(formatproduct), }) }) analytics subscribe('search submitted', (event) => { forward('track', 'products searched', { query event data searchresult query, }) }) // checkout events (postmessage + direct cdp) analytics subscribe('checkout started', async (event) => { const { checkout } = event data // postmessage (sync, fire and forget) forward('track', 'checkout started', formatcheckout(checkout)) // direct cdp const coupon = getcoupon(checkout) const discount = getdiscount(checkout) const props = { checkout type 'shopify', coupon, currency checkout currencycode, discount, products checkout lineitems map(getlineitem), revenue checkout subtotalprice amount, shipping checkout shippingline? price amount, tax checkout totaltax amount, value checkout subtotalprice amount, } await cdptrack('checkout started', props) }) analytics subscribe('checkout contact info submitted', async (event) => { const { checkout } = event data // postmessage (sync, fire and forget) // use undefined for userid — email is not a stable id; the real customer id // is set at checkout completed when checkout order customer id is available forward('identify', undefined, { email checkout email, phone checkout phone, }) forward('track', 'checkout step completed', { checkout id checkout token, step 1, step name 'contact info', }) // direct cdp const checkouttraits = getcheckouttraits(checkout) const inittraits = getinitcustomertraits(init) const traits = { inittraits, checkouttraits, } const userid = traits id || undefined await cdpidentify(userid, traits) const props = { checkout id checkout token, step 1, } await cdptrack('checkout step completed', props) }) analytics subscribe('checkout address info submitted', async (event) => { // postmessage (sync, fire and forget) forward('track', 'checkout step completed', { checkout id event data checkout token, step 2, step name 'shipping address', }) // direct cdp const props = { checkout id event data checkout token, step 2, } await cdptrack('checkout step completed', props) }) analytics subscribe('checkout shipping info submitted', async (event) => { // postmessage (sync, fire and forget) forward('track', 'checkout step completed', { checkout id event data checkout token, step 3, step name 'shipping method', }) // direct cdp const props = { checkout id event data checkout token, step 3, } await cdptrack('checkout step completed', props) }) analytics subscribe('payment info submitted', async (event) => { const { checkout } = event data // postmessage (sync, fire and forget) forward('track', 'payment info entered', { checkout id checkout token, step 4, currency checkout currencycode, value checkout subtotalprice amount, products checkout lineitems map(formatlineitem), }) // direct cdp const coupon = getcoupon(checkout) const props = { checkout id checkout token, coupon, currency checkout currencycode, products checkout lineitems map(getlineitem), step 4, value checkout subtotalprice amount, } await cdptrack('payment info entered', props) }) analytics subscribe('checkout completed', async (event) => { const { checkout } = event data // postmessage (sync, fire and forget) const userid = checkout order? customer? id || undefined forward('identify', userid, { email checkout email, phone checkout phone, firstname checkout shippingaddress? firstname, lastname checkout shippingaddress? lastname, }) forward( 'track', 'order completed', formatordercompleted(checkout, event timestamp) ) // direct cdp const coupon = getcoupon(checkout) const discount = getdiscount(checkout) const orderprops = { checkout id checkout token, checkout type 'shopify', coupon, currency checkout currencycode, discount, email checkout email || undefined, first name checkout shippingaddress? firstname || undefined, last name checkout shippingaddress? lastname || undefined, order date event timestamp, order id checkout order? id, phone checkout phone || undefined, products checkout lineitems map((item, i) => { const price = item variant? price amount const itemdiscount = item discountallocations reduce( (acc, { amount }) => acc + (amount amount || 0), 0 ) const revenue = price ? (item quantity || 1) price itemdiscount 0 return { getlineitem(item, i), revenue, } }), revenue checkout subtotalprice amount, shipping checkout shippingline? price amount, shipping city checkout shippingaddress? city || undefined, shipping country checkout shippingaddress? country || undefined, shipping state checkout shippingaddress? province || undefined, shipping zipcode checkout shippingaddress? zip || undefined, subtotal checkout subtotalprice amount, tax checkout totaltax amount, total checkout totalprice amount, } const checkouttraits = getcheckouttraits(checkout) const inittraits = getinitcustomertraits(init) const traits = { inittraits, checkouttraits, } const cdpuserid = traits id || undefined await cdpidentify(cdpuserid, traits) await cdptrack('order completed', orderprops) }) function forward(type, args) { try { const target = typeof window !== 'undefined' && window\ top ? window\ top self target postmessage( { source 'chord web pixel', type, payload args, }, ' ' ) } catch (err) { // silently fail if postmessage is not available } } // ============================================================================ // lightweight data formatters (for postmessage forwarding) // ============================================================================ function formatproduct(variant) { const product = variant? product return { product id product? id, sku variant? sku, name product? title || product? untranslatedtitle, price variant? price? amount, currency variant? price? currencycode, category product? type, brand product? vendor, variant variant? title || variant? untranslatedtitle, variant id variant? id, image url variant? image? src, url product? url, } } function formatcartline(cartline) { const variant = cartline merchandise const product = variant? product return { product id product? id, sku variant? sku, name product? title || product? untranslatedtitle, price variant? price? amount, currency cartline cost totalamount currencycode, quantity cartline quantity, category product? type, brand product? vendor, variant variant? title || variant? untranslatedtitle, variant id variant? id, image url variant? image? src, url product? url, value cartline cost totalamount amount, } } function formatlineitem(item, index) { const variant = item variant const product = variant? product return { product id product? id, sku variant? sku, name product? title || product? untranslatedtitle, price variant? price? amount, quantity item quantity, category product? type, brand product? vendor, variant variant? title || variant? untranslatedtitle, variant id variant? id, image url variant? image? src, url product? url, position typeof index === 'number' ? index + 1 undefined, } } function formatcheckout(checkout) { const discount = checkout lineitems reduce((acc, item) => { return ( acc + item discountallocations reduce( (sum, d) => sum + (d amount amount || 0), 0 ) ) }, 0) const coupon = checkout discountapplications find((d) => { if ('amount' in d value) return d value amount > 0 return d value percentage > 0 })? title return { checkout id checkout token, currency checkout currencycode, value checkout subtotalprice amount, revenue checkout subtotalprice amount, shipping checkout shippingline? price? amount, tax checkout totaltax? amount, discount, coupon, products checkout lineitems map(formatlineitem), } } function formatordercompleted(checkout, timestamp) { const base = formatcheckout(checkout) return { base, order id checkout order? id, order date timestamp, total checkout totalprice amount, subtotal checkout subtotalprice amount, email checkout email, phone checkout phone, first name checkout shippingaddress? firstname, last name checkout shippingaddress? lastname, shipping city checkout shippingaddress? city, shipping state checkout shippingaddress? province, shipping country checkout shippingaddress? country, shipping zipcode checkout shippingaddress? zip, } } // ============================================================================ // direct cdp methods (for checkout events in the sandbox) // ============================================================================ function cdpenabled() { if (window\ chord) return true if (!cdp write key || !cdp domain) return false initcdp() return !!window\ chord } async function cdpidentify(userid, traits) { if (!cdpenabled()) return const options = await getoptions() const anonymousid = getstorefrontanonymousid() await window\ chord identify(userid, traits, { options, (anonymousid && { anonymousid, }), context { page options page, }, }) } async function cdptrack(event, props) { if (!cdpenabled()) return const options = await getoptions() const meta = await getmeta() const anonymousid = getstorefrontanonymousid() await window\ chord track( event, { props, meta, context { page options page, }, }, { options, (anonymousid && { anonymousid, }), } ) } // ============================================================================ // cdp options & metadata // ============================================================================ async function getcategorypreferences() { return { analytics customerprivacystatus? analyticsprocessingallowed, marketing customerprivacystatus? marketingallowed, preferences customerprivacystatus? preferencesprocessingallowed, sale of data customerprivacystatus? saleofdataallowed, } } async function getoptions() { const categorypreferences = (await getcategorypreferences()) || {} return { consent { categorypreferences, }, page { path init context document location pathname, url init context document location href, }, } } async function getmeta() { if (!currency) { currency = await browser cookie get('cart currency') } return { i18n { currency, locale, }, ownership { oms id chord oms id, store id chord store id, tenant id chord tenant id, }, platform { name 'shopify', type 'web', }, store { domain store domain, }, version { major 3, minor 0, patch 0, }, } } // ============================================================================ // rich data formatters (for direct cdp — adapted from legacy pixel) // ============================================================================ function getlineitem(item, position) { const variant = 'variant' in item ? item variant item merchandise const product = variant? product const discountallocations = 'discountallocations' in item ? item discountallocations undefined const coupon = discountallocations? find((al) => al? amount? amount > 0) ? discountapplication title return { brand product? vendor, category product? type || undefined, coupon, image url variant? image? src, line item id 'id' in item ? item id undefined, name product? title || product? untranslatedtitle, position typeof position === 'number' ? position + 1 undefined, price variant? price amount, product id product? id, quantity ('quantity' in item && item quantity) || undefined, sku variant? sku || undefined, url product? url, variant variant? title || variant? untranslatedtitle || undefined, variant id variant? id, } } function getdiscount(checkout) { return checkout lineitems reduce((acc, item) => { const { discountallocations } = item const discount = discountallocations reduce((inneracc, { amount }) => { return inneracc + (amount amount || 0) }, 0) return acc + discount }, 0) } function getcoupon(checkout) { return checkout discountapplications find(({ value }) => { if ('amount' in value) return value amount > 0 return value percentage > 0 })? title } function getcheckouttraits(checkout) { const traits = {} if (checkout email) traits email = checkout email if (checkout phone) traits phone = checkout phone const customerid = checkout order? customer? id if (customerid) traits id = customerid return traits } function getinitcustomertraits(init) { const { customer } = init data const traits = {} if (customer? email) traits email = customer email if (customer? firstname) traits firstname = customer firstname if (customer? id) traits id = customer id if (customer? lastname) traits lastname = customer lastname if (customer? orderscount) traits orderscount = customer orderscount if (customer? phone) traits phone = customer phone return traits }