Shopify Installation

Installing Heap on your Shopify store will allow you to track your shop’s click events and pageviews in real-time. Once installed, Shopify events will include data going back to the date you installed Heap.

🚧

Beginning March 15, 2023, Heap has observed occasional unexpected failures with Shopify’s integration service that results in degraded performance for Shopify event syncs to Heap. Customers may experience sync delays of 24-48 hrs for Shopify event data. All successfully synced customer event data from Shopify is persisted and data integrity will remain unaffected.

For Shopify event sync delays lasting more than 48-hours, kindly contact us via the Get support page. Customers may contact Shopify for additional follow-up/feedback on the issue.

Installation

To install Heap in your Shopify store, you will need to insert the code snippet below into your shop’s theme file.

Navigate in Shopify to the theme.liquid file associated with your shop’s theme. Follow Shopify’s Editing theme code instructions if you do not know how to access this file.

<script type="text/javascript">
    window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
    heap.load("YOUR_ENV_ID");
    var customerId = '{{ customer.id }}';
    var customerEmail = '{{ customer.email }}' || '{{ checkout.email }}';
    heap.addUserProperties({'Name': '{{ customer.name }}','email': customerEmail,'CustomerID':'{{ customer.id }}','TotalSpent':'{{ customer.total_spent }}'});   
</script>

Make sure the snippet is between the <head> tags:

Once you have saved the snippet, you will begin to see Shopify events coming into Heap via the Live data feed.

You can collect additional types of data, such as the customer's name or the total amount they spent, by adding them into the theme.liquid page via Heap's addUserProperties API. You can add as many calls as you want to this snippet.

Tracking Checkouts

In addition to the installation snippet, add one of the scripts below to your "Thank you" page. This will ensure that Heap is tracking checkouts.

The script you use will depend on if your shop has Shopify Plus or not. Please check if you use Shopify Plus to ensure you pick the correct script for your shop.

How to add a checkout snippet to your shop:

  1. In your Shopify account, navigate to Settings > Checkout and accounts > Checkout settings and find the Order Status section. Follow Shopify's instructions for customizing the order status page if you are unable to locate this section.
  2. Based on your use case, insert one of the below scripts into the Additional scripts box and click Save. You only need to use one of these scripts.

You DO NOT have Shopify Plus

Please remember to replace YOUR_ENV_ID with your Heap environment ID.

<script>
  window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
  heap.load("YOUR_ENV_ID");

  const flattenObject = (data, prefix) => {
    let result = {}
    for (const key in data) {
      let currentPrefix = key;
      if (prefix) currentPrefix =  prefix + '.' + key;
      if (typeof data[key] == 'object' && data[key] !== null) {
        const flatten = flattenObject(data[key], currentPrefix)
        result = { ...result, ...flatten }
      } else {
        result[currentPrefix] = data[key];
      }
    }
    return result
  }


  const formattedCurrencies = [
    'USD',
    'CAD',
    'GBP',
    'EUR'
  ]

   const getMoney = (objKey, amount) => {
     const withSubunitKey = `${objKey}_subunit`
     const curr = '{{ currency }}';

     if (!formattedCurrencies.includes(curr)) {
       return {
         [withSubunitKey] : amount
       };
     }

     return {
       [objKey]: amount / 100.00,
       [withSubunitKey]: amount
     };
   }

  {% if first_time_accessed %}
    window.Shopify?.checkout?.line_items?.forEach((item) => {
      heap.track("Purchased line item", {
        ...flattenObject(item),
        "order_id": {{ order_id }},
        ...getMoney("total_price", {{ total_price }}),
        "order_number": "{{ order_number }}",
        "customer_id": window.Shopify?.checkout?.customer_id
      });
    });

    // Remove line items from the checkout event. They were sent as individual events.
    let checkoutEventProperties = {
      "billing_address.country_code": window.Shopify?.checkout?.billing_address?.country_code,
      "billing_address.country": window.Shopify?.checkout?.billing_address?.country,
      "billing_address.city": window.Shopify?.checkout?.billing_address?.city,
      "billing_address.province": window.Shopify?.checkout?.billing_address?.province,
      "billing_address.province_code": window.Shopify?.checkout?.billing_address?.province_code,
      "currency": "{{currency}}",
      "customer_id": "{{ customer.id }}",
      ...getMoney("discounts.amount", {{ discounts_amount }}),
      "discount.code": window.Shopify?.checkout?.discount?.code,
      "payment_due": window.Shopify?.checkout?.payment_due,
      "billing_address.first_name": "{{ customer.first_name }}",
      "billing_address.last_name": "{{ customer.last_name }}",
      ...getMoney("gift_cards_amount", {{ gift_cards_amount }}),
      ...getMoney("line_items_subtotal_price", {{ line_items_subtotal_price }}),
      "order_name": "{{ order_name }}",
      "requires_shipping": {{ requires_shipping }},
      ...getMoney("shipping_rate.price", {{ shipping_price }}),
      "subtotal_price": window.Shopify?.checkout?.subtotal_price,
      ...getMoney("total_tax", {{ tax_price }}),
      ...getMoney("total_price", {{ total_price }}),
    };

    heap.track("Checkout", flattenObject(checkoutEventProperties));
    heap.addUserProperties({ "email": "{{ email }}", customer_id: window.Shopify.checkout?.customer_id });
  {% endif %}
</script>

You have Shopify Plus

If you have Shopify Plus, you will need to add the Heap snippet to yourcheckout.liquid file in addition to the theme.liquid file. If you do not add the Heap snippet to your checkout page, the snippet below will not work.

<script>
  const flattenObject = (data, prefix) => {
    let result = {}
    for (const key in data) {
      let currentPrefix = key;
      if (prefix) currentPrefix =  prefix + '.' + key;
      if (typeof data[key] == 'object' && data[key] !== null) {
        const flatten = flattenObject(data[key], currentPrefix)
        result = { ...result, ...flatten }
      } else {
        result[currentPrefix] = data[key];
      }
    }
    return result
  }


  const formattedCurrencies = [
    'USD',
    'CAD',
    'GBP',
    'EUR'
  ]

   const getMoney = (objKey, amount) => {
     const withSubunitKey = `${objKey}_subunit`
     const curr = '{{ currency }}';

     if (!formattedCurrencies.includes(curr)) {
       return {
         [withSubunitKey] : amount
       };
     }

     return {
       [objKey]: amount / 100.00,
       [withSubunitKey]: amount
     };
   }

  {% if first_time_accessed %}
    window.Shopify?.checkout?.line_items?.forEach((item) => {
      heap.track("Purchased line item", {
        ...flattenObject(item),
        "order_id": {{ order_id }},
        ...getMoney("total_price", {{ total_price }}),
        "order_number": "{{ order_number }}",
        "customer_id": window.Shopify?.checkout?.customer_id
      });
    });

    // Remove line items from the checkout event. They were sent as individual events.
    let checkoutEventProperties = {
      "billing_address.country_code": window.Shopify?.checkout?.billing_address?.country_code,
      "billing_address.country": window.Shopify?.checkout?.billing_address?.country,
      "billing_address.city": window.Shopify?.checkout?.billing_address?.city,
      "billing_address.province": window.Shopify?.checkout?.billing_address?.province,
      "billing_address.province_code": window.Shopify?.checkout?.billing_address?.province_code,
      "currency": "{{currency}}",
      "customer_id": "{{ customer.id }}",
      ...getMoney("discounts.amount", {{ discounts_amount }}),
      "discount.code": window.Shopify?.checkout?.discount?.code,
      "payment_due": window.Shopify?.checkout?.payment_due,
      "billing_address.first_name": "{{ customer.first_name }}",
      "billing_address.last_name": "{{ customer.last_name }}",
      ...getMoney("gift_cards_amount", {{ gift_cards_amount }}),
      ...getMoney("line_items_subtotal_price", {{ line_items_subtotal_price }}),
      "order_name": "{{ order_name }}",
      "requires_shipping": {{ requires_shipping }},
      ...getMoney("shipping_rate.price", {{ shipping_price }}),
      "subtotal_price": window.Shopify?.checkout?.subtotal_price,
      ...getMoney("total_tax", {{ tax_price }}),
      ...getMoney("total_price", {{ total_price }}),
    };

    heap.track("Checkout", flattenObject(checkoutEventProperties));
    heap.addUserProperties({ "email": "{{ email }}", customer_id: window.Shopify.checkout?.customer_id });
  {% endif %}
</script>

The Checkout custom event being sent into Heap has the properties available on the {{ checkout }} liquid object from Shopify. A list of the properties included in the {{ checkout }} object can be found in Shopify's checkout docs.

You’re ready to check out how many users are purchasing items from your site! For more help customizing your Shopify page, visit Shopify’s documentation.

Currencies

We format the following currencies in their main units: USD, CAD, GBP, and EUR.

For example, $1345.83 USD will have a total price of 1345.83 and total_price_subunit will be 134583.

If your currency is not included in the list above, the following properties will not be present:

  • total_price
  • total_tax
  • shipping_rate.price
  • line_items_subtotal_price
  • gift_cards_amount
  • discounts.amount

Instead, there will be a similar properties with _subunit appended to the name (ex: total_price_subunit). This value will be in the subunit of the currency, or the lowest amount of such currency that is available as legal tender. For example, 10 JPY will be parsed as 10.

📘

For customers using ReCharge Apps app with Shopify

Subscriptions by ReCharge is a popular eCommerce app that integrates with Shopify. To successfully track the entire customer journey across both Shopify checkout and ReCharge checkout, contact ReCharge support for assistance setting up ReCharge on your own domain. If you have any questions, feel free to contact [email protected]!

Tracking Identity (optional)

If you are unsure about your identity schema, see our Using Identify guide.

If you already call heap.identify with email in another part of your codebase, and you plan on sending Shopify data to the same Heap environment, use the email option listed below.

Do not use the heap.identify calls listed below if you use a different property (not email or customer id) to identify users. This will cause one user to show up as two distinct users and pollute your dataset.

Note that this only applies when you’re sending data to the same Heap environment.

Identities in Heap should always be globally unique for each unique user so you can track user activity across sites and platforms. When a user is identified, their past sessions and event activity from when they were anonymous are now tied to that identity. This allows the user to use multiple devices/browsers to access your website with a single identity.

Heap uses Shopify liquid variables to call the identify API, which look like this: {{ customer.email }}.

You can identify Shopify customers in Heap via their Shopify Customer ID or email. The Shopify Customer ID is the unique ID that Shopify assigns to each unique customer who shops in your store. You can learn more about this in Shopify's dev docs.

Here are some important considerations when choosing your identifier for Shopify:

  • If you have customers who check out with something besides email, such as if they signed up via their phone number, then you should use Shopify Customer ID as your identifier.
  • If you have multiple Shopify stores, and you want to analyze user activity across different stores, you should use email as your identifier. This allows you to track activity across your Shopify stores.
  • If you have a Shopify site and other sites not hosted by Shopify, you should use email as your identifier. This allows you to track user activity across different stores.

For an in-depth explanation of identity along with examples, see the Using Identify guide.

Identifying your users

If you want to identify your users, you’ll need to add one of the heap.identify calls below to your checkout page. Review the identity information above to choose the correct snippet.

  1. In your Shopify account, navigate to Settings > Checkout and accounts > Checkout settings and find the Order Status section. Follow Shopify's instructions for customizing the order status page if you are unable to locate this section.
  2. Paste the appropriate snippet before the closing script tag: </script>
var customerEmail = '{{ customer.email }}' || '{{ checkout.email }}';
    heap.identify(customerEmail);
var customerId = '{{ customer.id }}';
    heap.identify(customerId);

Known Limitations

  • We recommend that you have login enabled. If you do not have login enabled, we will not be able to identify users by their customer.id or customer.email until after they have completed the checkout process.

Multiple Shopify Stores

If you want to install Heap for multiple Shopify stores for cross-site tracking, reach out to us via the Get support page.