Shopify themes, liquid, logos, and UX
Hi there!
I wanted to test the automatic discounts for special events, for example the Summer Sales or whatever.
So the I created my automatic discount and selected the products I want to apply it on. On the cart, no problem the price displayed is the actual price minus the reduction.
Thing is, I'd like to change the price on the product page too. For the moment, the normal price is still displayed. If possible I would like to avoid setting the price manually for each variant of each product, I have a lot of them...
In fact, I'd like to have something exactly like when you I apply manually the discount in the 'Pricing' section of the product: the real price crossed and the discounted price showed. And with the sentence 'You saved $XX !" also.
I tried to modify the code by copying the code from the cart page to the product page but was unsuccessful. I can't manage to get the discounted price, the price showing is still the one before the discount.
Anyone has an idea how I can solve this ? Or an indication ?
Thanks a lot!
This is exacly what I'm looking for and got nothing yet on google, I hope someone could help us.
I have the same issues, I am not able to find anything to help
Looking for a solution for this as well....
Shopify....? Are you listening?
Same here, would love to only have 1 price list, then everything else managed by "automatic discounting"
Have requested via live chat, so will wait to hear back
I'm trying to do the same thing. I had to go back to my products and change the pricing manually, and take off the automatic discount. It was easy though with holding down shift key and clicking the bottom cell to be able to change all at once. I agree - Shopify needs to add an option to the discount settings so that customers can see the discount reflect immediately.
I can't believe this isn't available yet - all the major retailers have slashed prices (especially on Cyber Monday) and you are way more apt to add something to your cart when you see the savings. Shopify - please hurry up!
After much research, I also did not find a solution on the internet. The main problem is that 'line_level_discount_allocations' is only available in a for loop which traverses the 'cart' object. I tinker with a functional solution for our shop, but I warn you I am a novice:
let pvfID = {{ product.variants.first.id }}, newVal = 1, discounts= [], discountAllocation = function (type, title, value, valueType, allocationMethod, targetSelection, targetType, totalAllocatedAmount) { this.type = type; this.title = title; this.value = value; this.valueType = valueType; this.allocationMethod = allocationMethod; this.targetSelection = targetSelection; this.targetType = targetType; this.totalAllocatedAmount = totalAllocatedAmount; }, pvfIDPOST = function() { jQuery.post('/cart/add.js', {quantity: 1, id: pvfID}) }, pvfIDREMOVE = function(newQty){ jQuery.post('/cart/change.js', {quantity: newQty, id: pvfID}) }; $.when( pvfIDPOST() ).done(setTimeout (function() { jQuery.getJSON('/cart.js', function(cart) { for(let i = 0; i < cart.items.length; i++){ if(pvfID === cart.items[i].id){ let currentQty = cart.items[i].quantity; if(cart.items[i].line_level_discount_allocations.length > 0){ for(let it = 0; it < cart.items[i].line_level_discount_allocations.length; it++){ let currentItem = cart.items[i].line_level_discount_allocations[it].discount_application; discounts[it] = new discountAllocation(currentItem.type, currentItem.title, currentItem.value, currentItem.value_type, currentItem.allocation_method, currentItem.target_selection, currentItem.target_type, currentItem.total_allocated_amount); } showDiscount(); pvfIDREMOVE(currentQty-1); }else{ console.log('discount allocations not fount'); pvfIDREMOVE(currentQty-1); } } } }); Shopify.getCart(function(data){ console.log(data); }) }, 2000 )); function showDiscount(){ for(let i = 0; i < discounts.length; i++){ console.log(discounts[i]) } }
This javascript code uses the jquery library. it uses the shopify API to add the product from the product page consulted in the cart, extracts the automatic promotion and finally it removes the product from the cart. The content of the automatic promotion will be visible in the console. You still have to modify the current code to display the information that interests you on your template.
So where would you paste/copy this?
did you found already a solution?
thanks
iwan
my system is not perfect but it works for me, but not on variant product
i use :
{% assign prixTTC = product.price | times: 1.2 %} {% if product.compare_at_price_max > 0 %} {% assign baseTTC = product.compare_at_price | times: 1.2 %} {% assign pourcentage = product.price | times: 1000 | divided_by: product.compare_at_price_max %} {% assign pourcentageReduction = 1000 | minus: pourcentage | divided_by: 10 %} {% assign eurosReduction = baseTTC | minus: prixTTC %} {% endif %} <script type="text/javascript"> // Auto Discount let pvfID = {{ product.variants.first.id }}, priceShopify = {{ product.price }}, taxes = 1.2, totalValueTTC = 0, discounts= [], discountAllocation = function (type, title, value, valueType, allocationMethod, targetSelection, targetType, totalAllocatedAmount) { this.type = type; this.title = title; this.value = value; this.valueType = valueType; this.allocationMethod = allocationMethod; this.targetSelection = targetSelection; this.targetType = targetType; this.totalAllocatedAmount = totalAllocatedAmount; }, pvfIDPOST = function() { jQuery.post('/cart/add.js', {quantity: 1, id: pvfID}) }, pvfIDREMOVE = function(newQty){ jQuery.post('/cart/change.js', {quantity: newQty, id: pvfID}) }; // Check Auto Discount function checkAutoDiscount(){ jQuery.getJSON('/cart.js', function(cart) { for(let i = 0; i < cart.items.length; i++){ if(pvfID === cart.items[i].id){ if(cart.items[i].variant_options.length >= 1 ){ let currentQty = cart.items[i].quantity; if(cart.items[i].line_level_discount_allocations.length > 0){ for(let it = 0; it < cart.items[i].line_level_discount_allocations.length; it++){ let currentItem = cart.items[i].line_level_discount_allocations[it].discount_application; discounts[it] = new discountAllocation(currentItem.type, currentItem.title, currentItem.value, currentItem.value_type, currentItem.allocation_method, currentItem.target_selection, currentItem.target_type, currentItem.total_allocated_amount); } showDiscount(); pvfIDREMOVE(currentQty-1); }else{ console.log('automatic discount : no'); pvfIDREMOVE(currentQty-1); } } } } }); } // YOU NEED CUSTOM THIS FOR YOUR THEM : function showDiscount(){ $('.detail-price .price-sale').fadeOut(); for(let i = 0; i < discounts.length; i++){ let value = parseInt(discounts[i].value, 10); // Percent Discount if(discounts[i].valueType === 'percentage'){ let valueTTC = (((priceShopify * value) / 10000)*taxes).toFixed(2); $('#product_v2_allDiscountBox').append( '<div class="product_v3_badge4">'+ '<i class="demo-icon icon-electro-cart-icon"></i>'+ ' '+discounts[i].title+' : -'+value+'%'+' vous économisez : '+valueTTC+'€'+ '</div>' ); if($(window).width() < 457 ){ $('.detail-price').append( '<div class="price-sale" style="color: #5bb300!important">'+ ((priceShopify / 100) * taxes - valueTTC).toFixed(2)+'€'+ '</div>' ); // Product Discount {% if product.compare_at_price_max > 0 %} $('.product_v2_boxContent .product-price').append( '<div class="product_v2_reductionValue" style="background-color: rgb(194, 222, 244);">'+ '<div class="sale-text">'+ 'Remise sur le produit : <strong>-'+{{pourcentageReduction}}+'%</strong>'+ '</div>'+ '</div>' ) {% endif %} // Cart Discount $('.product_v2_boxContent .product-price').append( '<div class="product_v2_reductionValue" style="background-color: rgb(194, 222, 244);">'+ '<div class="sale-text">'+ 'Offre spéciale : <strong>-'+value+'%</strong>'+ '</div>'+ '</div>' ) }else{ $('.product_v2_reduction').append( '<div class="product_v2_reductionValue">'+ '<div class="sale-text" style="background-color: #5bb300">'+ '-'+value+'%'+ '</div>'+ '</div>' ); $('.detail-price').append( '<div class="price-sale" style="color: #5bb300!important">'+ ((priceShopify / 100) * taxes - valueTTC).toFixed(2)+'€ TTC'+ '</div>' ); } totalValueTTC += valueTTC; // Remise fixe }else{ let valueTTC = (value * taxes).toFixed(2); $('#product_v2_allDiscountBox').append( '<div class="product_v3_badge4">'+ '<i class="demo-icon icon-electro-cart-icon"></i>'+ ' '+discounts[i].title+' : -'+valueTTC+'€ TTC'+ '</div>' ); if($(window).width() < 457 ){ $('.detail-price').append( '<div class="price-sale" style="color: #5bb300!important">'+ ((priceShopify / 100) * taxes - valueTTC).toFixed(2)+'€'+ '</div>' ); // Product Discount {% if product.compare_at_price_max > 0 %} $('.product_v2_boxContent .product-price').append( '<div class="product_v2_reductionValue" style="background-color: rgb(194, 222, 244);">'+ '<div class="sale-text">'+ 'Remise sur le produit : <strong>-'+{{pourcentageReduction}}+'%</strong>'+ '</div>'+ '</div>' ) {% endif %} // Cart Discount $('.product_v2_boxContent .product-price').append( '<div class="product_v2_reductionValue" style="background-color: rgb(194, 222, 244);">'+ '<div class="sale-text" >'+ 'Offre spéciale : <strong>-'+value * taxes +'€ TTC</strong>'+ '</div>'+ '</div>' ) }else{ $('.product_v2_reduction').append( '<div class="product_v2_reductionValue">'+ '<div class="sale-text" style="background-color: #5bb300">'+ '-'+value+'€'+ '</div>'+ '</div>' ); $('.detail-price').append( '<div class="price-sale" style="color: #5bb300!important">'+ ((priceShopify / 100) * taxes - valueTTC).toFixed(2)+'€ TTC'+ '</div>' ); } totalValueTTC += valueTTC; } // Add style mobile if($(window).width() < 457 && {{product.compare_at_price_max}} != null ){ for (let ite =0; ite < $('.product_v2_reduction').length; ite++){ $('.detail-price').css('width','75%'); $('.detail-price').css('margin','auto'); $('.detail-price').css('flex-flow','row-reverse'); $('.product_v2_reduction').css('margin','10px 0'); $('.price-compare').css('flex','1'); $('.price-compare s').css('margin','0 5px 3px 5px'); $('.price-compare s').css('font-size','22px'); $('.detail-price .product_v2_reductionValue').css('display','none'); $('.price-sale').css('font-size','30px'); $('.price-sale').css('flex','1'); } } } } // Start checkAutoDiscount if variant is not available {% unless variant.available %} $.when( pvfIDPOST() ).done(setTimeout (function() { checkAutoDiscount() }, 1000 )); {% endunless %} </script>
I hope this will inspire you.
Hi, showing automatic discount prices on pages other than the cart is possible, but it requires you being comfortable editing your theme. This solution works on collection pages and product pages, and with variants. It does not work with automatic discounts that have minimum requirements other than a quantity of 1. This solution may have unintended consequences for analytics and page speed, because it involves adding and removing large numbers of products from the cart using the Ajax API. @Pardoc's method is on the right track. Because automatic discounts are only applied after products are added to the cart, on every page where a product price appears, we have to add those products to the cart temporarily using the Ajax API, check their discounted prices in the cart, update prices on the page with those discounted prices, then remove them from the cart.
I've listed instructions below which should work with most of Shopify's free sectioned themes. I've tested it with Simple, Boundless, Venture, Debut, and Supply. You can easily break your theme, so be sure to make a backup before editing any code. To make a backup, navigate to the themes page and next to your live theme click Actions > Download theme file.
/* Update displayed product prices to reflect automatic discounts */ //newly added product listing selector and theme's single product variant select element if($('[data-price-id], form[action="/cart/add"] select[name="id"]').length){ displayAutoDiscounts(); } //when variants are changed on a product page, update the displayed price var $new_price = $(); $(document).on("change", ".single-option-selector", function(){ $new_price.remove(); //theme's single product price wrapper element var $price = $('[itemprop="price"]:not(meta), .product__price, #productPrice-product-template'); $price.show(); displayAutoDiscounts(); }); //add all products prices on this page to a data array including a unique item property so that they can be removed later function displayAutoDiscounts(){ var items_to_add = []; var item_counter = 0; $('[data-price-id]').each(function( index ){ items_to_add.push({ quantity: 1, id: $(this).data('price-id'), properties: { 'discount_check': 1 } }); }); //theme's single product variant option element $('form[action="/cart/add"] select[name="id"] option').each(function( index ){ items_to_add.push({ quantity: 1, id: $(this).val(), properties: { 'discount_check': 1 } }); }); //add items to the cart if(items_to_add.length){ $.ajax({ type: 'POST', url: '/cart/add.js', dataType: 'json', data: { "items": items_to_add }, success: itemsAdded }); } } //check the items in the cart for automatic discounts, update the displayed price, then remove them from the cart function itemsAdded(response){ var items_to_remove = {}; //update displayed prices for (item of response.items) { items_to_remove[ item.key ] = 0; if(item.discounted_price < item.original_price && item.discounts.length > 0){ //item has a discount, update the sale price var discount_dollars = item.discounted_price / 100; discount_dollars = discount_dollars.toLocaleString("en-US", {style:"currency", currency:"USD"}); var regular_dollars = item.original_price / 100; regular_dollars = regular_dollars.toLocaleString("en-US", {style:"currency", currency:"USD"}); var saved_dollars = (item.original_price - item.discounted_price) / 100; saved_dollars = saved_dollars.toLocaleString("en-US", {style:"currency", currency:"USD"}); //get product listing price element var $price = $('[data-price-id="'+item.id+'"]'); var is_single = false; if(!$price.length){ //theme's single product variant option element $price = $('form[action="/cart/add"] select[name="id"] option[value="'+item.id+'"]'); is_single = true; } if($price.is(':selected')){ //get single product price element //theme's single product price wrapper element $price = $('[itemprop="price"]:not(meta), .product__price, #productPrice-product-template'); } else if( $price.is('option')){ //price is for the unselected variant, skip continue; } /* adjust the following to match your theme's sale price display */ if(is_single){ //single product price display update $price.hide(); $new_price.remove(); $new_price = $( '<h4><span style="color:green">' + discount_dollars + '</span> \ <s>' + regular_dollars + '</s>\ <small style="display:inline-block; line-height: 1.2; padding: 0 0.2em; color:white; background: green;">SALE</small> \ <small style="color:green;">You saved ' + saved_dollars + '!</small></h4>' ); $price.after($new_price); } else { //product listing price display update $price.empty(); $price.append( '<span><span style="color:green">' + discount_dollars + '</span> \ <s>' + regular_dollars + '</s></span>\ <small style="display:inline-block; line-height: 1.2; padding: 0 0.2em; color:white; background: green;">SALE</small>' ); } /* END adjust the following to match your theme's price elements */ } } //remove items from the cart $.ajax({ type: 'POST', url: '/cart/update.js', dataType: 'json', data: { updates: items_to_remove } }); } //in case the there are temp items still in the cart, remove them on the cart page if($('body').hasClass('template-cart')){ cleanupCart(); } function cleanupCart(){ if($('[data-cart-item-property-name]:contains("discount_check")').length){ $.getJSON('/cart.js', function(cart) { var items_to_remove = {}; cart.items.forEach(function(item) { //only remove discount check items from cart based on item property if(typeof item.properties.discount_check !== 'undefined'){ items_to_remove[item.key] = 0; } }); //remove items from the cart and refresh the page var params = { url: '/cart/update.js', data: { updates: items_to_remove }, dataType: 'json' }; if( Object.keys(items_to_remove).length !== 0 ){ $.post(params).always( function() { location.reload(); } ); } else { location.reload(); } }); } } /* END Update displayed product prices to reflect automatic discounts */
{% if product.variants.first.available %}data-price-id="{{ product.variants.first.id }}"{% endif %}For example, with the Venture theme, that opening tag will now be:
<div {% if product.variants.first.available %}data-price-id="{{ product.variants.first.id }}"{% endif %} class="product-card__price">
{%- if recommendations.products_count > 0 -%}add the line:
<script>if (typeof displayAutoDiscounts === "function") { displayAutoDiscounts(); }</script>This re-runs the JavaScript function that updates the prices.
If these instructions don't work with your theme, check to make sure that you have included jQuery. Also, in theme.js you may need to replace the jQuery selector underneath
//theme's single product price wrapper element
with a jQuery selector for the html element that wraps the price on single product pages.
This solution is somewhat generic, so the discount price will need to be styled to match your theme. In theme.js, the html for the discount price can be found underneath
/*
adjust the following to match your theme's sale price display
*/
I've included different price discount html for the single product page and product listings.
This code can definitely be optimized, but hopefully it helps someone!
WARNING: I just confirmed that my above code adds a huge amount of Add-to-cart events to Shopify Analytics, Facebook, and Google Analytics. I'm not sure if there's a way to exclude them, so use it at your own risk.
Hi Steven_Amrhein,
Did you end up figuring out how to fix this issue? I did the same code as what was detailed in the above post, and I also realized random add to cart events. Does anyone know which part of the code is doing this? Otherwise everything outlined above worked but it is messing up the add to cart analytics. Anyway of fixing it? I did mine on the minimal theme. Please let me know. Thanks
Hi,
I manually solved this be adding the following codes :
Shopify Automatic Discount : 25% on ALL products except products with product type is NODISCOUNT (or whatever condition you have on your automatic discount)
On Product page: snippets\product-price.liquid
assign compare_at_price = variant.compare_at_priceassign price = variant.price
if product.type == "NODISCOUNT"assign compare_at_price = variant.compare_at_priceassign price = variant.priceelseassign compare_at_price = variant.priceassign price = variant.price | times: 0.75endif
This worked for me for the product page but in the home page in my bestselling products section it still shows without the discounted price. Can you tell me if there is a code for that too?
If anyone have used this code on debut theme what changes you made?
As when I am using it it's not working
Still nothing yet?
I was expecting something like
{% if product.descount == true %}
This item have an automatic descount
{% end if %}
But sadly that object do not exist. I have 500 products with variables, I don't want to do it manually
Still waiting here also! Would be great if they found a solution looking at the upcoming holidays and black friday....
all this is inconceivable! Showing the discount only in the cart is against all usability rules. Please fix it
Like so many things shopify, it is just mad that this is not easily achievable. Like excluding products/collections from previously created discount codes, or setting region specific pricing, it's simply far easier and profitable for shopify to shovel the issue off to an app dev, and take a 30% cut for not solving anything.
There is zero incentive for shopify to fix any of the issues that repeatedly come up on here because they make more money forcing us to buy apps to plug holes in shopify functionality.
It is absolutely ridiculous that Shopify has not created this solution yet. You are 100% correct, they do not make any changes to their usability because they profit more from the apps, yet they are frustrating their customers to no end! I am so tired of not having simple features on my store because of Shopify's greed.
Any update on this question.
its 2024... is there an update for this? maybe there is and i just havent found it yet.
Yes I am still looking for this too. There may be third party apps that can acheive this, but I guess the next best option is to "bulk edit" every product in that collection to allow for it. What a huge pain!
thanks again Shopify for listening to us.... why don't you ever just listen to your stores? 😿
That's a work around, but it doesn't create the same customer experience. Showing the regular price and then the discounted price motivates customers. Just discounting your price, now just becomes your price. You will not get the same results in sales. Shopify should be ashamed of themselves, but that ship sailed when they go rid of phone support.
Its not a bad idea, its just a shame that this is the best we can do with this awful system.
Starting a B2B store is a big undertaking that requires careful planning and execution. W...
By JasonH Sep 23, 2024By investing 30 minutes of your time, you can unlock the potential for increased sales,...
By Jacqui Sep 11, 2024We appreciate the diverse ways you participate in and engage with the Shopify Communi...
By JasonH Sep 9, 2024