Shopify themes, liquid, logos, and UX
Hey guys. Can anyone save me? I'm trying to solve this problem myself. I tried with some apps, but despite solving this problem, they created another one. So I need to configure it in code. Has anyone made this change in Empire Theme? I need to apply it on the product page, collection page, and cart.
I need to set up minimum order quantities (with multiples) for each product per tag.
(example tag: minqty:10 for products that are sold with a minimum order of 10 pieces... in this case, a minimum of 10 pieces and in multiples of 10 (10-20-30-40).
Thanks for your attention!
Here's how I would approach this:
1) Tag the products according to their minimums
2) Add code to the product page to tell the customer the minimum
3) Add a script that prevents adding to cart and triggers a warning message when the user tries to add to the cart under the minimum.
Example code snippet for #2
{% if product.tags contains "minimum 10" %}
<p>This product requires a minimum quantity of 10 units</p>
{% endif %}
Example code snippet for #3
{% if product.tags contains "minimum 10" %}
<p id="quantity-error" style="color: red; display: none;">This product requires a minimum of 10 units</p>
<script>
// Get the add to cart button by ID (inspect your atc button with chrome dev tools to find its ID)
let atc = document.querySelector("#add-to-cart");
// Set up a listener for clicking the atc button
atc.addEventListener("click", (e) => {
// Get the selected quantity (inspect your atc button with chrome dev tools to find its ID)
let quantity = document.querySelector("#quantity").value;
// If quantity is less than 10, prevent the add to cart and reveal the error message
if (quantity < 10) {
e.preventDefault;
document.querySelector("#quantity-error").style.display = "block";
}
});
</script>
{% endif %}
I would add those either above or below the add to cart button. If you share this with your developer they should know what to do.
If you don't have a developer, you can take a crack at it but make sure you do this on a backup theme and test first (this guide will help you with theme editing plus inspecting elements to get their ID: https://speedboostr.com/how-to-safely-edit-your-shopify-theme/), or if you want feel free to reach out to my team at speedboostr.com/contact if you want a Shopify developer to handle it for you.
I am using the Simple theme and trying to set a minimum order quantity on specific items, I am not a developer so am unsure where to add the code to the product-template.liquid
Hoping you can advise where to place it, below is the current code.
"
<!-- /templates/product.liquid -->
<div
itemscope
itemtype="http://schema.org/Product"
id="ProductSection"
data-section-id="{{ section.id }}"
data-section-type="product-template"
data-image-zoom-type="{{ section.settings.product_image_zoom_type }}"
data-show-extra-tab="{{ section.settings.show_extra_tab }}"
data-extra-tab-content="{{ section.settings.extra_tab_content }}"
data-cart-enable-ajax="{{ settings.cart_enable_ajax }}"
data-enable-history-state="true"
>
<meta itemprop="name" content="{{ product.title }}">
<meta itemprop="url" content="{{ shop.url }}{{ product.url }}">
<meta itemprop="image" content="{{ product.featured_image.src | img_url: 'grande' }}">
{% comment %}
Get first variant in stock, or deep linked one
{% endcomment %}
{% assign current_variant = product.selected_or_first_available_variant %}
{%- assign featured_image = current_variant.featured_image | default: product.featured_image -%}
<div class="grid product-single">
<div class="grid__item medium-up--one-half">
{% for image in product.images %}
{% capture img_id %}ProductImage-{{ image.id }}{% endcapture %}
{% capture wrapper_id %}ProductImageWrapper-{{ image.id }}{% endcapture %}
{%- assign img_url = image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}
{% include 'image-style' with image: image, width: 720, height: 600, small_style: true, wrapper_id: wrapper_id, img_id: img_id %}
<div
id="{{ wrapper_id }}"
class="product-single__featured-image-wrapper supports-js{% unless featured_image == image %} hidden{% endunless %}"
data-image-id="{{ image.id }}"
>
<div
class="product-single__photos"
data-image-id="{{ image.id }}"
style="padding-top:{{ 1 | divided_by: image.aspect_ratio | times: 100}}%;"
>
<img
id="{{ img_id }}"
class="product-single__photo lazyload{% unless featured_image == image %} lazypreload{% endunless %}{% if section.settings.product_image_zoom_type == 'lightbox' %} lightbox{% endif %}"
{% if section.settings.product_image_zoom_type == 'zoom-in' %}
data-zoom="{{ image | img_url: '1024x1024' }}"
{% endif %}
src="{{ image | img_url: '300x300' }}"
data-src="{{ img_url }}"
data-widths="[180, 360, 470, 600, 750, 940, 1080, 1296, 1512, 1728, 2048]"
data-aspectratio="{{ image.aspect_ratio }}"
data-sizes="auto"
alt="{{ image.alt | escape }}"
>
</div>
<div id="shopify-product-reviews" data-id="{{product.id}}">{{ product.metafields.spr.reviews }}</div>
{% if product.compare_at_price_max > product.price %}
<span class="badge badge--sale"
><span>{{ 'products.product.on_sale' | t }}</span></span
>
{% endif %}
</div>
{% endfor %}
<noscript>
<img src="{{ featured_image | img_url: 'grande' }}" alt="{{ featured_image.alt | escape }}">
</noscript>
{% if product.images.size > 1 %}
<ul class="product-single__thumbnails grid grid--uniform" id="ProductThumbs">
{% case product.images.size %}
{% when 2 %}
{% assign thumbnail_width = 'small--one-half medium-up--push-one-sixth medium-up--one-third' %}
{% when 4 %}
{% assign thumbnail_width = 'small--one-half medium-up--one-quarter' %}
{% else %}
{% assign thumbnail_width = 'small--one-third medium-up--one-third' %}
{% endcase %}
{% for image in product.images %}
<li class="grid__item {{ thumbnail_width }}">
<a
href="{{ image.src | img_url: 'grande' }}"
class="product-single__thumbnail"
data-image-id="{{ image.id }}"
>
<img src="{{ image.src | img_url: 'compact' }}" alt="{{ image.alt | escape }}">
</a>
</li>
{% endfor %}
</ul>
{% endif %}
{% if section.settings.product_image_zoom_type == 'lightbox' %}
<ul class="gallery hidden">
{% for image in product.images %}
<li
data-image-id="{{ image.id }}"
class="gallery__item"
data-mfp-src="{{ image | img_url: '3500x3500' }}"
></li>
{% endfor %}
</ul>
{% endif %}
</div>
<div class="grid__item medium-up--one-half{% if product.images.size == 0%} medium-up--push-one-half{% endif %}">
<div class="product-single__meta small--text-center">
<h1 class="product-single__title" itemprop="name">{{ product.title }}</h1>
SKU:
{% assign current_variant = product.selected_or_first_available_variant %}
<span class="variant-sku">{{ current_variant.sku }}</span>
{% if section.settings.vendor_show %}
<p class="product-single__vendor" itemprop="brand">{{ product.vendor }}</p>
{% endif %}
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<meta itemprop="priceCurrency" content="{{ shop.currency }}">
<link
itemprop="availability"
href="http://schema.org/{% if current_variant.available %}InStock{% else %}OutOfStock{% endif %}"
>
<p class="product-single__prices">
{% if product.compare_at_price_max > product.price %}
<span id="ComparePriceA11y" class="visually-hidden">{{ 'products.product.sale_price' | t }}</span>
{% else %}
<span class="visually-hidden">{{ 'products.product.regular_price' | t }}</span>
{% endif %}
<span
id="ProductPrice"
class="product-single__price"
itemprop="price"
content="{{ current_variant.price | divided_by: 100.00 }}"
>
{{ current_variant.price | money }}
</span>
{% if product.compare_at_price_max > product.price %}
<span id="PriceA11y" class="visually-hidden">{{ 'products.product.regular_price' | t }}</span>
<s class="product-single__price--compare" id="ComparePrice">
{{ current_variant.compare_at_price | money }}
</s>
{% endif %}
</p>
{% comment %} Inventory tracking on product page {% endcomment %}
<div id="variant-inventory" class="{% unless current_variant.available %} hide {% endunless %}">
{% if current_variant.inventory_management == 'shopify'
and current_variant.inventory_policy != 'continue'
%}
We have {{ current_variant.inventory_quantity }} in stock.
{% else %}
This product is available.
{% endif %}
</div>
Weight each: {{ product.variants.first.weight | weight_with_unit }} approx.
</div>
{%- if shop.taxes_included or shop.shipping_policy.body != blank -%}
<div class="product-single__policies rte">
{%- if shop.taxes_included -%}
{{ 'products.product.include_taxes' | t }}
{%- endif -%}
{%- if shop.shipping_policy.body != blank -%}
{{ 'products.product.shipping_policy_html' | t: link: shop.shipping_policy.url }}
{%- endif -%}
</div>
{%- endif -%}
{% form 'product', product, class: 'product-form' %}
<select name="id" id="ProductSelect-{{ section.id }}" class="product-single__variants">
{% for variant in product.variants %}
{% if variant.available %}
<option
{% if variant == product.selected_or_first_available_variant %}
selected="selected"
{% endif %}
data-sku="{{ variant.sku }}"
value="{{ variant.id }}"
>
{{ variant.title }} - {{ variant.price | money_with_currency }}
</option>
{% else %}
<option disabled="disabled">{{ variant.title }} - {{ 'products.product.sold_out' | t }}</option>
{% endif %}
{% endfor %}
</select>
{% if section.settings.product_quantity_enable %}
<div class="product-single__quantity">
<label for="Quantity">{{ 'products.product.quantity' | t }}</label>
<input type="number" id="Quantity" name="quantity" value="1" min="1">
</div>
{% endif %}
<div class="product-single__cart-submit-wrapper{% if section.settings.enable_payment_button %} product-single__shopify-payment-btn{% endif %}{% if section.settings.add_to_cart_width == 'full_width' %} product-form--full{% endif %}">
<button
type="submit"
name="add"
id="AddToCart"
class="btn product-single__cart-submit{% if section.settings.add_to_cart_width == 'full_width' %} btn--full{% endif %}{% if section.settings.enable_payment_button %} shopify-payment-btn btn--secondary{% endif %}"
>
<span id="AddToCartText">{{ 'products.product.add_to_cart' | t }}</span>
</button>
{% if section.settings.enable_payment_button %}
{{ form | payment_button }}
{% endif %}
</div>
{% endform %}
</div>
{% if section.settings.product_description_position == 'right' %}
{%- assign position = 'right' -%}
{% include 'product-description' %}
{% endif %}
{% if section.settings.social_sharing_products %}
{% include 'social-sharing', share_title: product.title, share_permalink: product.url, share_image: product %}
{% endif %}
<div class="product-nav clearfix">
<span style="float:left;">
{%- if collection.previous_product %}
{{ '← PREVIOUS' | link_to: collection.previous_product }}
{% endif -%}
</span>
<span style="float:right;">
{%- if collection.next_product %}
{{ 'NEXT →' | link_to: collection.next_product }}
{% endif -%}
</span>
</div>
</div>
</div>
{% if section.settings.product_description_position == 'below' %}
{%- assign position = 'below' -%}
{% include 'product-description' %}
{% endif %}
{% include 'related-products' %}
</div>
{% unless product == empty %}
<script type="application/json" id="ProductJson-{{ section.id }}">
{{ product | json }}
</script>
{% endunless %}
<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.
window.productStrings = {
addToCart: {{ 'products.product.add_to_cart' | t | json }},
soldOut: {{ 'products.product.sold_out' | t | json }},
unavailable: {{ 'products.product.unavailable' | t | json }}
}
</script>
"
Thanks in advance!
I am using the Simple theme and want to set a minimum order quantity on certain products but cannot work out where to place the code. Could you advise where to place the code, in the below current product-template.liquid
"
<!-- /templates/product.liquid -->
<div
itemscope
itemtype="http://schema.org/Product"
id="ProductSection"
data-section-id="{{ section.id }}"
data-section-type="product-template"
data-image-zoom-type="{{ section.settings.product_image_zoom_type }}"
data-show-extra-tab="{{ section.settings.show_extra_tab }}"
data-extra-tab-content="{{ section.settings.extra_tab_content }}"
data-cart-enable-ajax="{{ settings.cart_enable_ajax }}"
data-enable-history-state="true"
>
<meta itemprop="name" content="{{ product.title }}">
<meta itemprop="url" content="{{ shop.url }}{{ product.url }}">
<meta itemprop="image" content="{{ product.featured_image.src | img_url: 'grande' }}">
{% comment %}
Get first variant in stock, or deep linked one
{% endcomment %}
{% assign current_variant = product.selected_or_first_available_variant %}
{%- assign featured_image = current_variant.featured_image | default: product.featured_image -%}
<div class="grid product-single">
<div class="grid__item medium-up--one-half">
{% for image in product.images %}
{% capture img_id %}ProductImage-{{ image.id }}{% endcapture %}
{% capture wrapper_id %}ProductImageWrapper-{{ image.id }}{% endcapture %}
{%- assign img_url = image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}
{% include 'image-style' with image: image, width: 720, height: 600, small_style: true, wrapper_id: wrapper_id, img_id: img_id %}
<div
id="{{ wrapper_id }}"
class="product-single__featured-image-wrapper supports-js{% unless featured_image == image %} hidden{% endunless %}"
data-image-id="{{ image.id }}"
>
<div
class="product-single__photos"
data-image-id="{{ image.id }}"
style="padding-top:{{ 1 | divided_by: image.aspect_ratio | times: 100}}%;"
>
<img
id="{{ img_id }}"
class="product-single__photo lazyload{% unless featured_image == image %} lazypreload{% endunless %}{% if section.settings.product_image_zoom_type == 'lightbox' %} lightbox{% endif %}"
{% if section.settings.product_image_zoom_type == 'zoom-in' %}
data-zoom="{{ image | img_url: '1024x1024' }}"
{% endif %}
src="{{ image | img_url: '300x300' }}"
data-src="{{ img_url }}"
data-widths="[180, 360, 470, 600, 750, 940, 1080, 1296, 1512, 1728, 2048]"
data-aspectratio="{{ image.aspect_ratio }}"
data-sizes="auto"
alt="{{ image.alt | escape }}"
>
</div>
<div id="shopify-product-reviews" data-id="{{product.id}}">{{ product.metafields.spr.reviews }}</div>
{% if product.compare_at_price_max > product.price %}
<span class="badge badge--sale"
><span>{{ 'products.product.on_sale' | t }}</span></span
>
{% endif %}
</div>
{% endfor %}
<noscript>
<img src="{{ featured_image | img_url: 'grande' }}" alt="{{ featured_image.alt | escape }}">
</noscript>
{% if product.images.size > 1 %}
<ul class="product-single__thumbnails grid grid--uniform" id="ProductThumbs">
{% case product.images.size %}
{% when 2 %}
{% assign thumbnail_width = 'small--one-half medium-up--push-one-sixth medium-up--one-third' %}
{% when 4 %}
{% assign thumbnail_width = 'small--one-half medium-up--one-quarter' %}
{% else %}
{% assign thumbnail_width = 'small--one-third medium-up--one-third' %}
{% endcase %}
{% for image in product.images %}
<li class="grid__item {{ thumbnail_width }}">
<a
href="{{ image.src | img_url: 'grande' }}"
class="product-single__thumbnail"
data-image-id="{{ image.id }}"
>
<img src="{{ image.src | img_url: 'compact' }}" alt="{{ image.alt | escape }}">
</a>
</li>
{% endfor %}
</ul>
{% endif %}
{% if section.settings.product_image_zoom_type == 'lightbox' %}
<ul class="gallery hidden">
{% for image in product.images %}
<li
data-image-id="{{ image.id }}"
class="gallery__item"
data-mfp-src="{{ image | img_url: '3500x3500' }}"
></li>
{% endfor %}
</ul>
{% endif %}
</div>
<div class="grid__item medium-up--one-half{% if product.images.size == 0%} medium-up--push-one-half{% endif %}">
<div class="product-single__meta small--text-center">
<h1 class="product-single__title" itemprop="name">{{ product.title }}</h1>
SKU:
{% assign current_variant = product.selected_or_first_available_variant %}
<span class="variant-sku">{{ current_variant.sku }}</span>
{% if section.settings.vendor_show %}
<p class="product-single__vendor" itemprop="brand">{{ product.vendor }}</p>
{% endif %}
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<meta itemprop="priceCurrency" content="{{ shop.currency }}">
<link
itemprop="availability"
href="http://schema.org/{% if current_variant.available %}InStock{% else %}OutOfStock{% endif %}"
>
<p class="product-single__prices">
{% if product.compare_at_price_max > product.price %}
<span id="ComparePriceA11y" class="visually-hidden">{{ 'products.product.sale_price' | t }}</span>
{% else %}
<span class="visually-hidden">{{ 'products.product.regular_price' | t }}</span>
{% endif %}
<span
id="ProductPrice"
class="product-single__price"
itemprop="price"
content="{{ current_variant.price | divided_by: 100.00 }}"
>
{{ current_variant.price | money }}
</span>
{% if product.compare_at_price_max > product.price %}
<span id="PriceA11y" class="visually-hidden">{{ 'products.product.regular_price' | t }}</span>
<s class="product-single__price--compare" id="ComparePrice">
{{ current_variant.compare_at_price | money }}
</s>
{% endif %}
</p>
{% comment %} Inventory tracking on product page {% endcomment %}
<div id="variant-inventory" class="{% unless current_variant.available %} hide {% endunless %}">
{% if current_variant.inventory_management == 'shopify'
and current_variant.inventory_policy != 'continue'
%}
We have {{ current_variant.inventory_quantity }} in stock.
{% else %}
This product is available.
{% endif %}
</div>
Weight each: {{ product.variants.first.weight | weight_with_unit }} approx.
</div>
{%- if shop.taxes_included or shop.shipping_policy.body != blank -%}
<div class="product-single__policies rte">
{%- if shop.taxes_included -%}
{{ 'products.product.include_taxes' | t }}
{%- endif -%}
{%- if shop.shipping_policy.body != blank -%}
{{ 'products.product.shipping_policy_html' | t: link: shop.shipping_policy.url }}
{%- endif -%}
</div>
{%- endif -%}
{% form 'product', product, class: 'product-form' %}
<select name="id" id="ProductSelect-{{ section.id }}" class="product-single__variants">
{% for variant in product.variants %}
{% if variant.available %}
<option
{% if variant == product.selected_or_first_available_variant %}
selected="selected"
{% endif %}
data-sku="{{ variant.sku }}"
value="{{ variant.id }}"
>
{{ variant.title }} - {{ variant.price | money_with_currency }}
</option>
{% else %}
<option disabled="disabled">{{ variant.title }} - {{ 'products.product.sold_out' | t }}</option>
{% endif %}
{% endfor %}
</select>
{% if section.settings.product_quantity_enable %}
<div class="product-single__quantity">
<label for="Quantity">{{ 'products.product.quantity' | t }}</label>
<input type="number" id="Quantity" name="quantity" value="1" min="1">
</div>
{% endif %}
<div class="product-single__cart-submit-wrapper{% if section.settings.enable_payment_button %} product-single__shopify-payment-btn{% endif %}{% if section.settings.add_to_cart_width == 'full_width' %} product-form--full{% endif %}">
<button
type="submit"
name="add"
id="AddToCart"
class="btn product-single__cart-submit{% if section.settings.add_to_cart_width == 'full_width' %} btn--full{% endif %}{% if section.settings.enable_payment_button %} shopify-payment-btn btn--secondary{% endif %}"
>
<span id="AddToCartText">{{ 'products.product.add_to_cart' | t }}</span>
</button>
{% if section.settings.enable_payment_button %}
{{ form | payment_button }}
{% endif %}
</div>
{% endform %}
</div>
{% if section.settings.product_description_position == 'right' %}
{%- assign position = 'right' -%}
{% include 'product-description' %}
{% endif %}
{% if section.settings.social_sharing_products %}
{% include 'social-sharing', share_title: product.title, share_permalink: product.url, share_image: product %}
{% endif %}
<div class="product-nav clearfix">
<span style="float:left;">
{%- if collection.previous_product %}
{{ '← PREVIOUS' | link_to: collection.previous_product }}
{% endif -%}
</span>
<span style="float:right;">
{%- if collection.next_product %}
{{ 'NEXT →' | link_to: collection.next_product }}
{% endif -%}
</span>
</div>
</div>
</div>
{% if section.settings.product_description_position == 'below' %}
{%- assign position = 'below' -%}
{% include 'product-description' %}
{% endif %}
{% include 'related-products' %}
</div>
{% unless product == empty %}
<script type="application/json" id="ProductJson-{{ section.id }}">
{{ product | json }}
</script>
{% endunless %}
<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.
window.productStrings = {
addToCart: {{ 'products.product.add_to_cart' | t | json }},
soldOut: {{ 'products.product.sold_out' | t | json }},
unavailable: {{ 'products.product.unavailable' | t | json }}
}
</script>
"
Thanks in advance!
@ana_vasbr Have you got your solution? If not then your requirements can be fulfilled with the MultiVariants - Bulk order app. But this app will only work on the product page and cart page, not on the collection page. If it suits your business then you can go ahead with the solution. For the collection page, the app will either block the add to cart button where you have applied the restriction or restrict your customer on the cart page unless the condition is fulfilled.
Through the MultiVariants - Bulk order app, you can set a minimum quantity per order for any product. If you set the minimum quantity as 10 then the customer can’t go to the cart page without choosing 10 quantities. Also, if you want to set a multiple quantity increase for the product then that can be also achieved by the app. If you set the quantity interval as 10 then it will increase like 10,20,30 and so on. After choosing any quantity the stock will be updated immediately. You set different restrictions for different products or groups of products in your store.
Also, with this app, you can apply restrictions for minimum-maximum quantities, predefined bundle, interval quantities, limits on variants and orders can be achieved. You’ll get 3 days of trial for going through all the available features.
Here is the Demo product where the customer must choose 12 items before going to the cart page and here is the Demo store with more available features.
Minimum order quantity – MultiVariants app
User | RANK |
---|---|
225 | |
168 | |
65 | |
54 | |
53 |
On our Shopify Expert Marketplace, you can find many trusted third party developers and fr...
By Arno Nov 27, 2023You've downloaded the Search & Discovery app from the Shopify App store, and as you're ...
By Skye Nov 8, 2023The year-end shopping season is just around the corner. Is a flash sale on your radar? Are...
By Jasonh Nov 6, 2023