How can I apply a discount to multiple variants in code?

Solved

How can I apply a discount to multiple variants in code?

johnfrail
Tourist
10 0 0

I added "you save x%" using this code:

{% capture discount %}
{{ current_variant.compare_at_price | minus: current_variant.price | money }}
({{ current_variant.compare_at_price | minus: current_variant.price | times: 100.0 | divided_by: current_variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%)
{% endcapture %}

You save:
{{ discount }}

But I couldn't make it work when I have multiple variants. 

Normally, it works on the first reload but how can I make it change when I selected different variant?
Help would be appreciated. Thank you.

Accepted Solution (1)
Starbadar
Excursionist
16 3 24

This is an accepted solution.

ok I'm back now, sorry bout the wait, aight so the issue is that your data-sale-price is controlled by a function within theme.js which changes the value based on the variant selected, Shopify's liquid isn't as good as Angular or React yet, basically, you can't double bind elements in order to refresh the data once it's loaded which is why liquid.... is far behind and sucks but that's life, so Javascript to the rescue.

 

On line 51, you'll find this

 

<span class="price-item price-item--sale" data-sale-price>

Doing a quick search through theme.js we can trace where the data is being changed and there we go, let's change the code a bit to have it render what we want. However before let's change the liquid a bit to this

<div class="price__sale">
    <dd>
      <div class="price-item price-item--sale" data-sale-price>
        {{ money_price }}
        <div class="price-item price-item--sale--save">You save: {{ variant.compare_at_price | minus:variant.price | money }} ({{ variant.compare_at_price | minus:variant.price | times: 100.0 | divided_by:variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%)</span>
      </div>
    </dd>
  </div>

Basically, I remove the Sale string as it's no longer needed and moved the sale up.

 

In Theme.js

 

On line 3678 You should see this:

$salePrice.html(
  theme.Currency.formatMoney(variant.price, theme.moneyFormat)
);

Change it to this

$salePrice.html(
  '<div class="price-item price-item--sale">' + 
    theme.Currency.formatMoney(variant.price, theme.moneyFormat) + 
    '<div class="price-item  price-item--sale--save">You save: ' + 
      theme.Currency.formatMoney(variant.compare_at_price - variant.price, theme.moneyFormat) + 
              ' (' + Math.round((1 - (variant.price / variant.compare_at_price)) * 100) + '%) ' + 
    '</div>' + 
  '</div>'
);

It could be refactored a bit with more elegant code but ES6 isn't compatible with most older browsers which represent 5-15% of your sales, unless you installed a polyfill library like babel.js

Voila, it works now.

 

Have fun

View solution in original post

Replies 10 (10)

Starbadar
Excursionist
16 3 24

Hey jfrail,

 

This is pretty simple actually, all you have to do is place this code within the for loop of your variants.

 

 

{% assign sortedVariants = product.variants %}
{% for variant in sortedVariants %}
  {% if variant.available %}
    {% capture discount %}
    {{ variant.compare_at_price | minus:variant.price | money }}
    ({{ variant.compare_at_price | minus:variant.price | times: 100.0 | divided_by:variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%)
    {% endcapture %}

    You save: {{ discount }}
  {% endif %}
{% endfor %}

 

 

johnfrail
Tourist
10 0 0

Hello Starbadar,

 

Thank you so much for the fast respond. I tried what you suggest and it doesn't work for me. I am using debut theme, for some reason can you tell where should I put it?

 

I really appreciate it. Thank you.

Starbadar
Excursionist
16 3 24

Well, that depends on which version of Debut you have, I'm not familiar with all versions however assuming you want this data to show next to the pricing you should see something like this in product-template.liquid.

 

<div class="product__price">
  {% include 'product-price', variant: current_variant %}
</div>

If that's the case then you wanna go into product-price.liquid

 

On line 45 Change

<div class="price__sale">
    <dt>
      <span class="visually-hidden visually-hidden--inline">{{ 'products.product.sale_price' | t }}</span>
    </dt>
    <dd>
      <span class="price-item price-item--sale" data-sale-price>
        {{ money_price }}
      </span>
      <span class="price-item__label" aria-hidden="true">{{ 'products.product.on_sale' | t }}</span>
    </dd>
  </div>

To this

 

<div class="price__sale">
    <dt>
      <span class="visually-hidden visually-hidden--inline">{{ 'products.product.sale_price' | t }}</span>
    </dt>
    <dd>
      <span class="price-item price-item--sale" data-sale-price>
        {{ money_price }}
      </span>
      <span class="price-item__label" aria-hidden="true">{{ 'products.product.on_sale' | t }}</span>
<span class="price-item price-item--sale">You save: {{ variant.compare_at_price | minus:variant.price | money }} ({{ variant.compare_at_price | minus:variant.price | times: 100.0 | divided_by:variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%)</span> </dd> </div>

Tadaaa

johnfrail
Tourist
10 0 0

Starbadar,

 

I have tried what you instruct and follow it carefully. I believe we have the same debut version because all the codes that you show are very similar to mine.

The problem is when I selected a new variant the percentage discount disappear.

 

Thank you for your response.

Screen Shot 2019-04-19 at 1.16.13 PM.pngScreen Shot 2019-04-19 at 1.16.21 PM.png

Starbadar
Excursionist
16 3 24
Oh that's odd. I'm away from my desk right now, at the restaurant but I'll respond when I get home with an answer 🙂
johnfrail
Tourist
10 0 0

Okay. Thanks a lot. I'll be gladly waiting.

Starbadar
Excursionist
16 3 24

This is an accepted solution.

ok I'm back now, sorry bout the wait, aight so the issue is that your data-sale-price is controlled by a function within theme.js which changes the value based on the variant selected, Shopify's liquid isn't as good as Angular or React yet, basically, you can't double bind elements in order to refresh the data once it's loaded which is why liquid.... is far behind and sucks but that's life, so Javascript to the rescue.

 

On line 51, you'll find this

 

<span class="price-item price-item--sale" data-sale-price>

Doing a quick search through theme.js we can trace where the data is being changed and there we go, let's change the code a bit to have it render what we want. However before let's change the liquid a bit to this

<div class="price__sale">
    <dd>
      <div class="price-item price-item--sale" data-sale-price>
        {{ money_price }}
        <div class="price-item price-item--sale--save">You save: {{ variant.compare_at_price | minus:variant.price | money }} ({{ variant.compare_at_price | minus:variant.price | times: 100.0 | divided_by:variant.compare_at_price | money_without_currency | times: 100 | remove: '.0'}}%)</span>
      </div>
    </dd>
  </div>

Basically, I remove the Sale string as it's no longer needed and moved the sale up.

 

In Theme.js

 

On line 3678 You should see this:

$salePrice.html(
  theme.Currency.formatMoney(variant.price, theme.moneyFormat)
);

Change it to this

$salePrice.html(
  '<div class="price-item price-item--sale">' + 
    theme.Currency.formatMoney(variant.price, theme.moneyFormat) + 
    '<div class="price-item  price-item--sale--save">You save: ' + 
      theme.Currency.formatMoney(variant.compare_at_price - variant.price, theme.moneyFormat) + 
              ' (' + Math.round((1 - (variant.price / variant.compare_at_price)) * 100) + '%) ' + 
    '</div>' + 
  '</div>'
);

It could be refactored a bit with more elegant code but ES6 isn't compatible with most older browsers which represent 5-15% of your sales, unless you installed a polyfill library like babel.js

Voila, it works now.

 

Have fun

johnfrail
Tourist
10 0 0

Hi Starbadar,

 

Thank you so much for your help. This saves me from my work.

This is absolutely great and works like charm.

 

I now understand that liquid cannot alter an html element without reloading the page. Anyway, Thanks a lot.

 

Have a great day ahead.

Vladd
Tourist
19 0 2

It just prints out all possible price options. The calculations are correct.

But the discount for the currently chosen variant should be displayed. How to fix it?

 

I use the Dawn theme. ss.png

satishsumbria
Shopify Partner
1 0 0

Hi, did you resolve the issue? I'm facing the same problem

satishsumbria_0-1715533524261.png