How to show “spend X to get Free Shipping” in Prestashop

In this Prestashop tutorial, we will see how to boost our sales by letting customers know how much they still have to spend in order to be eligible for free shipping.

Version used: Prestashop 1.6

Setting the Free Shipping amount

To keep thing simple, in this tutorial we will only consider the “Free shipping starts at” value that we can configure in the back office, instead of dealing with all the 0-fee weight or price ranges that it’s possible to setup for each carrier.

Therefore, before starting, head to Shipping -> Preferences and set “Free shipping starts at” to any value you like. Please notice this represent the price in the default currency, and it’s not possible to set up one for each, at the time being.

Retrieving the Free shipping value – 2 approaches

When dealing with an MVC pattern, the best approach is usually to keep logic and display code separated. Prestashop, however, allows us to retrieve the previously set configuration value in templates too, saving us the trouble to create an override and extend the default OrderController, in order to assign the value we need.

Therefore, given that the best way to go would be to create an override, grab the configuration value, and assign it to the template, for simplicity reasons I will get it directly in the template, so it’s ready to use.

Amending the template: shopping-cart.tpl

Reach your theme folder and open up shopping-cart.tpl. We will be adding our small advertisement right below the cart summary. This is the perfect chance to apply some cross-selling principles; therefore, if you use the cross-selling module in the cart page, the best spot to maximize your cross-selling rate is right above it, before the shopping cart hook .

Locate:

<div id="HOOK_SHOPPING_CART">{$HOOK_SHOPPING_CART}</div>

And right before it, add the following

{assign var='freeshipping_price' value=Configuration::get('PS_SHIPPING_FREE_PRICE')}

Explanation: as I mentioned before, I am grabbing the free shipping value directly from the tpl file, and assigning it to a variable that can be used within our Prestashop template.

Then, we need to check if it is actually holding a value


	{assign var='freeshipping_price' value=Configuration::get('PS_SHIPPING_FREE_PRICE')}
	{if $freeshipping_price}
		{assign var='freeshipping_price_converted' value={toolsConvertPrice price=$freeshipping_price}}	
	{/if}


Explanation: if the value exists, we need to convert it to the current currency (which might be other than the default). Therefore, we use the very handy toolsConvertPrice method to make sure the value is correctly set to the actual customer currency.

What’s next? We need to compare the total cart value without shipping to the free shipping one, and display a message in case it’s positive:

	
	{assign var='freeshipping_price' value=Configuration::get('PS_SHIPPING_FREE_PRICE')}

	{if $freeshipping_price}
		{assign var='freeshipping_price_converted' value={toolsConvertPrice price=$freeshipping_price}}


		{math equation='a-b' a=$total_price b=$total_shipping assign='total_without_shipping'}
		{math equation='a-b' a=$freeshipping_price_converted b=$total_without_shipping assign='remaining_to_spend'}

		{if $remaining_to_spend > 0}
			<p>{l s='Your total (without shipping) is'} {convertPrice price=$total_without_shipping}</p>
			<p><strong>{l s='You will be eligible for free shipping if you spend another'} {convertPrice price=$remaining_to_spend}</strong></p>
		{/if}
	

	{/if}

Explanation: first, we subtract the total shipping price from the overall total, which is the value taken in consideration by Prestashop when deciding if a cart is eligible or not, and then we simply subtract it from our minimum free shipping threshold. If the result is positive, we tell our customers how much is left to get rid of the shipping charge!

You like the tuts and want to say "thank you"? Well, you can always feel free to donate:

  • http://www.rempaddesign.com Pavel Andrei

    The right answer for Amount X to spend until free shipping in the header message (blockcart.tpl) with ajax and all good is here: https://www.prestashop.com/forums/topic/268269-show-remaining-amount-to-free-shipping-in-cart/?p=1399766

    Works great under PS 1.6.
    Thank you.

  • http://www.rempaddesign.com Pavel Andrei

    Hi NemoPS,

    I’m working on a prestashop store now and getting problems with this “Need to buy some X more to get free shipping”.

    For the shoping-cart.tpl module that you described it works just fine, but for the blockcart.tpl in Modules (for display a message in header) it’s a pain.

    I get some results with this snipet:

    {if 200-$total > 0}

    You should by products in ammount of

    {200-$total} Curency

    and you will get FREE SHIPPING!

    {else}

    {/if}

    The script is not optimised at all and I would like to have yours working on the blockcart too but have not managed to change it acording to what you said here https://www.prestashop.com/forums/topic/348398-free-tutorial-how-to-show-%E2%80%9Cspend-x-to-get-free-shipping%E2%80%9D/:

    @ghost4life
    {$total}
    And this as shipping amt
    {$shipping_cost}

    Thanks a lot and hope you can help me manage this.
    Best regards.

  • Sergio

    This code needs to be able to update each time increasing number of products .. and also if you remove products .. as would be done ?
    Only updated reloading the page.

  • Magdalena

    Hi Nemo!
    Tried it and works great! :) However this will be in English regardless of the language selected. How can I do if my site has 2 languages?

    Thanks!

    • NemoPS

      It should be possible to translate it from the back office if you used {l s=””…

  • Stan Piotrowski

    I can pay for thtat

    • NemoPS

      Well unfortunately I never tried it, but can you see if it works by adding it to blockcart.tpl, in the template folder, inside the .layer_cart_product box

  • mazoor

    Try this one:

    {assign var=’freeshipping_price’ value=Configuration::get(‘PS_SHIPPING_FREE_PRICE’)}
    {if $freeshipping_price}

    {assign var=’freeshipping_price_converted’ value={toolsConvertPrice price=$freeshipping_price}}
    {math equation=’a-b’ a=$total_price b=$total_shipping assign=’total_without_shipping’}
    {math equation=’a-b’ a=$freeshipping_price_converted b=$total_without_shipping assign=’remaining_to_spend’}
    {if $remaining_to_spend > 0}
    {l s=’Get FREE shipping for this order’}
    {l s=’Your total (without shipping) is’} {convertPrice price=$total_without_shipping}

    {l s=’You will be eligible for free shipping if you spend another’} {convertPrice price=$remaining_to_spend}
    {/if}

    var freeshipping_price_converted = {$freeshipping_price_converted}
    $(‘#total_product’).bind(‘DOMNodeInserted DOMSubtreeModified DOMNodeRemoved’, function(event) {
    //var curreny_str = $(‘#totalSpend.value’).html().charAt(0);
    var total_without_shipping = $(‘#total_product’).html();
    total_without_shipping = parseFloat(total_without_shipping.replace(‘$’,”)).toFixed(2);
    var remaining_to_spend = (freeshipping_price_converted – total_without_shipping).toFixed(2);
    if(remaining_to_spend > 0) {
    $(‘#remaingSpendContainer’).show();
    $(‘#totalSpend .value’).html(total_without_shipping);
    $(‘#remaingSpend .value’).html(remaining_to_spend);
    } else {
    $(‘#remaingSpendContainer’).hide();
    }
    });

    {/if}

  • jaxTus

    UPDATE:
    You need to change outer container div id to ‘remaingSpendContainer’ as there was a conflict with
    also added show() and hide() on the outer container div when the free shipping value is reached.
    Updated code below:

    {assign var=’freeshipping_price’ value=Configuration::get(‘PS_SHIPPING_FREE_PRICE’)}
    {if $freeshipping_price}

    {assign var=’freeshipping_price_converted’ value={toolsConvertPrice price=$freeshipping_price}}
    {math equation=’a-b’ a=$total_price b=$total_shipping assign=’total_without_shipping’}
    {math equation=’a-b’ a=$freeshipping_price_converted b=$total_without_shipping assign=’remaining_to_spend’}
    {if $remaining_to_spend > 0}
    {l s=’Get FREE shipping for this order’}
    {l s=’Your total (without shipping) is’} {convertPrice price=$total_without_shipping}
    {l s=’You will be eligible for free shipping if you spend another’} {convertPrice price=$remaining_to_spend}
    {/if}

    var freeshipping_price_converted = {$freeshipping_price_converted}
    $(‘#total_product’).bind(‘DOMNodeInserted DOMSubtreeModified DOMNodeRemoved’, function(event) {
    var curreny_str = $(‘#totalSpend .value’).html().charAt(0);
    var total_without_shipping = $(‘#total_product’).html();
    total_without_shipping = parseFloat(total_without_shipping.replace(‘$’,”)).toFixed(2);
    var remaining_to_spend = (freeshipping_price_converted – total_without_shipping).toFixed(2);
    if(remaining_to_spend > 0) {
    $(‘#remaingSpendContainer’).show();
    $(‘#totalSpend .value’).html(curreny_str.concat(total_without_shipping));
    $(‘#remaingSpend .value’).html(curreny_str.concat(remaining_to_spend));
    } else {
    $(‘#remaingSpendContainer’).hide();
    }
    });

    {/if}

  • jaxTus

    Hi darkf3d3,

    The below code will auto updates the display in the page if the total products value changes.
    Is using JavaScript to recalculate the values and rewrite them back into the tags
    This way and currency or language changes are retained as it’s just updating the number values.
    Not tested thoroughly but working for me nicely.

    {assign var=’freeshipping_price’ value=Configuration::get(‘PS_SHIPPING_FREE_PRICE’)}
    {if $freeshipping_price}

    {assign var=’freeshipping_price_converted’ value={toolsConvertPrice price=$freeshipping_price}}
    {math equation=’a-b’ a=$total_price b=$total_shipping assign=’total_without_shipping’}
    {math equation=’a-b’ a=$freeshipping_price_converted b=$total_without_shipping assign=’remaining_to_spend’}
    {if $remaining_to_spend > 0}
    {l s=’Get FREE shipping for this order’}
    {l s=’Your total (without shipping) is’} {convertPrice price=$total_without_shipping}
    {l s=’You will be eligible for free shipping if you spend another’} {convertPrice price=$remaining_to_spend}
    {/if}

    var freeshipping_price_converted = {$freeshipping_price_converted}
    $(‘#total_product’).bind(‘DOMNodeInserted DOMSubtreeModified DOMNodeRemoved’, function(event) {
    var curreny_str = $(‘#totalSpend .value’).html().charAt(0);
    var total_without_shipping = $(‘#total_product’).html();
    total_without_shipping = parseFloat(total_without_shipping.replace(‘$’,”)).toFixed(2);
    var remaining_to_spend = (freeshipping_price_converted – total_without_shipping).toFixed(2);
    if(remaining_to_spend > 0) {
    $(‘#totalSpend .value’).html(curreny_str+total_without_shipping);
    $(‘#remaingSpend .value’).html(curreny_str+remaining_to_spend);
    }
    });

    {/if}

  • darkf3d3

    Hi, I test your tip and it works, the problem is that if i update the quantity of products in cart the ammount doesn’t update… Any idea on how to fix it?

  • http://ecigopaline.fr Zythom

    Hello,
    i tried to follow this tuto and make changes, but i allways have a white page on the cart. I think it is because of the table PS_SHIPPING_FREE_PRICE that doesn’t exist in my DB (even with the right prefix). Do you know where i can retrieve this information ?

    Thanks

    • http://www.martinkokes.cz Martin Kokeš

      Hello, I have made an upgrade from PS 1.4 to 1.6 and this works for me in my custom template

      {assign var=’freeshipping_price’ value=Configuration::get(‘PS_SHIPPING_FREE_PRICE’)}

      {if $freeshipping_price}

      {assign var=’freeshipping_price_converted’ value={toolsConvertPrice price=$freeshipping_price}}

      {math equation=’a-b’ a=$total_price b=$total_shipping assign=’total_without_shipping’}

      {math equation=’a-b’ a=$freeshipping_price_converted b=$total_without_shipping assign=’remaining_to_spend’}

      {if $remaining_to_spend > 0 && $freeshipping_price_converted >= 0 && !$isVirtualCart}

      {l s=’Remaining amount to be added to your cart in order to obtain free shipping:’}

      {convertPrice price=$remaining_to_spend}

      {/if}

      {/if}

      {addJsDef freeshipping_price_converted=$freeshipping_price_converted|intval}

      ================ cart-summary.js in your template =============
      at the end of function updateCartSummary add this BEFORE the ending bracket }:

      // REMAINING AMOUNT TO SPEND FOR FREE SHIPPING

      if(json.total_products_wt >= freeshipping_price_converted) {

      // hide spend more to get free shipping

      $(‘#free-shipping-block’).fadeOut();

      } else {

      // show spend more to get free shipping

      $(‘#free-shipping-block’).fadeIn();

      }

You like the tuts and want to say "thank you"? Well, you can always feel free to donate: