32 search results for “Keir Whitaker”

Customize Shopify Password Pages With the password.liquid Template

Customize Shopify Password Pages With the password.liquid Template

Customize Shopify password page

There will be occasions when you need to enable password protection on your own, or a client’s, Shopify store. This may be because the site is still being built and tested, or you need to make a quick change to the theme.

By default, Shopify allows you to add a custom message (which can include HTML) to the standard password protected page, but what if you're looking for even greater personalization?

In this tutorial, we'll show you the basics of customizing a password page on Shopify using the password.liquid template.

Continue reading

How to Use all_products in a Shopify Theme

How to Use all_products in a Shopify Theme

How to use all_products in a Shopify Theme

For this week's advanced Liquid Shopify tutorial, we'll be looking at a way to access product information without having to loop over a collection or be on a product detail page.

We can achieve this by using all_products. Here’s a quick example:

{{ all_products["coffee-cup"].title }}

Let’s have a look at what’s happening. The syntax is pretty simple: all_products takes a quoted product handle as it’s argument.

Liquid Handles

If you aren’t familiar with handles, the Shopify docs provide a great explanation:

The handle is used to access the attributes of a Liquid object. By default, it is the object's title in lowercase with any spaces and special characters replaced by hyphens (-). Every object in Liquid (product, collection, blog, menu) has a handle. For example, a page with the title "About Us" can be accessed in Liquid via its handle “about-us”.

In the above example, we have a handle of coffee-cup which represents the product available at yourstore.com/products/coffee. We follow that by .title. When rendered, this will output the title of the product with the handle of coffee-cup.

Using all_products we can access any property of the product:


Note that some of the returned values will be a Liquid collection and because of this would need to be “looped” over. Let’s use the images collection as an example:

{% for image in all_products["coffee-cup"].images %} ​
<img src="{{ image.src | img_url: 'grande' }}" /> ​
{% endfor %}

This example would output all of the images associated with the coffee-cup product.

More than one handle

You can go one step further and create a simple Liquid array of handles that you can use to output specific products. Here’s an example:

{% assign favourites = "hand-made-coffee-tamper|edible-coffee-cup" | split: "|" %}
{% for product in favourites %}
<li>{{ all_products[product].title }}<li>
{% endfor %}

Using the Liquid assign tag, we create a new variable called favourites, which are product handles separated by a | character. The | is used as a delimiter to divide the string into an array that we can loop over using for. 

We now have access to both products in turn and can output any property associated with it — in the example above I simply display the title.

When to use all_products

all_products is a great option when you need to pull out a couple of products in a particular template. Of course, if you are outputting a lot of products, a collection is still the best way forward — principally as you won’t have to manually know all the different product handles. However, all_products makes a great option when you have need of outputting a single, or small number of products, that won't change frequently.

You might also like: An In-Depth Look Into Designing a Shopify Theme

Continue reading

How to Use Liquid's "case/when" Control Tags in Shopify Themes

How to Use Liquid's "case/when" Control Tags in Shopify Themes

How to Use Liquid's case/when control tags

I am sure many of you are more than familiar with Liquid control tags such as if and else, but are you familiar with case/when?

Here's how the Shopify docs describe it:

Case/when creates a switch statement to compare a variable with different values. case initializes the switch statement, and when compares its values.

Here's an example:

{% assign handle = 'cake' %} {% case handle %}
{% when 'cake' %}
This is a cake
{% when 'cookie' %}
This is a cookie
{% else %}
This is not a cake nor a cookie
{% endcase %}


In this instance, the output will be determined when the variable called handle is "equal" to "cake" or is equal to "cookie". If neither condition evaluates to true, it will output the text after the last else clause.

If you omit the else clause and the handle variable never evaluates to true, no output will be output. This is because the else clause acts as a fallback in the above example.

Real world example

As nice as our example is, you might be wondering when you might use this in your own theme development.

One example I have used in the past is in relation to banners in a theme. Despite my love of alternate templates, there are occasions where creating a variety of templates simply to display different promotional banners would be very time-consuming. Not only would you have to build the templates, but you'd also have to assign them to each product in turn. A more practical approach is to let Shopify do the heavy lifting for you.

Let's say we wanted to display different promo banners on particular products. One way we could do this is to use product handles and case/when. This code example will work in a product.liquid template.

{% assign handle = product.handle %}
{% case handle %}
{% when 'coffee-cup' %}
{% include 'promo-coffee-cup' %}
{% when 'cup-saucer' %}
{% include 'promo-cup-saucer' %}
{% else %}
{% include 'promo-default' %}
{% endcase %}


We start off by creating a variable called handle and assign it the current value of product.handle. If you aren't familiar with handles then the docs have a great primer to get you started. Next we instantiate our case clause. What follows is a series of when statements.

In our example, if our product handle equals coffee-cup then the snippet titled promo-coffee-cup will be included and Shopify will head right to endcase and carry on.

Alternatively, if the product handle is equal to cup-saucer then the snippet titled promo-cup-saucer will be included. If the product handle is neither coffee-cup or cup-saucer then the else clause kicks in and the snippet titled promo-default will be output.

We have achieved quite a lot with a little. We are conditionally loading different snippets depending on the product being viewed and outputting a default promo banner if neither condition is met. We've also achieved this without having to create any alternate templates.

To extend the example, you could simply add in further specific product handles when needed. However, an alternative approach might be needed if you wanted to include tens of different banners. Of course, there's many different ways to achieve the same thing in Liquid and in a future tutorial we'll look at how to use other Liquid constructs such as contains and unless to achieve similar results.

You might also like: Ways to Customise the img element in Shopify Themes

Continue reading

How URLs Map to Shopify Templates

How URLs Map to Shopify Templates

shopify tutorial- how URLs map to Shopify themes

One of the (many) features I love about working with Shopify Themes is the simple folder structure. Each store can be powered by a single layout file and a handful of templates meaning you can achieve a lot with a little — power in simplicity.

However if you are new to Shopify Themes, you may not know exactly when each template gets rendered, or be aware that the same template gets used in various places around the store.

We've already looked at how to use both alternate layout and template files, therefore in this article we'll turn our focus to understanding under what conditions each template is rendered in a store.

URL template mapping

Internally, Shopify has its own routing table which determines which template is displayed based on the URL requested by the user. If you have ever used one of the popular development frameworks, you might be familiar with the concept of URL routing. Put simply it's a way of determining which template to send to the browser based on the requested URL.

I mentioned earlier that there are only a handful of templates required to power a store. Each of these templates serves one or more URL — in other words, we are able to utilise the same templates for multiple URLs. From a design perspective, this enables us to reduce our overhead when building a new store.

You might also like: Using Metafields in Your Shopify Theme

URLs to templates

Here's an overview of which template is rendered as determined by the URL:

/thisisntarealurl → 404.liquid
/blogs/{blog-name}/{article-id-handle} → article.liquid
/blogs/{blog-name} → blog.liquid
/cart → cart.liquid
/collections → list-collections.liquid
/collections/{collection-handle} → collection.liquid
/collections/{collection-handle}/{tag} → collection.liquid
/ → index.liquid
/pages/{page-handle} → page.liquid
/products → list-collections.liquid
/products/{product-handle} → product.liquid
/search?q={search-term} → search.liquid

Password protected

You might have noticed that the password.liquid template is not included in the list. This template is only seen if you choose to password protect your storefront and as such will override all other URLs.

If your store is password protected and you do not have a password.liquid template in your theme, Shopify will render it's default password login page instead.

Alternate templates

It's also worth remembering that the above routing table can be affected by alternate templates — something we have covered in a previous tutorial.

URL parameters

As you will see above, a number of the routes have elements of the URL path wrapped in { }. I have included this to denote a variable which will have an impact on the data loaded into a template.

For example, if we take the /collections/{collection-handle} URL pattern a different set of data will be loaded into the template and sent to the browser if we requested /collections/bikes compared to /collections/cars.

You will also notice that a number of different URL patterns share the same template file, e.g /products and /collections will both render the list-collections.liquid template. Likewise /collections/, /collections/{collection-handle}/ and /collections/{collection-handle}/{tag} all make use of collection.liquid.

Final note

If you are ever unsure which template is being rendered, there's a really simple way to check.

All you need to do is add {{ template }} to your theme.liquid file and start browsing your store. This global Shopify variable will output the currently rendered template minus the .liquid extension. It's a neat way to be doubly sure your templates are working as expected.

Here's a handy snippet that you can use in your own theme development with the output shown in the screenshot below:

<p style="display: inline-block; background: yellow; border: 1px solid #CCC; padding: 1em; font-weight: 700;">Current template: {{ template }}.liquid</p>

How URLs Map to Shopify Templates: Keir Whitaker's site

Want to learn more about building with Shopify? Check out our full list of Shopify tutorials.

You might also like: How to Optimize Themes for Performance

Continue reading

PODCAST: How Do We Build Profitable, Long-Term Relationships With Customers?

PODCAST: How Do We Build Profitable, Long-Term Relationships With Customers?


In their fourth Ecommerce Lifecycle podcast, Keir and Ross turn their attention to the subject of retention. This focuses on ways in which we can get customers to continue coming back and purchasing products. Having long-term relationships with customers who have already purchased from you can be highly profitable as your “cost per acquisition” reduces.

Continue reading

PODCAST: How Do We Help Clients With Fulfillment?

PODCAST: How Do We Help Clients With Fulfillment?


In part two of “The Ecommerce Customer Lifecycle,” Ross and I discussed "conversion" – ways in which we can help our clients get visitors to their ecommerce stores to purchase products and services. In particular, we looked at how user experience, design, branding and content all play a key role in this process.

In our third episode, we turn our attention to the often overlooked topic of fulfillment. Whilst on first glance you might think that it's a simple case of putting a product in a box and adding a postage label, there are plenty of other factors to consider – many of which will help your clients showcase themselves and their brand values.

Continue reading

PODCAST: How to Convert Your Client's Visitors Into Customers

PODCAST: How to Convert Your Client's Visitors Into Customers


In part one of “The Ecommerce Customer Lifecycle,” we focused our attention on the “acquisition” phase  and asked the question: “How can we get potential customers to visit our sites?” Tactics discussed included social media, paid advertising, influencer marketing, among others.

In our second episode, we move on to discuss “conversion” which focuses on getting the visitors of your website to actually purchase products. This step is where user experience, design, branding, content and your on-site strategy are crucial.

Let's take a look at how to improve conversion on your client's store

Continue reading

PODCAST: How To Get Visitors to Your Client's Website

PODCAST: How To Get Visitors to Your Client's Website

Podcast: How to Convert Your Client's Visitors Into Customers

Sometimes remarks made in jest turn actually turn into the best ideas.

A few weeks ago, Ross and I were chatting about his upcoming Shopify workshop in Boston. During the conversation, he referred me to a blog post he’d written about a “framework” that his company Growth Spark has developed to guide the process of kicking off a new ecommerce client project. After having read it, I jokingly said that it would make a great podcast series. Little did I know we'd be producing it a few weeks later.

Earlier this month, Ross, myself and our respective Blue Yetis sat down and recorded episode one of a four (maybe five – we’ll get to that) part series called “The Ecommerce Customer Lifecycle: Acquisition” which you can listen to in this post.

Continue reading

Shopify Tutorial: The product.liquid template

Shopify Tutorial: The product.liquid template

So far in our Shopify tutorial series we've looked at a lot of concepts relating to how Liquid works in Shopify themes. In this article, I'd like to take a more in-depth look at one particular template — product.liquid.

If you are new to Shopify themes, product.liquid is the template that is rendered by default whenever a customer views a product detail page. As discussed in a previous tutorial, it is also possible to have alternate product templates, however in this post we'll stick to the basic template, which resides in the templates folder within a Shopify theme.

By way of an example, I am going to use the product.liquid template from my own starter theme “Birthday Suit”. Here it is in its entirety:

<h2>{{ product.title }}</h2>
{{ product.description }}
<form action="/cart/add" method="post" enctype="multipart/form-data">
<select name="id">
{% for variant in product.variants %}
{% if variant.available == true %}
<option value="{{variant.id}}"> {{ variant.title }} for {{ variant.price | money_with_currency }}</option>
{% else %}
<option disabled="disabled"> {{ variant.title }} - sold out!</option>
{% endif %}
{% endfor %}
<input type="submit" name="add" id="add" value="Add to Cart" class="button">

As you will see, there's very little HTML in this template. This is on purpose as it's intended as a starting block for your own theme. If you download a theme from the Shopify theme store, you'll notice that the product.liquid template will be more involved but may not actually contain much more Liquid code.

Let's examine what's happening in detail. We begin by using Liquid output to display the product's title and description:

<h2>{{ product.title }}</h2>
{{ product.description }}

As the description is entered via the Shopify admin, we don't need to wrap this output with further HTML. Of course, if you need to add in a wrapper element of some sort then you can.

Moving down the template, we come to the form and opening <select> element:

<form action="/cart/add" method="post" enctype="multipart/form-data">
<select name="id">

The action attribute is important – it must be set to /cart/add in order for products to be added to the cart. We also need to ensure that the <select> element has its name attribute set to id.

Next comes the main output of the template:

{% for variant in product.variants %}
{% if variant.available == true %}
<option value="{{variant.id}}"> {{ variant.title }} for {{ variant.price | money_with_currency }}</option>
{% else %}
<option disabled="disabled"> {{ variant.title }} - sold out!</option>
{% endif %}
{% endfor %}

A few things are at work here:

  • We create a for loop to iterate over all the current products variants
  • We check to see if the current product in the loop has inventory using {% if variant.available == true %}
  • If the product has inventory, we output the title in an <option> element and set the value of the <option> to the variants id. As well as outputting the variant title, we output the price and use the money_with_currency filter.
  • If the product has no inventory, we output a disabled <option> element and output the title followed by sold out!
  • Finally, we close off our if statement and for loop

Next we add in a <input type="submit"> that when clicked will add an available product to the cart:

<input type="submit" name="add" id="add" value="Add to Cart"> </form>

We complete the template by closing out the </form> element.

This template makes use of both the product and variant objects. They have a large range of properties that you can display in this template and are worth investigating as you develop your Shopify theme skills.

You might also like: 10 Top Questions About Developing Shopify Themes Answered

Extending the template

Of course this example is relatively simplistic and is intended as a starting point for your own development. There's a lot more you could include in this template including:

  • Adding in Liquid code to display product and variant images
  • Use the Shopify JavaScript snippet option_selection.js to allow better display of variant options
  • Use the | t filter for retrieving translated strings from your theme's locale file

Continue reading

Grow your business with the Shopify Partner Program

Learn more