> For the complete documentation index, see [llms.txt](https://docs.getpurpledot.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.getpurpledot.com/docs/shopify-stores/integrate-purple-dot-with-your-storefront/integrate-into-shopify-themes-built-with-liquid.md).

# Integrate into Shopify Themes built with Liquid

#### [1. Enable Purple Dot in your theme](#id-1.-enable-purple-dot-in-your-theme)

Having completed [Install our app](/docs/shopify-stores/install-our-app.md)

1. Navigate to a theme where you wish to test Purple Dot
2. Click "Edit theme", then "App embeds" on the sidebar of the theme code editor
3. Search for "Purple Dot"
4. Provide the "Purple Dot API Key" and "Purple Dot Shared Secret" values that you can find at the bottom of the Integrations page in our [Merchant Portal](https://www.purpledotprice.com/merchant-portal)
5. Enable the embed and save the theme

#### [2. Add the Shopper Portal](#id-6.-add-the-shopper-portal)

The shopper portal allows your customers to see their pre-order history and cancel pre-orders before they are fulfilled.&#x20;

We recommend hosting the shopper portal 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 should be placed on a Shopify page by editing the page's HTML:

```
<purple-dot-self-service />
```

#### [**3. Configure Separate Cart (optional)**](#id-3.-configure-separate-cart-optional)

If your preferred checkout method is to use a separate cart, there is some additional configuration required to place the separate cart icon and enable the variant selectors on liquid theme:

1. **Configure the cart placement**

```js
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;
    },
  },
};
```

{% hint style="info" %}
**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:
{% endhint %}

```js
// 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;
},
```

2. **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.

```js
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',
    },
  },
};
```

<br>
