Showing price after an automatic discount directly on the product page

armdgnthr
Shopify Partner
1 0 10

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!

Replies 20 (20)
Pardoc
Excursionist
13 1 1

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.

Steven_Amrhein
Shopify Partner
7 0 9

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.

  1. Open your theme's main JavaScript file in the code editor, usually Assets > theme.js or Assets > theme.js.liquid. At the very bottom, add this code, which provides the bulk of the discount price functionality:
    /*
    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
    */
  2. Next you'll need to modify the price that appears in product lists, such as on collection pages. Our script needs to know the product variant id of the product in the list. This is done by adding a variant id to a data attribute on the html element that wraps the product price. The location of the code that renders the product list items varies from theme to theme. Here are the file and html tags that you'll need to edit in each theme that I've tested:

    Simple - Snippets > product-grid-item.liquid - <div class="product__prices text-center">
    Boundless - Snippets > product-grid-item.liquid - <p class="product-item__price-wrapper">
    Venture - Snippets > product-cart.liquid - <div class="product-card__price">
    Debut - Snippets > product-price-listing.liquid - <dl class="price price--listing ... >
    Supply - Snippets > product-grid-item.liquid - <div class="product-item--price">

    Within the opening tag of the element that wraps the product price, add:
    {% 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">
  3. Last step. Product recommendations in some themes are loaded via Ajax, so our script may run before these products appear. To update the prices on recommended products, you need to edit Sections > product-recommendations.liquid, if your theme contains this file. Just after the line:
    {%- 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!

Steven_Amrhein
Shopify Partner
7 0 9

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.

GRUB
New Member
2 0 1

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

MvW
New Member
2 0 2

Still waiting here also! Would be great if they found a solution looking at the upcoming holidays and black friday....

dram
Tourist
4 0 4

all this is inconceivable! Showing the discount only in the cart is against all usability rules. Please fix it

lpscleay
Tourist
5 0 10

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.

HouseofBestToys
New Member
2 0 0

So where would you paste/copy this?

PatrickF1
Tourist
6 0 3

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.  

jesssss
New Member
1 0 0

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