Integrate into Shopify Themes built with Liquid

This guide will walk you through Purple Dot's Platform integration into any Shopify store built with Liquid Templates. If you are using our Shopify App, please seeInstalling our Shopify App instead. See Purple Dot Overview for the comparison of our Shopify App vs. Platform integrations.

This will allow you to turn the Purple Dot integration on and off without any code changes.

  • Clone your currently live theme to make a new preview theme

  • In config/settings_schema.json add the following

    {
      "name": "Purple Dot",
      "settings": [
        {
          "type": "checkbox",
          "id": "use_purpledot",
          "label": "Turn on Purple Dot integration"
        }
      ]
    }
  • In config/settings_data.json add the following

    "use_purpledot": true,

  • In the preview theme create a new snippet and name it purple-dot.liquid

  • In layout/theme.liquid find the closing </head> tag and place the following code just before it

    {% if settings.use_purpledot %} 
      {% render 'purple-dot' %}
    {% endif %}
  • If your theme still uses checkout.liquid find the closing </head> tag and place the following code just before it

    {% if settings.use_purpledot %} 
      {% render 'purple-dot' %}
    {% endif %}
    
    <script type="text/javascript">
      window.PurpleDotConfig.checkoutLineItems = [
        {% for line_item in checkout.line_items %}
          {
            preorder_state: '{{ line_item.variant.metafields['purple-dot'].preorder_state }}'
          },
        {% endfor %}
      ];
    </script>
    
    {% comment %}
    Purple Dot has support for Checkout Extensibility, please reach out to support@getpurpledot.com after making the switch to update your Purple Dot integration.
    {% endcomment %}

We will use purple-dot.liquid as the place where all other Purple Dot related code lives. It is being rendered from the header as it is required to run on every single page in your Shopify store for Purple Dot to function correctly.

Paste the following snippet into purple-dot.liquid

<script>
  window.PurpleDotConfig = {
    shopifyCart: {{ cart | json }},
    shopifyCartString: {{ cart | json | json }},
    shopifyCartSignature: {{ cart | json | hmac_sha256: 'SHARED_SECRET' | json }},
    prefillEmail: '{{ customer.email }}',
    prefillShippingAddress: {{ customer.default_address | json }},
  };
</script>
<script src="https://www.purpledotprice.com/api/v1/init.js?apiKey=PUBLIC_API_KEY"></script>

Replace SHARED_SECRET and PUBLIC_API_KEY with the public API key and shared secret of your Purple Dot store, which can be found at the bottom of the Integration settings page in the Merchant Portal.

Purple Dot offers 3 different methods for shoppers to buy pre-order products

  • Combined Cart (the default)

  • Separate Cart

  • Express

If you want to use a non-default checkout method, please create a new script tag before init.js that will use window.PurpleDotConfig to specify this:

  • To use Separate Cart

    <script>
      window.PurpleDotConfig = {
        checkoutMethod: 'SEPARATE_CART',
      };
    </script>
    <script src="https://www.purpledotprice.com/api/v1/init.js?apiKey={{settings.purpledot_api_key}}"></script>
  • To use Express

    <script>
      window.PurpleDotConfig = {
        checkoutMethod: 'EXPRESS',
      };
    </script>
    <script src="https://www.purpledotprice.com/api/v1/init.js?apiKey={{settings.purpledot_api_key}}"></script>

If you do not know which checkout method you would like to integrate, contact us for more information.

Each checkout method may require some specifics to work with your store's theme.

No extra configuration is necessary

No extra configuration is necessary

  1. Configure the cart placement

window.PurpleDotConfig = {
  ...
  cart: {
    // Icon styles
    fill: '#000000',
    strokeWidth: '1.5px',
    matchFill: '.icon--cart',
    width: '22px',
    height: '22px',
    // Function to place the cart element onto the page
    placeElement: (cartElement, cartLink) => {
      const cartLinkContainer = cartLink.parentElement;
      const pdCartContainer = cartLinkContainer.cloneNode();
      // Adjust these next two lines to your DOM, if necessary
      pdCartContainer.appendChild(cartElement);
      cartLinkContainer.insertAdjacentElement('beforebegin', pdCartContainer);
      // Returns the container element
      return pdCartContainer;
    },
  },
};

Unexpected DOM structure?

Sometimes, you may find empty elements with padding/margin etc., if the theme you're working on is different to the one assumed in our previous example. If this is the case, you can set up a mutation observer on an ancestor of the cart icon like so:

// Function to place the cart element onto the page
placeElement: (cartElement, cartLink) => {
  const cartLinkContainer = cartLink.parentElement;
  const pdCartContainer = cartLinkContainer.cloneNode();
  const nav = document.querySelector('nav.Header__SecondaryNav');
  // Define observer callback
  const observer = new MutationObserver(() => {
    const iframe = document.querySelector('iframe.purple-dot-frame');
    if (iframe.style.display === "none") {
      pdCartContainer.style.display = "none";
    } else {
      // May need to adjust this line to suit your theme
      pdCartContainer.style.display = "inline-block";
    }
  });
  // Adjust these next two lines to your DOM, if necessary
  pdCartContainer.appendChild(cartElement);
  cartLinkContainer.insertAdjacentElement('beforebegin', pdCartContainer);
  // Set up observer:
  // IMPORTANT: 'attributes' must be true, as iframe.style.display will change
  observer.observe(nav, { attributes: true, childList: true, subtree: true });
  // Returns the container element
  return pdCartContainer;
},
  1. Configure variant selectors on a PDP

Sometimes, a PDP will have variant selectors that show the variant as sold out, even though the variant is available for preorder. In this case, we can target these elements, and remove a 'disabled' class (or similar) from them in order to 'enable' them.

There are two ways of selecting elements (depending on whether or not they are inside an ATC form), but you must always provide a class to remove.

window.PurpleDotConfig = {
  ...
  pdp: {
    variantSelector: {
      // CSS selector to be queried for inside the ATC form
      selector: '.some-selector',
      // Find variant selector elements that are outside the ATC form
      find: () => document.querySelectorAll('.another-selector'),
      // Class to remove to enable the variant
      disabledClass: 'disabled',
    },
  },
};

Modify existing PDP/PLP page behaviour

We support a number of customisations to Product Detail Pages (PDP) and Product Listing Pages (PLP) that may be required.

Out of the box, when the shopper selects a variant that is on pre-order through Purple Dot, we will hide the following on every PDP because we do not support them in our checkouts:

  • Shopify payment buttons

  • Klarna messaging

  • Klaviyo notify me buttons

  • as well as others

If you would like to hide some elements on PLPs or PDPs, simply add a pdp.hide or plp.hide attribute with an array of selectors to instruct Purple Dot to hide these if the selected variant will be on pre-order

If you would like to show some elements on PDPs, create them in your theme with display:none and then add a pdp.show attribute with an array of selectors to instruct Purple Dot to display these if the selected variant will be on pre-order.

window.PurpleDotConfig = {
  ...
  pdp: {
    hide: ['<SELECTOR>'],
    show: ['<SELECTOR>'],
  },
  plp: {
    hide: ['<SELECTOR>'],
  },
};

To modify the quick view/add components on a PLP for any product that is on pre-order

window.PurpleDotConfig = {
  ...
  plp: {
    quickAdd: {
      // Optional selector that targets the title element within a collection item
      title: '',
      // Optional string that will be used in place of the existing text
      newTitle: '',
      // Optional selector for a size selector element which Purple Dot will
      // transform to link through to the PDP
      sizeSelector: '',
      // Class used to disable the size selector if the variant is sold out.
      // Purple Dot will remove this if the variant is available for pre-order
      disabledClass: '',
      // Useful if you need to remove some attributes from some elements
      removeAttributes: [{
        selector: '',
        attributes: [''],
      }],
    },
  },
};

Automatically apply discount

The provided discount will be applied to every checkout involving a line item on preorder.

window.PurpleDotConfig = {
  ...,
  discountCode: <discount code>,
};

Enable pre-order stock notification

Purple Dot will email the subscribed shoppers when the product is back on pre-order. Please note: this feature is only supported by EXPRESS and SEPARATE_CART checkout methods.

window.PurpleDotConfig = {
  ...
  enableNotifyMe: true,
};

Tracking pre-orders

The Purple Dot SDK can automatically forward events to various product analytics, ad and order tracking platforms. You can activate these integrations from the Integration settings page in the Merchant Portal. See Pre-order tracking for more information about these integrations.

Restrict Purple Dot to some markets

Some merchants handle multiple markets with one Shopify store, with checkout handled by another service like Global-E. Purple Dot does not currently support integrating with other checkout providers and so in these cases you can hide Purple Dot in markets you do not wish to offer pre-orders in.

With Global-E

window.PurpleDotConfig = {
  ...,
  enableWaitlists: () => {
    // Show Purple Dot to UK shoppers only
    return new Promise((resolve, reject) => {
      const interval = setInterval(() => {
        try {
          let waitlistsEnabled;
          if (window.GLBE_PARAMS && window.GLBE_PARAMS.countryCode) {
            waitlistsEnabled = window.GLBE_PARAMS.countryCode === 'GB';
          } else if (window.GlobalE && window.GlobalE.Country) {
            waitlistsEnabled = window.GlobalE.Country === 'GB';
          }
          if (waitlistsEnabled !== undefined) {
            clearInterval(interval);
            resolve(waitlistsEnabled);
          }
        } catch (err) {
          clearInterval(interval);
          reject(err);
        }
      }, 100);
      setTimeout(reject, 10000);
    });
  },
};

With Shopify

window.PurpleDotConfig = {
  ...,
  enableWaitlists: () => {
    return new Promise((resolve, reject) => {
      fetch('/browsing_context_suggestions.json')
        .then(response => response.json())
        .then(data => {
          if (data?.detected_values?.country?.handle) {
            resolve(data.detected_values.country.handle === 'US');
          } else {
            resolve(true);
          }
        })
        .catch(error => {
          reject(error);
        });
    });
  },
};

Localise the Pre-order button

Currently we support English, Spanish, German and Dutch.

The correct locale will be automatically detected in most cases but if you wish to override it you can set it yourself.

window.PurpleDotConfig = {
  ...,
  locale: 'es-ES',
};

You can also provide your own copy if you like.

window.PurpleDotConfig = {
  ...,
  translations: {
    'es-ES': { 
      addToCart: 'Añadir a la cesta',
      preorderCTA: 'Resérvalo',
    }
  }
};

Styling

You may find that you need to style some components on a page differently when a waitlisted variant is selected. In this case, you can add the styles param to your PurpleDotConfig.pdp.

A good example of this would be when our 'Waitlist powered by' content is being added incorrectly to the PDP. Our code adds the waitlist content underneath the 'Pre-order' button (in the DOM), but if the button is in a flex container with flex-direction: row, the waitlist info will be added to the side of the button.

We can solve this using CSS, which will only be applied if the selected variant is on pre-order, and will be removed when the selected variant is not on preorder. We can also specify multiple style rules, if needed, and change values based on screen size, e.g. mobile screens.

window.PurpleDotConfig = {
  ...
  // 'styles' must be inside 'pdp', not 'plp'
  pdp: {
    styles: {
      preorder: [
        {
          selector: '.product__buy-buttons',
          style: 'flex-wrap: wrap'
        },
        {
          media: 'only screen and (max-width: 600px)',
          selector: '.product__add',
          style: 'width: 100% !important'
        },
        {
          media: 'only screen and (min-width: 600px)',
          selector: '.product__add',
          style: 'width: 50% !important'
        },
      ]
    }
  }
};

The self-service portal allows your customers to see their pre-order history and cancel pre-orders before they are fulfilled. We recommend hosting the self-service iframe on a new page - e.g. /pages/manage-pre-orders - that is linked from your support pages, similar to how a returns portal would be.

The title of the page should be Manage Pre-orders

The following snippet can be placed on a Shopify page by editing the page's HTML:

<purple-dot-self-service />

Please refer to Test the Platform Integration.

  • Publish the preview theme

  • Set up Waitlists in your Purple Dot Merchant Portal

Last updated