Shopify themes, liquid, logos, and UX
If you have products that are out of stock, you can sell them as pre-orders. This is done by creating an alternate product template, and editing your payment settings. You can also use this customization to continue selling products that are on back-order.
Note: This customization isn't compatible with dynamic checkout buttons. If your theme supports dynamic checkout, then prevent the buttons from showing by following the steps to hide dynamic checkout buttons on product pages.
Sectioned and non-sectioned themes
The steps for this tutorial differ depending on whether you are using a sectioned or a non-sectioned theme. A sectioned theme is a newer theme that lets you drag and drop to arrange the layout of your store's pages.
To figure out whether your theme supports sections, go to the theme's Edit code page. If there are files in the Sections directory, you are using a sectioned theme. Non-sectioned themes were released before October 2016, and do not have files in the Sections directory.
If you are using a sectioned theme, then click the Sectioned themes button and follow the instructions. If you are using an older, non-sectioned theme, then click the Non-sectioned themes button and follow the instructions.
TyW | Online Community Manager @ Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit the Shopify Help Center or the Shopify Blog
I would be so grateful If you have time to send me code modification please, that's the only thing missing for me !!! thank you so much @Alex-Miller
I am using Warehouse Theme. I cannot find these codes,
addToCart: {{ 'products.product.add_to_cart' | t | json }},
<span data-add-to-cart-text>
{% unless current_variant.available %}
{{ 'products.product.sold_out' | t }}
{% else %}
{{ 'products.product.add_to_cart' | t }}
{% endunless %}
</span>
Hope you can help me. Thanks.
This pre-order option looks like it could work really well for me. For those of you who have tried it, please let me know how the buttons work. If I change my product to the pre-order template but only set one variant to allow ordering when out of stock, do my other variants still show the 'buy now' and 'out of stock' buttons?
This was so helpful! Thank you for doing this! if anyone is looking for how they can delete the buy it now button here's a link to that! https://community.shopify.com/c/Shopify-Design/Removing-quot-Buy-it-Now-quot-button-on-some-of-my-pr...
Hello I followed this and it worked thank you! Can someone explain additionally how to add a ship date message to appear along with the pre order button so customers know when to expect shipping?
I managed to get around this by replacing the text between the comment tags below
{%- comment -%}
Live region for announcing updated price and availability to screen readers
{%- endcomment -%}
with
This product is temporarily out of stock, but you can PRE-ORDER it now and we will put it into production and deliver it to you as soon as possible. Payment is due at the time of purchase, and you will receive a shipping notification once the order is on its way to you.
in the product-pre-order-template.liquid code in the debut theme
Just replace the message with whatever you feel is appropriate.
Nice tutorial
Where / when will this message pop up? Thanks for the comment btw! I successfully have added the pre-order button & removed the BIN button but now I want to make sure the customer knows the item is on pre-order.
My template doesn't seem to have
<span data-add-to-cart-text>
{% unless current_variant.available %}
{{ 'products.product.sold_out' | t }}
{% else %}
{{ 'products.product.add_to_cart' | t }}
{% endunless %}
</span>
instead it has
<link itemprop="availability" href="http://schema.org/{% if current_variant.available %}InStock{% else %}OutOfStock{% endif %}">
{% include 'product-form' %}
What can i do?
I have the new Express Theme and I can't find this code
addToCart: {{ 'products.product.add_to_cart' | t | json }},
Help anyone ?
I am using minimal and this part isn't there..
addToCart: {{ 'products.product.add_to_cart' | t | json }},
In fact this is the only code I have..
{% comment %}
The contents of the product.liquid template can be found in /sections/product-template.liquid
{% endcomment %}
{% section 'product-pre-order-template' %}
{% section 'product-recommendations' %}
(It's also not in the sections)
Anyone able to help please?
did you ever get an answer to this?
I followed the step by step instruction but i could not find the following script that need to look for in product.pre-order.liquid file.
addtocart {{ 'Pre-order' | json }},
My template is Canopy please can you help.
For anyone looking to find the "missing code" I finally found the answer.
You can usually find the script in theme.liquid - but you cannot use the same code listed here as it will change ALL buttons to pre-order.
Instead replace it with the line:
addToCart: {%- if template.suffix == 'pre-order' -%}{{ 'Pre-order' | json }}{%- else -%}{{ 'products.product.add_to_cart' | t | json }}{%- endif -%}
This is in response to samueldthomas "missing code" comment:
Thank you this worked for me. One thing to note, when I copied and replaced this line of code verbatim it broke my nested menu. When I added the "," to the end of the line of code it worked perfectly.
Hi There
Thank you for you help , notes for pre -order ,
I have a problem from the begin ,
I have created a pre-order-templet but there is no add_to_cart line at all after <script> line there is nothing instead of lines for other Apps.
I will appreciate very much if you could help me as I donot like to add another app for pre order .
Thanks
I have done all the steps for the debut theme, however when I click my pre-order product the product won't open. It says "Liquid error: Error in tag 'section' - 'product-pre-order-template' is not a valid section type".
Any ideas on where I made a mistake and how to fix it.
Did you ever get an answer? This is the issue with mine
Hi! Yes i solved this today!!
(Hat tip to @John_G2 for the inspiration to loop through the variants for their policy and quantity in liquid INSIDE the JS)
You can check the example on my development shop:
https://aimhuge-dev-dec20.myshopify.com/products/product-preorder
Password is 123456 (check the catalog → product-preorder)
How to do it?!
1. Followed the tutorial linked on the first page of this thread to create a new template option for products that allow preorder
2. BUT skip this part of the tutorial
3) Replace the product strings bit of script in product.pre-order.liquid
<script>
theme.productStrings = {
addToCart: {{ 'products.product.add_to_cart' | t | json }},
unavailable: {{ 'products.product.unavailable' | t | json }},
sold_out: {{ 'products.product.sold_out' | t | json }}
}
</script>
with the following:
<script>
// Override default values of shop.strings for each template.
// Alternate product templates can change values of
// add to cart button, sold out, and unavailable states here.
// | t filter translates from strings files
// there is no Pre-order string my default, so we add it without the t filter
theme.productStrings = {
addToCart: {{ 'products.product.add_to_cart' | t | json }},
unavailable: {{ 'products.product.unavailable' | t | json }},
sold_out: {{ 'products.product.sold_out' | t | json }},
preorder: {{ 'Pre-order' | json }}
}
// inventory quantity and policy were depercated from liquid
// https://community.shopify.com/c/API-Announcements/Deprecated-Notice-inventory-quantity-and-inventory-policy-fields/m-p/419770
// but can be accessed by reading the product into a variable
// and backfilling the inventory quanity & policy into the product
const product = {{ product | json}}
let v;
{% for variant in product.variants %}
v = getVariantById({{ variant.id}})
v.inventory_quantity = {{ variant.inventory_quantity | json }}
v.inventory_policy = {{ variant.inventory_policy | json }}
{% endfor %}
// then we just change the text of the CTA when the select is changed
document.querySelector('.single-option-selector').onchange = ()=>{
const selectEl = document.querySelector('[name="id"]') // the select
const cta = document.querySelector('.product-form__cart-submit') // the CTA
setTimeout(()=>{ // requires a little delay for some reason
const [options] = getSelectedOptions(selectEl)
const variant = getVariantById(parseInt(options.value))
if(variant.inventory_quantity > 0 ){
cta.textContent = theme.productStrings.addToCart
} else if( variant.inventory_policy === "continue" ){
cta.textContent = theme.productStrings.preorder
} else {
cta.textContent = theme.productStrings.sold_out
}
},5)
};
// fire the event on page load (check if it's pre-order)
document.querySelector('.single-option-selector').onchange()
// helper functions
function getVariantById(id){
const [variant] = product.variants.filter( (v) => v.id === id )
return variant
}
function getSelectedOptions(selectEl) {
const result = [];
const options = selectEl.getElementsByTagName('option');
for (let i = 0; i < options.length; i++) {
if (options[i].selected)
result.push(options[i]);
};
return result;
}
</script>
CC @Jennifer42
Script updated to handle products with only one variant (aka no variant selector)
<script>
// Override default values of shop.strings for each template.
// Alternate product templates can change values of
// add to cart button, sold out, and unavailable states here.
// | t filter translates from strings files
// there is no Pre-order string my default, so we add it without the t filter
theme.productStrings = {
addToCart: {{ 'products.product.add_to_cart' | t | json }},
unavailable: {{ 'products.product.unavailable' | t | json }},
sold_out: {{ 'products.product.sold_out' | t | json }},
preorder: {{ 'Pre-order' | json }}
}
// inventory quantity and policy were depercated from liquid
// https://community.shopify.com/c/API-Announcements/Deprecated-Notice-inventory-quantity-and-inventory-policy-fields/m-p/419770
// but can be accessed by reading the product into a variable
// and backfilling the inventory quanity & policy into the product
const product = {{ product | json}}
let v;
{% for variant in product.variants %}
v = getVariantById({{ variant.id}})
v.inventory_quantity = {{ variant.inventory_quantity | json }}
v.inventory_policy = {{ variant.inventory_policy | json }}
{% endfor %}
const selectEl = document.querySelector('[name="id"]') // the select
const cta = document.querySelector('.product-form__cart-submit') // the CTA
const currentVariant = getVariantById({{product.selected_or_first_available_variant.id}})
// fire the event on page load (check if it's pre-order)
updateCTA(currentVariant, cta)
// then we just change the text of the CTA when the select is changed
document.querySelector('.single-option-selector').onchange = ()=>{
setTimeout(()=>{ // requires a little delay for some reason
const [options] = getSelectedOptions(selectEl)
const variant = getVariantById(parseInt(options.value))
updateCTA(variant, cta)
},5)
};
// helper functions
function getVariantById(id){
const [variant] = product.variants.filter( (v) => v.id === id )
return variant
}
// update the cta based on the inventory quantity and policy
function updateCTA(variant, ctaEl){
if(variant.inventory_quantity > 0 ){
return ctaEl.textContent = theme.productStrings.addToCart
} else if( variant.inventory_policy === "continue" ){
return ctaEl.textContent = theme.productStrings.preorder
} else {
return ctaEl.textContent = theme.productStrings.sold_out
}
}
function getSelectedOptions(selectEl) {
const result = [];
const options = selectEl.getElementsByTagName('option');
for (let i = 0; i < options.length; i++) {
if (options[i].selected)
result.push(options[i]);
};
return result;
}
</script>
Hi @Alex-Miller ,
Thank you for providing the tutorial for adding pre-order function for variants! I'm using debut theme (Shop Link) and was able to follow the steps until step 3 as I have a much longer code than yours with the "theme.productStrings" part of product.pre-order.liquid and I'm not sure which part should be replaced. I attached the full script of my product.pre-order.liquid below. Grateful for your advice the steps forward, please. Thanks in advance!
Yours:
Mine:
{% comment %}
The contents of the product.liquid template can be found in /sections/product-template.liquid
{% endcomment %}
{% section 'product-pre-order-template' %}
{% section 'product-recommendations' %}
<div id="backToCollection"></div>
<script>
// Override default values of shop.strings for each template.
// Alternate product templates can change values of
// add to cart button, sold out, and unavailable states here.
theme.productStrings = {
addToCart: {{ 'Pre-order' | json }},
soldOut: {{ 'products.product.sold_out' | t | json }},
unavailable: {{ 'products.product.unavailable' | t | json }}
};
if(sessionStorage.backToCollection) {
theme.backToCollection = {};
theme.backToCollection.collection = JSON.parse(sessionStorage.backToCollection);
var productCollections = {{ product.collections | json }};
var showCollection = false;
if (productCollections) {
productCollections.forEach(function(collection) {
if (collection.title === theme.backToCollection.collection.title) {
showCollection = true;
}
});
}
if(showCollection) {
var backToCollectionHTML = '<div class="text-center return-link-wrapper page-width"><a href="' + theme.backToCollection.collection.link + '" class="btn btn--secondary btn--has-icon-before">{% include 'icon-arrow-left' %}{{ 'products.product.back_to_collection' | t }} ' + theme.backToCollection.collection.title + '</a></div>';
var backToCollectionContainer = document.getElementById('backToCollection');
backToCollectionContainer.insertAdjacentHTML('afterbegin', backToCollectionHTML);
}
}
</script>
{% assign current_variant = product.selected_or_first_available_variant %}
<script type="application/ld+json">
{
"@context": "http://schema.org/",
"@type": "Product",
"name": {{ product.title | json }},
"url": {{ shop.url | append: product.url | json }},
{%- if product.featured_media -%}
{%- assign media_size = product.featured_media.preview_image.width | append: 'x' -%}
"image": [
{{ product.featured_media | img_url: media_size | prepend: "https:" | json }}
],
{%- endif -%}
"description": {{ product.description | strip_html | json }},
{%- if current_variant.sku != blank -%}
"sku": {{ current_variant.sku | json }},
{%- endif -%}
"brand": {
"@type": "Thing",
"name": {{ product.vendor | json }}
},
"offers": [
{%- for variant in product.variants -%}
{
"@type" : "Offer",
{%- if variant.sku != blank -%}
"sku": {{ variant.sku | json }},
{%- endif -%}
"availability" : "http://schema.org/{% if variant.available %}InStock{% else %}OutOfStock{% endif %}",
"price" : {{ variant.price | divided_by: 100.00 | json }},
"priceCurrency" : {{ cart.currency.iso_code | json }},
"url" : {{ shop.url | append: variant.url | json }}
}{% unless forloop.last %},{% endunless %}
{%- endfor -%}
]
}
</script>
Leatheraholicx
hello @leatheraholicx
The product strings appear to be the same. I think you can just replace that part of the script. If you need support, please feel free to DM or email me.
Hi,
I've implemented this and have the pre-order working as it's supposed to, but we have just noticed that the product codes and collection names are not showing up on the product pages for pre-orderable items. Any ideas as to how to solve this? Do I possibly also need to create a 'product-details-pre-order-template.liquid as well? We have sites using the Mobilia theme and also some using the Envy theme, so I need to fix it on both themes as we've found that the issue is the same in both.
I just changed the translation: add to cart ---> Pre-order
What's the different? I need the pre-order to appear once i've not products on stock.
If I change my payment to manually capture payment, will this affect all other purchases outside of the pre-order style?
@YuriLee I asked this along with several other operational and procedural questions a while back and got zero response from the OP or anyone else. Hopefully you'll have better luck...
Thank you for this tutorial. I have implemented the solution for Sectioned themes. I have 3 product variants, S, M and L. I tested this out by indicate S and L at 0 inventory and M at 1 inventory, but when I select M on the front end, the button still says Pre-order. Do you have any inkling where I may have gone wrong in my implementation?
Hi TyW,
Thank you for your easy-to-follow instructions. Do you happen to have an updated or applicable to "brooklyn" theme version by chance? Your codes don't work fo my store. Store url is www.ootdnewyork10.com and the theme, again, is brooklyn.
TyW,
I am following your instructions to the Tee. Maybe I am missing something the line code for the style for the boost template does not have the following below for me to replace.
addToCart: {{ 'products.product.add_to_cart' | t | json }}, to addToCart: {{ 'Pre-order' | json }},
instead I have the following code.
<script type="application/json" class="ProductJson-{{ product.id }}">
{{ product | json }}
</script>
Do you have any updated instructions?
Good Day I have followed instructions and everything works great! I have one question though, how can products that are in stock show an "in stock" or "add to cart" to show that they are in stock and not on preorder, and then switch to pre-order if the inventory stock hits 0? Would one have to change the Template suffix or is there a script that can be included?
Great instructions! Very easy to follow! I did everything exactly as you said, but I'm getting this error on most of my items. Do you have any insight on this "Translation missing"?
You'll see it worked for the Pebble color in the pants, but not for the white.
Thank you for the solution, this worked for my debut theme shop!
Thank you for the tip! I managed to do the pre-order and get it to work. However I would like to add a message in the section to inform the customer about delayed shipping.
May I know how I should do that?
Sections > product template liquid > line 152 > <div class="free_ship"><img width="50px" src="https://cdn0.iconfinder.com/data/icons/e-commerce-69/512/delivery-512.png"><span style="font-size: 20px;padding-left: 5px;">type your message about delayed shipping here</span></div>
This is the only way I could think of doing it.
Hi there, thank you so much for this tutorial, it worked perfectly!
Im just wondering how to get the quantity picker showing when you have pre order template enabled. As its currently only the 'preorder' button available
thanks so much!
Henrietta
User | RANK |
---|---|
162 | |
138 | |
74 | |
69 | |
58 |
Explore the 30-30-30 rule, a dynamic social media strategy for new businesses. Learn how t...
By Trevor Sep 20, 2023Discover how to leverage the often overlooked footer of your ecommerce site to gain custom...
By Skye Sep 15, 2023In this blog, we’ll be shining a light on Shopify Partners, Experts, and Affiliates. Who a...
By Imogen Sep 13, 2023