How to display different variant prices to different customers? (Shopify/Liquid) - shopify

I'm currently working on the shopify site for the B2B company where i work.
(Yeah, we know that Shopify Plus is the best option for B2Bs, but we can't afford the price)
We work on two different customer lists and really need two different prices to show to customers on the main-product page.
I managed the lists with customer tags, and also the two different prices with Variants.
Now i was trying to figure out how to show the Price of the Variant 1 to customers with the "list1" tag and the Price of the Variant 2 to customers with the "list2" tag.
(Yeah, we know that there are Wholesale Pricing app to do this, but we can't afford the monthly cost either).
I tried something like this, but i'm stuck...
Could you please help me out?
This is my last try:
{% if customer.tags contains "list1" %}
{% assign current = product.selected_or_first_available_variant %}
{%- assign target_variant = product.variants[0] -%}
<div class="no-js-hidden" id="variantPrice-{{ section.id }}" role="status" {{ block.shopify_attributes }}>
{%- render 'price', product: product, use_variant: true, show_badges: true, price_class: 'price--large' -%} </div>
{% else %}
{% assign current = product.selected_or_first_available_variant %}
{%- assign target_variant = product.variants[1] -%}
<div class="no-js-hidden" id="variantPrice-{{ section.id }}" role="status" {{ block.shopify_attributes }}>
{%- render 'price', product: product, use_variant: true, show_badges: true, price_class: 'price--large' -%} </div>
{% endif %}

I somehow managed to solve this. After being stuck on it for two days :P
It works with something like this:
{%- when 'price' -%}
{% if customer %}//Hide the price if not registered - endif is at the end//
{% if customer.tags contains "list1" %}
{%- assign target_variant = product.variants[0] -%}
<div class="no-js-hidden" id="price-{{ section.id }}" role="status"
{{block.shopify_attributes }}>
{%- render 'price', product: product, use_variant: true, show_badges: true,
price_class: 'price--large' -%} </div> //It shows the price of the First Variant//
{% else %}
{%- assign target_variant = product.variants[1] -%}//I can't figure out if this is relevant for the code, but it works like this, so...//
<div id="variantPrice" role="status" {{ block.shopify_attributes }}>{%- render 'price' -%} </div> //It shows the price of the Second Variant //
{% endif %}
I don't know if this is the correct way, but it works, so it's fine :P
Hope it will help someone with the same issue.

The interesting thing about your approach here is that a customer from List type 1 would be seeing the price for the variant as List type 1 price, but there is zero stopping them from simply placing the variant with the different price from List type 2 in the cart if they wanted.
In other words, you are decorating the price displayed, which is your goal I guess, but there is no actual logic in place to ensure customers pay the correct amount. For that, you would need a different logic, one that tries hard to ensure a customer from List type 1 only gets to checkout with product variants that are assigned to List type 1. Without that logic, you're wide open to a bit of price abuse.

The approach may be very straight to the point:
{% if customer %}
{% for variant in product.variants %}
{% assign current = forloop.index | plus: 1 | prepend:'list' %}
{% if customer.tags contains current %}
{{ variant.price}}
{% assign found = true %}
{% endif %}
{% endfor %}
{% unless found %}
Display what you want to if no price has been found for logged in user
{% endunless %}
{% else %}
What you want to display when customer is not connected to an account.
{% endif %}
You may use the same logic for your add to cart form.

Related

How can I show Shopify variants depending on option value

How could you display only certain variants on the product and collection pages in Shopify depending on the value of an option?
Assuming the option name is 'Box Options' and the values would either be 'Trade' or 'Retail' I would expect something similar to this code to return the price for the Trade variant:
{%- assign get_variant = product.options_with_values -%}
{% assign trade_variant = get_variant | where: "Trade" %}
<p>{{ trade_variant.price }}</p>
For context I'm trying to get trade prices to be used where the customer tag is "Trade" using this if statement in the liquid file:
{% if customer.tags contains 'Trade' %}
Feel like this should be really easy but for the life of me I cannot get this to work.
If your variants contain only one option, then something like that should work (not tested):
{% if customer.tags contains 'Trade' %}
{% assign p_variants = product.variants | where:'title','Trade' %}
{% for variant in p_variants %}
{{ variant.title }}
{% endfor %}
{% endif %}
Then, second case, your variants go with multiple options, then it is a little bit more complex (not tested either):
{% if customer.tags contains 'Trade' %}
{% for variant in product.variants %}
{% if variant.options contains 'Box Options' and variant.title contains 'Trade' %}
{{ variant.title }}
{% endif %}
{% endfor %}
{% endif %}

Vendor list page - Only list vendors with items in stock

I have a page on my site that lists all the vendors in my shop like so:
<div class="vendor-list" id="designers-a-to-z">
<ul>
{% assign current = "" %}
{% capture alphabet %}
-A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-Z
{% endcapture %}
{% assign letters = alphabet | split: '-' %}
{% assign its_a_letter = false %}
{% for vendor in shop.vendors %}
{% assign vendor_first_letter = vendor | strip | upcase | slice : 0 %}
{% for letter in letters %}
{% if vendor_first_letter == letter %}
{% assign its_a_letter = true %}
{% break %}
{% endif %}
{% endfor %}
{% if its_a_letter %}
{% unless vendor_first_letter == current %}
<h3><span class="anchor" id="designers-{{ vendor_first_letter }}"></span>{{ vendor_first_letter }}</h3>
{% endunless %}
<li class="vendor-list-item">
{{ vendor }}
</li>
{% else %}
{% assign vendor_first_letter = "#" %}
{% unless vendor_first_letter == current %}
<h3><span class="anchor" id="designers-{{ vendor_first_letter }}"></span>{{ vendor_first_letter }}</h3>
{% endunless %}
<li class="vendor-list-item">
{{ vendor }}
</li>
{% endif %}
{% assign current = vendor_first_letter %}
{% endfor %}
</ul>
</div>
Some of these vendors don't currently have any items in stock so it's pointless to have them show up here. Is it possible to display only the vendors that have items in stock within their collection?
I currently have 2 collection tags in my store for 'in-stock' and 'sold-out' to help filter them with our filter menu and that is appended to the url so we only show customers in stock items.
Since a product has a vendor, and a product has inventory, you could just check that way. It would be insanely slow and obnoxious but hey! That is what a hosted platform is for, to turn crazy Liquid into the right tight HTML.
Note the Liquid for product.available
Returns true if a product is available for purchase. Returns false if all of the products variants' inventory_quantity values are zero or less, and their inventory_policy is not set to "Allow users to purchase this item, even if it is no longer in stock."
So while you loop through your vendor list, loop through all the products, checking the product vendor for a match, and the availability. If they don't suit you... skip the vendor.
Would be interesting to see how slow this is... but you never know till you try...
Another approach, perhaps smarter, is to iterate all your in-stock products once. Build your vendor list out of that, instead of shop.vendors.
I was able to get this working by writing it like this:
{% for vendor in shop.vendors %}
{% for collection in collections %}
{% if collection.title == vendor %}
{% if collection.all_tags contains 'in-stock' %}
then the conditions for checking the first letter and displaying the vendor, etc. nothing new
It only worked, however, on my dev site that I was testing it on and when I pushed it to production I got liquid error: memory limits exceeded. My dev site is definitely lacking in collections and products compared to my live site so this may work for people who have smaller sites.

how to limit the numbers of product to show

I'm new to shopify. I'm trying to limit the output of the product for example 4 product for each tag. but seems like there is variables for me to loop..
anyone can help? thx.
{% for tag in collection.all_tags %}
{% if current_tags contains tag %}
<li class="active">{{ tag | link_to_remove_tag: tag }}</li>
{% else %}
<li>{{ tag | link_to_add_tag: tag }}</li>
{{ tag }}
{% if collection.products.size > 0 %}
<ul class="product-grid just">
{% for product in collection.products %}
{% if product.tags contains tag %}
<li>{% include 'product-grid-item' %}</li>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p><strong><br/>No products found in this collection.</strong></p>
{% endif %}
{% endif %}
{% endfor %}
The limit parameter can be used to display the first 4 products in a collection:
{% for product in collection.products limit:4 %}
However if you need to display a limited number of products with a given tag, you will need to implement your own counter. See this discussion on the Shopify forums for an example of how to do this.
E.g.
{% for tag in collection.all_tags %}
{{ tag }}
{% assign counter = 0 %}
{% for product in collection.products %}
{% if product.tags contains tag and counter < 4 %}
<li>{% include 'product-grid-item' %}</li>
{% assign counter = counter | plus: 1 %}
{% endif %}
{% endfor %}
{% endfor %}
For a good separation the logic how many items are to be displayed is better put somewhere the "List" is made ready for output.
This way you don't have to do content related maths in the view, which is never a good idea since it doesn't put code where it belong and other people wanting to change something may have difficulties to find it. That being said you can either put the limitations on the collection.products object based on a configured backend parameter just before handing the object to the rendering or you go further back and intervene at the "grab products from database" point and limit/alter the result. ;)
There sure is a possibility to use an incrementing counter and stop at 4 in the template but I can hardly recommend to use that since it's not where the logic should be. The template should show, not think what to show, otherwise it's hardly reusable.

How to Display a Metafield in Shopify

We have a group of products that we want to have FREE Shipping. In order to do so, I have made their weight =0 and created a weight based shipping for 0lbs.
That way the shipping passes through the cart. But...I would like to display the actual weight on the product page.
I have created a metafield for the shipping weight, and I am trying to call that value to the product page, but not having any luck......
Here is what I am trying for code....
//------SHIPPING WEIGHT-------------------------//
{% if product.vendor == 'American Chains' %}
$('.wt').text((variant.ShippingWeight)+'lb');
// {{ variant.metafields.ShippingWeight.shipping_weight }}
{% else %}
$('.wt').text(parseInt(variant.weight * 0.0022046, 10) + 'lb');
{% endif %}
//------SHIPPING WEIGHT-------------------------//
Thanks for any help or direction on this one.
In Product.liquid you only have access to the Product. If you want to access a specific Product Variant you have to loop through the Product Variants. Within the loop you have access to the metafields for a variant.
{% for variant in product.variants %}
// to display the variant metafields use {{resource.metafields.namespace.key}}
{{ variant.metafields.ShippingWeight.shipping_weight }}
{% endfor %}
http://docs.shopify.com/themes/liquid-documentation/objects/metafield
go threw with this link
simple...
{% for field in product.metafields.instructions %}
{{ field | first }}: {{ field | last }}
{% endfor %}
Meta fields are created by using ( metafields or shopify FD ) shopify app for products edit page
Then enter the following values in form fields (Namespace,Key,Value)
After entering values,you can retrive values like following code..,
Namespace = metafield_values,
Key= color,
Value= red,
{% assign value = product.metafields.metafield_values%}
<p>{{ value.color }}</p>
output: red
------------------------------
{{metafields.namespace.key}}
------------------------------
Namespace = prod_video,
{{ product.metafields.prod_video.prod_video }}
{{ collection.metafields.prod_video.prod_video }}
---------metafield loop with same namespace & different key------------
<div class="prod_add_img">
{% for collection in product.collections %}
{% for field in collection.metafields.additional_images %}
<img src="{{ field | last | asset_url }}">
{% endfor %}
{% endfor %}
</div>
In metafield section, shopify show's shortcode. For below screenshot the code is
{{product.metafields.custom.theme_color}}

Shopify If in collection then display this

I am trying to write a simple if statement, but always struggle with shopify's system.
Essentially I want it to do this:
{% if collection.product == 'discontinued' %}
This Product is Discontinued.
{% endif %}
If it's in this collection, then display this text/html. Otherwise it wouldn't display anything. This would be in the product.liquid template.
Any ideas?
This is what ended up working:
{% for c in product.collections %}
{% if c.handle == "discontinued" %}
This product is Discontinued
{% endif %}
{% endfor %}
You can create an array of the collections for a product using map on product.collections. This which will create a new array with your specified property, i.e. the handles of each collection.
You can then check if this new array contains the handle you want to work with.
{% assign productCollections = product.collections | map: "handle" %}
{% if productCollections contains 'your-collection-handle' %}
{% comment %} DoSomething {% endcomment %}
{% endif %}
So for your example:
{% assign productCollections = product.collections | map: "handle" %}
{% if productCollections contains 'discontinued' %}
This product is Discontinued
{% endif %}
You can map other fields if your case is different, such as the title.
I guess this will help any one, I have used in the sidebar of shopify website.
The current collection page will get checked by this below code.
<div class="row-fluid not-animated" data-animate="fadeInUp">
<div class="title">By Collections</div>
<form class="coll">
{% assign col_tags = collection.title %}
{% for collection in collections %}
<input type="radio" value="{{ collection.url }}" name="collections" {% if col_tags contains collection.title %} checked {% endif %} >{{ collection.title | escape }} <br/>
{% endfor %}
</form>
If I understand how liquid collections work in Shopify, you will need to iterate over all of your products.
You'd need to do something similar to this if you are working with collections directly:
{% for product in collection.product %}
{% if product.tags contains 'discontinued' %}
This product has been discontinued :(
{% endif %}
{% endfor %}
If you are just working with a single product you can probably just use the inner if liquid tag part.
References:
Collection.liquid
Product.liquid
You can indeed add discontinued products to a collection called discontinued.
When rendering a product, you could do as csaunders suggests, simply loop through all the products in the discontinued collection, and check if the id of the current product matches any of the products in that collection. If so, do what you must do. No need to use tags.