CKzJk9zZg_sCEAE=

How to display product prices using liquid code on InstaOrders Form ?

We’re excited to announce a brand new feature for InstaOrders – the ability to display product prices from liquid code!

Liquid code is a powerful and versatile coding language that is used by Shopify merchants to create custom themes and designs for their stores.

This new feature allows merchants to easily display prices for products on the InstaOrders order form based on product, variant and their metafields properties. This is useful to show B2B pricing based on logged in customer. We know that merchants are busy people, so this feature is designed to save them time and effort.

The new feature is incredibly easy to use. All merchants have to do is copy and paste their product liquid code into the InstaOrders app by visiting the app > Layout & Language > Use Liquid Code to Determine Product Price section and the prices will automatically be displayed. It’s that simple! We hope that this new feature will help Shopify merchants make the most out of their store and save them time in the process. So head on over to InstaOrders today and start displaying product prices from liquid code!

Sample Liquid Codes:

{{ variant.metafields.b2b.price }}

Expected Output is string with or without decimal

120
120.00

Available Liquid Objects:

Objects: customer, variant, product, shop

Properties:

customer: id, tags

variant: id, title, sku, price, barcode, inventoryPolicy, inventoryItem, image, inventoryQuantity, product, compare_at_price, metafields

product: id, title, body_html, vendor, product_type, created_at, handle, updated_at, published_at, template_suffix, status, published_scope, tags, admin_graphql_api_id, variants, options, images, image, price, compare_at_price, price_max, price_min, compare_at_price_max, compare_at_price_min, metafields

shop: metafields

Code templates for apps:

B2B Wholesale Club (https://apps.shopify.com/wholesale-club)

{% capture new_price %}{% comment %} Wholesale_Club_Item_Prices Start {% endcomment %}
{% assign base_product = product %}
{% assign base_variant = variant %}

{% if shop.metafields.sawholesale['base_price'] == blank %}
  {% assign base_price = 'compare_at_price' %}
{% else %}
  {% assign base_price = shop.metafields.sawholesale['base_price'] %}
{% endif %}

{% assign saw_discount = 0 %}{% assign saw_has_discount = false %}

{% if customer.tags != blank %}
  {% for mf in base_product.metafields.sawholesale %}
    {% capture product_customer_tag %}{{ mf | first | replace: 'discount_', '' }}{% endcapture %}
    {% if customer.tags contains product_customer_tag %}
      {% assign saw_has_discount = true %}
      {% assign discount_key = product_customer_tag | prepend: 'discount_' %}
      {% assign price_key = product_customer_tag | prepend: 'price_' %}
      {% assign saw_discount = base_product.metafields.sawholesale[discount_key] | divided_by: 100.0 %}
    {% endif %}
  {% endfor %}
{% endif %}

{% assign saw_discount = 1 | minus: saw_discount %}

{% if base_price == 'price' or base_variant.compare_at_price == blank  or base_variant.compare_at_price == 0 or base_variant.compare_at_price < base_variant.price %}
  {% assign saw_variant_compare_at_price = base_variant.price %}
{% else %}
  {% assign saw_variant_compare_at_price = base_variant.compare_at_price %}
{% endif %}

{% assign cpe = shop.metafields.sawholesale['cpe'] | default: "true" %}
{% if base_variant.metafields.sawholesale[price_key] != blank and cpe == "true" %}
  {% assign saw_variant_price = base_variant.metafields.sawholesale[price_key] %}
{% else %}
  {% assign saw_variant_price = saw_variant_compare_at_price | times: saw_discount %}
{% endif %}

{% if saw_has_discount == false or saw_variant_price >= saw_variant_compare_at_price %}
  {% assign WCItem_OriginalPrice = product.price %}
  {% assign WCItem_FinalPrice = product.price %}
  {% assign WCItem_Price = product.price %}
  {% assign WCItem_PriceMin = product.price_min %}
  {% assign WCItem_PriceMax = product.price_max %}
  {% assign WCItem_CompareAtPrice = product.compare_at_price %}
  {% assign WCItem_CompareAtPriceMin = product.compare_at_price_min %}
  {% assign WCItem_CompareAtPriceMax = product.compare_at_price_max %}
  {% assign WCItem_OriginalLinePrice = product.price %}
  {% assign WCItem_FinalLinePrice = product.price %}
  {% assign WCItem_LinePrice = product.price %}
{% else %}
  {% assign WCItem_OriginalPrice = saw_variant_compare_at_price %}
  {% assign WCItem_FinalPrice = saw_variant_price %}
  {% assign WCItem_Price = saw_variant_price %}
  {% assign WCItem_PriceMin = product.price_min | times: saw_discount %}
  {% assign WCItem_PriceMax = product.price_max | times: saw_discount %}
  {% assign WCItem_CompareAtPrice = saw_variant_compare_at_price %}
  {% if base_product.compare_at_price_min != 0 %}{% assign WCItem_CompareAtPriceMin = base_product.compare_at_price_min %}{% else %}{% assign WCItem_CompareAtPriceMin = base_product.price_min %}{% endif %}
  {% if base_product.compare_at_price_max != 0 %}{% assign WCItem_CompareAtPriceMax = base_product.compare_at_price_max %}{% else %}{% assign WCItem_CompareAtPriceMax = base_product.price_max %}{% endif %}
  {% assign WCItem_OriginalLinePrice = WCItem_OriginalPrice %}
  {% assign WCItem_FinalLinePrice = WCItem_FinalPrice %}
  {% assign WCItem_LinePrice = WCItem_Price | round: 2 %}
{% endif %}
{% comment %} Wholesale_Club_Item_Prices End {% endcomment %}
{{ WCItem_LinePrice }}
{% endcapture %}{{ new_price | strip }}
mplus

How to display metafields for variants ? (auto-updates based on current variant selection)

Today we’ll talk about most requested feature for variant metafields, i.e way the variant metafields get automatically updated on change in the selection. This will need update to your theme’s liquid code, but no worries we’ve tried to make it pretty simple.

Step 1:

Navigate to your store’s admin panel and open themes. You wanna try the code before publishing it on live, so better make a duplicate theme of your active theme and start editing code of your duplicated and unpublished theme.

Step 2:

Create a snippet with name “variant-dynamic-metafield” (you can choose any name, but keep in mind to use same name in Step 3 while rendering snippets on your product page)

Insert following code into this file and save:

{% comment %}
 \*****Copyrights DigiBrew (digibrew.io)*****\
{% endcomment %}
{% if updateHTMLSelectors %}
  <script>
        if(typeof variantMetafieldValues === 'undefined'){
          var variantMetafieldValues = {};
        } 
  </script>
{% endif %}
{% for variant in product.variants %}
    {% if updateHTMLSelectors %}
      <script>
        if(typeof variantMetafieldValues[{{ variant.id }}] === 'undefined')
        variantMetafieldValues[{{ variant.id }}] = {}

        if(typeof variantMetafieldValues[{{ variant.id }}]["{{ namespace }}"] === 'undefined')
        variantMetafieldValues[{{ variant.id }}]["{{ namespace }}"] = {}

        if(typeof variantMetafieldValues[{{ variant.id }}]["{{ namespace }}"]["{{ key }}"] === 'undefined')
        variantMetafieldValues[{{ variant.id }}]["{{ namespace }}"]["{{ key }}"] = {}

        if(typeof variantMetafieldValues[{{ variant.id }}]["{{ namespace }}"]["{{ key }}"]["selectors"] === 'undefined')
          variantMetafieldValues[{{ variant.id }}]["{{ namespace }}"]["{{ key }}"]["selectors"] = [`{{ updateHTMLSelectors }}`]
        else
          variantMetafieldValues[{{ variant.id }}]["{{ namespace }}"]["{{ key }}"]["selectors"].push(`{{ updateHTMLSelectors }}`)

        variantMetafieldValues[{{ variant.id }}]["{{ namespace }}"]["{{ key }}"]["value"] = "{{ variant.metafields[namespace][key] }}"
      </script>
	{% elsif is_image %}
		{% if variant.metafields[namespace][key] %}
			<img class="dynamic-variant-data variant-{{variant.id}} {{ class }}" src="{{ variant.metafields[namespace][key] }}" alt="{{ key }}" style="{% if variant.id != selected_variant.id %}display:none{% endif %}">
		{% endif %}
    {% elsif is_input %}
		<input namespace="{{ namespace }}" key="{{ key }}" variant-id="{{variant.id}}" class="dynamic-variant-data-input-value" value="{% if variant.metafields[namespace][key] %}{{ variant.metafields[namespace][key] }}{% endif %}" style="display:none"/>
	{% else %}
    <span class="dynamic-variant-data variant-{{variant.id}} {{ class }}" style="{% if variant.id != selected_variant.id %}display:none{% endif %}">
      {% if variant.metafields[namespace][key] %}
      	{{ variant.metafields[namespace][key] }}
      {% endif %}
    </span>
	{% endif %}
{% endfor %}

{% if is_input %}
	<input name="{{ name }}" namespace="{{ namespace }}" key="{{ key }}" class="dynamic-variant-data-input {{ class }}" {%if display %}style="display:{{ display }}"{% endif %} value="{{ selected_variant.metafields[namespace][key] }}"/>
{% endif %}

<script>
if(!variantDynamicMetafieldScriptAlreadyAdded){    
var variantDynamicMetafieldScriptAlreadyAdded = true;
document.addEventListener('DOMContentLoaded', function(){

function usePushState(handler){

    //modern themes use pushstate to track variant changes without reload
    function track (fn, handler, before) {
        return function interceptor () {
            if (before) {
                handler.apply(this, arguments);
                return fn.apply(this, arguments);
            } else {
                var result = fn.apply(this, arguments);
                handler.apply(this, arguments);
                return result;
            }
        };
    }

    var currentVariantId = null;
    function variantHandler () {
        var selectedVariantId = window.location.search.replace(/.*variant=(\d+).*/, '$1');
        if(!selectedVariantId) return;
        if(selectedVariantId != currentVariantId){
            currentVariantId = selectedVariantId;
            handler(selectedVariantId);
        }
    }

    // Assign listeners
    window.history.pushState = track(history.pushState, variantHandler);
    window.history.replaceState = track(history.replaceState, variantHandler);
    window.addEventListener('popstate', variantHandler);
}

function updateSelectorVal(el,selector_options,value){
  var defaultValue;
  var valueType = typeof selector_options[1] !== 'undefined' ? selector_options[1] : 'innerHTML';

  
  switch(valueType){
    case 'innerHTML':
        if(value){
          defaultValue = el.innerHTML;
          el.innerHTML = value;
        }
    break;
    case 'value':  
        if(value){
            defaultValue = el.value;    
            el.value = value;
        }
    break;
    case 'attr':      
        const attrName = selector_options[2];
        if(typeof attrName !== 'undefined'){
          valueType += '-'+attrName
          if(value){
            defaultValue = el.getAttribute(attrName);  
            el.setAttribute(attrName,value)
          } 
        }
    break;
    default:
      if(value){
        el.innerHTML = value;
        el.value = value;
      }
    break;
        
  }

  const defaultValueAttrName = 'default-value-'+valueType;

  if(value){
    if(!el.getAttribute(defaultValueAttrName))
    el.setAttribute(defaultValueAttrName,defaultValue)
  }else{
    const defaultAttrValue = el.getAttribute(defaultValueAttrName);
    if(defaultAttrValue){
      updateSelectorVal(el,selector_options,defaultAttrValue)
    }
  }
}

usePushState(function(variantId){  
    if(typeof variantMetafieldValues[variantId] !== 'undefined'){
      for (namespace_index in variantMetafieldValues[variantId]){
        const namespaces = variantMetafieldValues[variantId][namespace_index];
        
        for (key_index in namespaces){
          const key = namespaces[key_index];
            key.selectors.map((selector) => {
              const selectors = selector.split(",");
              selectors.map((selector_option) => {
                const selector_options = selector_option.split("|");
                for (let el of document.querySelectorAll(selector_options[0])){
                  updateSelectorVal(el,selector_options,key.value);
                } 
              })
            })
        }
      }
    }
    for (let el of document.querySelectorAll('.dynamic-variant-data')) el.style.display = 'none';
    for (let el of document.querySelectorAll('.dynamic-variant-data.variant-'+variantId)) el.style.display = '{{ display }}';
    for (let el of document.querySelectorAll('.dynamic-variant-data-input')) {
      const matching_el = document.querySelector('.dynamic-variant-data-input-value[namespace="'+el.getAttribute('namespace')+'"][key="'+el.getAttribute('key')+'"][variant-id="'+variantId+'"]');
      el.value = matching_el ? matching_el.value : '';
    };
});
});
}
</script>

Step 3:

You can render auto-updating variant metafields on product.liquid using following code. I’ll explain the customizable parameters below.

{% render "variant-dynamic-metafield", product: product, selected_variant: product.selected_or_first_available_variant, display: "inline-block", namespace: "your_variants_metafield_namespace", key: "your_variants_metafield_key" %}

Customizable Parameters:

  • updateHTMLSelectors – update html elements using selectors with option to update innerHTML, attributes or value. Selector format: [selector]|[innerHTML/value/attr]|[attr-name(optional)]

    e.g
{% render "variant-dynamic-metafield", product: product, selected_variant: product.selected_or_first_available_variant, updateHTMLSelectors : 'head title|innerHTML,meta[property="og:title"]|attr|content', namespace: "global", key: "title_tag" %}

{% render "variant-dynamic-metafield", product: product, selected_variant: product.selected_or_first_available_variant, updateHTMLSelectors : 'meta[name="description"]|attr|content', namespace: "global", key: "description_tag" %}

{% render "variant-dynamic-metafield", product: product, selected_variant: product.selected_or_first_available_variant, updateHTMLSelectors : 'input[name="variant-description"]:value', namespace: "global", key: "description_tag" %}
  • display – css display property, possible values “block”, “inline-block” etc. (https://www.w3schools.com/cssref/pr_class_display.asp)
  • namespace – Variant’s metafield namespace
  • key – Variant’s metafield key
  • class – custom css class for variant element
  • is_image – true/false
  • is_input – true/false
  • name – input name (only applicable if is_input is set to true)

And that’s it. Happy Coding ! Let us know if this worked for you or not.

Screenshot-2019-09-09-at-4.19.49-PM-1024x434

How to add new custom fields to Shopify Products ?

Ever felt a need to add more fields to Shopify’s default fields on products and variants ?

Well, you can try Metafields Plus + app for Shopify.

Just click “Add New Fields” to product / variant page from Shopify and you can multiple fields types

You can add custom meta-fields to:

  • Products
  • Product Variants
  • Product Collections
  • Customers
  • Store
  • Orders

Type of Metafields you can attach:

  • Images
  • Files
  • HTML
  • Simple Text

Other Features:

  • Edit meta-fields directly from products, variants, collections and customers admin page by clicking on “More Actions” > “Edit via Metafields +”
  • Bulk Import/Export Meta-fields via CSV

Examples of custom meta-fields:

  • Attach Self-Assembly instruction files for your products/variants
  • Attach Size Charts
  • Link internal production files

Your imagination is the only limitation to what purpose you use these custom meta-fields, over your Shopify Store.

Simply follow instructions from app on how to show custom meta-fields on your store front.

  • No advance Shopify Liquid knowledge required.