Working with Product Variants When Building a Shopify Theme


One of the most crucial elements of any ecommerce site is the product page, and as a developer, it’s your responsibility to ensure your client’s products are easy to select and add to the cart. According to a study by Conversio, only eight percent of product page traffic converts to a sale. So, reducing customer effort on the product page, even if only by a few clicks, can have a significant effect on conversions.

Often, clients will want to prioritize specific product variants for greater visibility on the product page. This could be because a certain variant is on sale, or because demand is very high for it. In these cases, the merchant will want to make it as easy as possible for customers to add that variant to their carts—especially during fast-paced sales events like BFCM.

With careful use of Liquid, developers can use deep-links to automatically select particular variants on a product page. This allows clients to highlight key variants and minimize the number of mouse clicks their customers need to make during the sales flow.

In this article, I’ll demonstrate two practical ways to work with deep-linked product variants, and discuss best practices for making the customer experience more intuitive. 

If you’d like more tutorials on how to make browsing easier for buyers, you can also learn how to build a customizable related products section.

Template Icon

Diving into deep-links

To begin, we’ll need to understand how deep-linked variants work with Shopify product page URLs. For every variant of a product created on Shopify, there’s a unique variant ID. Our help docs show how variant IDs can be found.

It’s possible to create a deep-link directly to a specific variant by adding a query string to a product page URL. You can achieve this by appending the ?variant= query parameter to the URL of the product, along with the ID of the variant.

For example, if you wanted to link to the Small variant of a t-shirt, you could do so through a URL that looks like this:

In this example, the variant ID is 12207472312376. When the ?variant= query parameter is added to this URL, we are deep-linking to the small variant of the Ocean Blue Shirt.

This means that when this URL is clicked, the product page will load, containing all the information associated with the deep-linked variant. The correct drop-down option, product image, and price should be pre-selected when a deep-linked page loads.

Now we can use Liquid attributes and control-flow tags on the product-template section to output the attributes of this deep-linked variant to the different elements of the product page.

You might also like: How to Use Math Filters with Liquid.

Enabling variant deep-linking on the product page

The first step is to implement conditional Liquid logic when we are building our selection menu for product options. This will identify if a variant is deep-linked, and if so, will load this variant as the default selection in the product’s drop-down option box.

We’ll need to find the container which holds the selection menu, and use control-flow tags to create a set of instructions for product options. The code for this selection container could look like this:

A crucial attribute here is product.selected_or_first_available_variant, which returns the variant that is deep-linked if there’s a valid ?variant= query parameter in the URL. If there’s no valid deep-link in the URL, the first available variant is output.

If the variant ID in the URL matches with a variant in the current iteration of the for loop, it will output selected="selected", causing that option in the drop-down to be selected when the template is loaded.

It’s important to note that in order for a variant to be considered available, its variant.inventory_quantity must meet one of the following conditions:

  • Its variant.inventory_quantity is greater than zero
  • The product inventory itself is not being tracked by Shopify
  • Customers are able to purchase this product when it's out of stock

You might notice that there are additional control flow tags here too, which disable the selection box completely when no variants are available. This improves the user experience when a product is sold out, as it replaces the selection box with Sold Out text. However, it’s not necessary for pre-loading a specific variant.

In order for the correct product prices to be output, we could make use of the product.selected_or_first_available_variant syntax again, in places where the price and compare-at price would be displayed. These attributes would be product.selected_or_first_available_variant.price and product.selected_or_first_available_variant.compare_at_price, respectively.

However, another option is to use variable tags to set up a named variable for the currently-selected variant, which would make our code leaner and more readable. This could look like:

{%- assign current_variant = product.selected_or_first_available_variant -%}

Now, when you want to output the price of the selected product, you would use the variable current_variant.price or current_variant.compare_at_price, if you need the old price. This approach shortens the long lines of code and makes section files more legible for clients or other members of your team.

Similarly, you could create a variable for the selected variants image, which would allow you to avoid using verbose attributes when adding image-related code. This can be set up like:

{%- assign featured_image = product.selected_or_first_available_variant.featured_image | default: product.featured_image -%}

The easily written featured_image will now return the image associated with the currently selected variant, or the product’s own featured image. We can see here that the default Liquid filter is setting a default, or fallback value, in the case where the selected variant has no associated image.

Last but not least, to update the variant image as the user selects different variants, we’ll need to use JavaScript. This will add option selection functionality to the product page. Below is the function used on the Slate starter theme, which is called when a variant input changes:

This function also calls some other helper functions like _updateImages and _updateSKU, ensuring that when a customer switches variants, the correct data is loaded.

You might also like: How to Build for Modern Browsers (With Legacy Browser Support).

Enabling variant deep-linking on the cart page

Now that your clients can draw special attention to specific variants, we’d like the variant image to carry across to the cart page. This creates a continuous, consistent experience, and avoids the chance of a customer being confused if they see an image in their cart that they didn’t expect.

This means the product image visible on the cart page should be the selected variant image, rather than the product’s featured image. To display the variant image on the cart page, look for where you're outputting the featured_image attribute of the line item variable.

Instead of using an attribute like item.featured_image, we can simply use the item object with the img_url filter. For line items, img_url returns the URL of the line item's variant image. If the variant doesn’t have an assigned image, img_url returns the URL of the product's featured image.

Once this is set up, it could appear like this:

<img class="cart__image" src="{{ item | img_url: '95x95', scale: 2 }}" alt="{{ item.title | escape }}">

You can also see that we are applying a specific square size of 95 pixels to the image, as well as requesting a doubled pixel density. You can implement any size that suits the requirements of your client here. More options for this versatile filter can be found in our article on how to manipulate images with the img_url filter.

Finally, we want to ensure that the line item title links back to the selected product variant, rather than simply to the product. Since the line item is aware of what variant was added to the cart, it should deep-link back to the product's variant instead.

To achieve this, we can use the item.url attribute, which will always link to the variant itself. Other attributes like item.product.url or product.url would link to the product without deep-linking. To ensure a cohesive and consistent experience for customers, we should favor the deep-linked option, since this will reduce effort and support a seamless experience.

Variants have value

Pre-selecting product variants is a powerful approach for boosting conversions, as the checkout process becomes more streamlined. Making the customer experience more intuitive will add value to your clients’ stores and add some extra billable hours to your project. Hopefully with the help of this article, building this functionality will be a little bit faster.

Grow your business with the Shopify Partner Program

Learn more