You may or may not be aware of the fact that free shipping promotions won’t work with the default Magento Table Rate shipping method.
Of course you can build your free shipping option into the table rates. For example, if you are using weight vs. destination, then you can offer a zero charge for weight under a certain value.
However, this approach is very limiting. What if you want to run occasional free shipping promotions? Or you want to offer free shipping only on certain items. You need to use the Promotions tools for this, alas, the Table Rate shipping method doesn’t play ball.
The fix is surprisingly simple (once you know about it).
The shipping is calculated in app/code/core/Mage/Shipping/Model/Carrier/Tablerate.php in public function collectRates(...). So, to fix the free shipping promotions issue, we will need to override this method in our local override. We won’t go into details on how to override Magento classes and methods, there are plenty of tuts around. We’ll just go straight to the code changes.
We’ll focus on this part of the collectRates method:
if (!empty($rate) && $rate['price'] >= 0) {
$method = Mage::getModel('shipping/rate_result_method');
$method->setCarrier('tablerate');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('bestway');
$method->setMethodTitle($this->getConfigData('name'));
$shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']);
$method->setPrice($shippingPrice);
$method->setCost($rate['cost']);
$result->append($method);
}
And change it to read:
if (!empty($rate) && $rate['price'] >= 0) {
$method = Mage::getModel('shipping/rate_result_method');
$method->setCarrier('tablerate');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('bestway');
// If the free shipping promo condition is met
if($request->getFreeShipping() === true) {
$shippingPrice = '0.00'; // we set the shipping price to zero
// then we change the method title to indicate shipping is free
$method->setMethodTitle(Mage::helper('shipping')->__('Free Shipping'));
} else { // else we continue as normal
$shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']);
$method->setMethodTitle($this->getConfigData('name'));
}
$method->setPrice($shippingPrice);
$method->setCost($rate['cost']);
$result->append($method);
}
After that, you can charge some more training to your clients when you show them how to set up some fantastic free shipping promos.
Let me know in the comments if you’re interested in some articles on setting up promotions in Magento.
UPDATE: Please note that this tip is relevant for Magento versions before 1.4.2 since this has been addressed in Magento 1.4.2 and above.
Looking at the new code in Magento 1.4.2, we see that on line 123 the code was changed to:
if ($request->getFreeShipping() === true || ($request->getPackageQty() == $freeQty)) {
$shippingPrice = 0;
} else {
$shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']);
}
Which means to say in plain english, the shipping price will be 0.00 if the free shipping is active for the whole cart OR if the cart ONLY contains items which have been marked for free shipping (using the “For matching items only” option in the discount rule).
If you’re using Magento 1.4.0.1 and lower, you can try back-porting this code change to enable free shipping promotions for the whole cart.
To make the free shipping for a specific item work, when creating the shopping cart rule, you need to select “For matching items only” in the “Free Shipping” drop-down and add your “free shipping” product(s) to the section below that says:
“Apply the rule only to cart items matching the following conditions“
Originally published on magebase.com. Copyright © 2010 Magebase - All Rights Reserved.




Proud members of the
Robert,
We need to fix problem with Magento related to Authorize (first) and then Capture (some days afterwards) using Authorize.net
Can you help me locate how to do that in agento?
Thanks in advance and I look forward your comments.
Isy.
@Isy, this article has nothing to do with payment methods. It is about shipping methods. I can’t help with Autorize.net since we don’t use this payment method.
Not understanding how to call this free shipping… do I need to config a promotion?
Thanks
@Wayne,
correct. You will need to create a Free Shipping promotion to see the effect of the code changes described here.
Robert,
Thanks for the reply… I’ll set it up and see what I come up with.
Will this apply to configurable products as well?
This will work for any shipments, regardless of the product type.
Robert,
I have to let you know, I have been scanning google and Magento for this and reviled very little solutions that work…. so far yours is the cleanest solution.
I have this to the point I am getting free shipping for the item I am calling, and shipping on the items with a call for shipping. I had to set the shipping value to 0.0001 and the promotion to the same.
However I am not getting any display indicating to the client “shipping is free” for the particular item.
Am I missing something other?
Thanks so much for this… it is very nice solution.
Wayne,
you should not have to set the shipping costs to 0.0001.
When creating a free shipping promotion, you create a shopping cart price rule that has a fixed price discount of 0 and the Free Shipping drop-down set to “For Shipment with matching items”. You can set your conditions up as you please (ie. if you want to offer free shipping only if a certain item is in the cart or the cart value is over a certain threshold).
Also, how exactly did you change the code in Tablerate.php?
Robert,
The following link is the promo I have set up and the tablerate.php code… I used the view source link and pasted in into the tablerate.php file
If I set the weights to “0″, the cart gives me a shipping charge… let me know what I doing wrong ….thanks
http://we-designstudio.com/magento/promo-rule.png
// Package weight and qty free shipping $oldWeight = $request->getPackageWeight(); $oldQty = $request->getPackageQty(); $request->setPackageWeight($request->getFreeMethodWeight()); $request->setPackageQty($oldQty - $freeQty); $result = Mage::getModel('shipping/rate_result'); $rate = $this->getRate($request); $request->setPackageWeight($oldWeight); $request->setPackageQty($oldQty); if (!empty($rate) && $rate['price'] >= 0) { $method = Mage::getModel('shipping/rate_result_method'); $method->setCarrier('tablerate'); $method->setCarrierTitle($this->getConfigData('title')); $method->setMethod('bestway'); // If the free shipping promo condition is met if($request->getFreeShipping() === true) { $shippingPrice = '0.00'; // we set the shipping price to zero // then we change the method title to indicate shipping is free $method->setMethodTitle(Mage::helper('shipping')->__('Free Shipping')); } else { // else we continue as normal $shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']); $method->setMethodTitle($this->getConfigData('name')); } $method->setPrice($shippingPrice); $method->setCost($rate['cost']); $result->append($method); }OK I think I see what you are trying to do and what you mean. This method isn’t going to show that there is Free Shipping for a specific item. It will only show free shipping for the whole shipment if the conditions for the whole cart are satisfied so the “Free Shipping” title change applies only for the whole shipment.
So, you are not really doing anything wrong, it’s just a misunderstanding as to what the “Free Shipping” refers to.
To see the difference, create a simple cart rule that has Free Shipping = “For Shipment with matching items”.
Robert,
The following link is the product I have using the promo.
http://s93157791.onlinehome.us/store/digital-equipment/epson-4880-inkjet-printer.html
Wayne, I’m sorry I will have to draw the line as I can’t really provide personal support for your issues.
I suggest you consult a Magento developer since it looks like to me that you have specific requirements that are not covered by the trick in this article.
Robert,
No worries… I appreciate your help, time and patience.
Thanks
Robert,
Are you saying that will show the the free shipping call to the user?
Thanks
Hi Robert,
I’m curious as to how you set up your promotion. Did you use a coupon code to enable free shipping on checkout, and did you have to name the promotion “Free Shipping” to enable this code change? I can’t quite get it to work on my Magento install. Is it compatible with 1.4?
Thanks
-Brittany
@Brittany
Your shopping cart rule must have the “Free Shipping” option set to “For shipment with matching items” in the “Actions” tab. This will make sure to apply free shipping to the whole order.
You can name the rule anything you like. Also, this should work on Magento 1.4.x.
What shipping method have you set up? If you are using the table rate method, then you have to apply the fix above. It should work out of the box with the fixed method.
We encountered this problem today, but a Google search lead us right to the solution here. Got to love open source and big online communities
. Thanks for the fix Robert!
Hi,
This looks like exactly what I’m after – but I can’t get it working.
I’ve updated the Tablerate.php file, created a Shopping Cart Price Rule with the following settings:
Rule Name * – UK Shipping Discount
Status * – Active
Customer Groups * – All
Coupon * – Yes
Coupon Code * – noukshipping
Uses per Coupon – Blank
Uses per Customer – Blank
From Date – Today
To Date – Blank
Priority – 0
Public In RSS Feed – No
——-
Conditions – Blank
——-
Apply – Fixed Amount Discount
Discount Amount * – 0
Maximum Qty Discount is Applied To – 0
Discount Qty Step (Buy X) – 0
Apply to Shipping Amount – 0
Free Shipping – For shipment with matching items
Stop Further Rules Processing – No
When I apply the coupon in the cart I get the ‘Coupon code “noukshipping” was applied’ message, but the grand total does not update – and the checkout give no indication of the Free Shipping either.
Any ideas?
Thanks!
@matthew
Hm, you will only see the effect in your cart if you have used the shipping estimate to check the shipping cost for your order. Without this, you have to go through the checkout – shipping step until you actually see this take affect. Magento can’t work out your shipping until you tell it where you want to ship – ie. enter a billing/shipping address. But you say that the checkout doesn’t give any indication.
What magento version are you using? This trick is for 1.4 (but should be OK in 1.3)
Have you disabled/refreshed your cache after the code change?
Have you made sure you are using the Tablerate method?
Try to put a debugging statements somewhere in the changed shipping method code to see if your code is executing (a Mage::log() call should do and don’t forget to enable logging to see it in var/log/system.log).
Not sure what else to say.
Hi Robert,
Thanks for the quick reply.
It was working! I’ve removed the Shipping Estimate and never actually went through the whole checkout process. But now that I do, yes, it’s working as it should.
Thanks again for posting this tip and having such a great site. This site is so much more informative than the official Magento site and forum. Sifting through their articles is pure pain!
Thanks.
Robert,
great fix, thanks. I suppose we can’t complain about Magento not having fixed things like this earlier themselves. After all this is a free product. But it would make sense for them to organise the community better. A fix like this should be easily available on officila Magento support site ..
@Dickdv
It’s debatable if this is a bug needing a fix or if it is a customization and there might be a good reason why Magento decided not to implement the free shipping discount on the table rate method… In any case, it seems that this mod is quite useful to a few people.
Hey Robert,
Simpel and good fix.
Thanks
hey this is cool but i want to apply on item rate shipping calcuation how i perform
Hi,
I am having trouble implementing the “Shopping Cart Rule” on USPS and FedEx shipping method. I have set all things up properly in “Shopping Cart Rule” i.e.
Rule Name: Free Shipping 50
Description: This is free shipping
Status: Active
Customers Group: All
Coupon: FREE50
User per Coupon: 1000000000
User per Customer: 100000000
From Date: today
End Date: 12/21/2010
Priority:
RSS: No
Conditions:
Subtotal >= 50
Shipping country: US
True if Any:
{
Shipping Method: is fedex ground
Shipping Method: is fedex Home delivery
Shipping Method: is usps Priority Mail
Shipping Method: is usps First-Class Mail flat
}
True if All:
{
Shipping Method: is not flat rate
Shipping Method: is not Fixed
}
Total weight >= 0
Action:
Apply: Percent of product price discount
Disount Amount: 0
Max Qty : 0
Discount Qty Step: 0
Apply to Shipping Amount: Yes
Free Shipping: For Shippment with matching items
Stop further: No
When I go to checkout and apply the Coupon “Free50″. It only apply the discount on Flat rate or free Shipping method types and It doesn’t have any impact on USPS and Fedex rates.
I am using Magento 1.4.1.1.
Can you please guide me what need to be done to apply this on these two Shipping methods.
Best regards,
This tutorial is specific to the Table rate shipping method. For the FedEx method, I suspect that you would have to work through the code and work out how to add the free shipping capability. Just setting up the promotion may not be enough.
Ok, thanks will check it out.
How did you get the override of collectRates to work. I’m trying to override that function and doesn’t seem to want to allow it. I have checked and rechecked my code.
@Chris
You can either create an extension or directly override Tablerate.php by creating it in a local override:
app/code/local/Mage/Shipping/Model/Carrier/Tablerate.php@Robert
Yes, thanks.. after monkeying around a bit, that’s what I ended up doing.
Slightly offtopic but I hope you would help me.
it seems that there’s a bug in the Tablerate. Since 1.4.2 the tablerate returns always a shippingprice of 0 euro for all my products and accordings weights.
Do you know where the weight prices is collected and how to set a correct weight?
Any help appreciated !!!
@Peter
How did you set up your tablerates csv file? All the shipping cost – weight information is set up in the csv you upload into the tablerate method configuration. You can check directly in the Magento database if your tabelrates are present by looking into the shipping_tablerate table.
Everything works just fine until the upgrade to 1.4.2 (with te same CSV-file). I debug the problem a little. In line 90 the following code:
$result = Mage::getModel(‘shipping/rate_result’);
$rate = $this->getRate($request);
where the price is getting collected to rate (rate['price']) but for every product (and every weight) rate['price'] always zero.
My knowledge is not enough to determine furthermore.
Where is the code for Mage::getModel? or where is getRate collecting the request?
Hopefully you can send me in the correct direction !
I’m sorry but I don’t know why you should have this issue with your upgraded site. Are you having this problem with the un-modified table rate method? If you have the problem with the modified version, then try to disable the modification and test the method using just the original, built in tablerate.
Also try to compare the original Tablerate.php in Magento 1.4.2 with the same file from the earlier version to see if there are significant differences.
To find the code you are asking about:
1. getModel(‘shipping/rate_result’) will instantiate the class in: Mage/Shipping/Model/Rate/Result.php
2. $this-getRate() refers to the getRate method in Mage/Shipping/Model/Carrier/Tablerate.php
Hope this helps.
Hi Robert,
thank you very much, you helped me a lot with this.
By the way, the issue seems to be fixed in Magento 1.5.0.1.
Glad this was useful to you.
I haven’t had a chance to check what has been improved in this area on Magento 1.5 – are you saying that the table rate shipping method now supports free shipping promotions out of the box, without having to apply the change from this article?
If so, then that’s great. One less thing to worry about
.
Hi Robert,
I tried using your solution but it seems not to work on my end.
I get a “Sorry, no quotes are available for this order at this time.” on the one page checkout.
The following are my setup:
1. i enabled table rate shipping method ONLY.
2. I only want x products to be free shipping y and z to have a minimum shipping cost of $20
3. I enabled a promo with the following settings
Rule Information:
Rule Name: Free shipping on x products
Status: Active
Customers groups: All
Coupon: No Coupon
Uses per customer: 9999
From date: 01/01/2011
To date: 01/01/2012
Conditions:
As is
Actions:
Apply: Fixed amount discount
discount amount: 0
max qty discount is applied: 999
discount qty step: 0
Apply to shipping amount: No
Free Shipping: For matching items only
Stop further rules processing: Yes
Rule:
if any of these conditions are true:
category is one of 4 Note: 4 is category of x product
attribute set is x
I troubleshoot the issue by placing a magento log before and after the condition to check if the code is going inside the modification you made.
Mage::log("Im outside");
Mage::log('rate: '.$rate);
if (!empty($rate) && $rate['price'] >= 0)
Mage::log("im inside");
The output is
debug(7): Im outside
debug(7): rate:
it shows the “rate” has a null value causing it not to go inside the condition where the modifications (roberts snippet) were installed.
any ideas where i went south?
Thanks,
Suzy
@suzy
I think the key is in your free shipping setting that applies “For matching items only”. Can you try changing the “Free shipping” setting to: “For shipment with matching items” and see if your free shipping works.
The solution here really applies only to enable blanket free shipping promotions when the table rate method is in use, it may not apply to a more fine-tuned situation as you have outlined (ie. partial free shipping for matching items only with a minimum shipping charge).
Thanks for the reply Rob.
its working fine now. Good job on this one. simple and it works.
Hi Robert,
Do you know if there is a way of altering the code for the Configuration/Shipping Methods/Free Shipping module so that Free shipping only appears in shopping cart checkout when an applicable customer from a customer group is logged in?
i.e. If I put a customer into, say, the wholesale customer group, then free shipping always appears in their cart, but not for a NOT LOGGED IN or any other customer.
I’ve just updated site to Magneto ver 1.5.1
Many thanks in advance
Hi Paul
You can add code to check if the customer is logged in and if so, whether they belong to a certain group or groups.
You can use the customer helper class to get information about your current customer:
$currentCustomer = Mage::helper('customer')->getCustomer(); $customerGroups = Mage::helper('customer')->getGroups(); // returns Mage_Customer_Model_Entity_Group_Collection $isLoggedIn = $currentCustomer->isLoggedIn();You will have to check where to exactly, alter the code in the Tablerate.php. By the way, it seems that indeed in M 1.5.x the mod from this article is not necessary any more to enable free shipping promotions ‘out of the box’ so you will just need to plug the customer group check around these lines:
if ($request->getFreeShipping() === true || ($request->getPackageQty() == $freeQty)) { $shippingPrice = 0; } else { $shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']); }H Robert,
Is this applicable with Mulitple Table Rates?
Thanks,
You should be able to use similar logic as outlined here in any shipping extension. You just need to find the appropriate place in the code to add the free shipping logic.
Hi, Great fix
but i have a small problem. I get the free shipping method only with simple products. when i use a config product the free shipping isn’t working. This is with magento version 1.4.0.1. Any tips on this or will it only work on simple products?
Hi,Robert!
I have recently upgraded M from 1.3.2.4 to 1.4.2.0. I am applying table rates there with csv like this
“Country”,”Region/State”,”Zip/Postal Code”,”Order Subtotal (and above)”,”Shipping Price”
“AE”,”*”,”*”,0,5
“AE”,”*”,”*”,50,15
“AE”,”*”,”*”,200,20
“IN”,”*”,”*”,0,5
“IN”,”*”,”*”,25,100
I am testing table rates.But i dont know why only i am getting only $5 in shipping method.
I have checked this csv in another fresh 1.4.2.0 version, it works perfect. But again when i have changed this with weight vs destination and made changes according to it,then applying price vs destination with above rates. And using one page checkout, again i am getting $5 in shipping.I have searched out for this issue but not getting any answer.TIA
@Kamal
Check your shipping_tablerate table in the database after you import the edited tablerate. If that is empty, then your file has failed to import.
I find you need to save the csv in windows format with CR-LF line endings for the import to work correctly. This is important if you are editing the csv on Mac or Linux…
@Robert thanks for your quick response. Already i have checked my database i can see values entered by me are correct. Means there is no problem for importing csv file. And i am using notepad to edit csv. I am not getting by CR-LF line endings.
Maybe it’s a stupid question, but you have changed the Condition setting in the Tablerate method to “Price vs. Destination” as well?
Other than that, I don’t see what could be wrong in your case.
Yeah first i have made table rates with price vs destination then i changed to weight vs destination and after that i m using again price vs destination. Doing this stuff my shipping value is based on 0 rates only.thx
Sorry Kamal, I don’t think I can help you further. You have a situation that needs troubleshooting, time and admin access to resolve.
Thx for your response.
Kamal .. this may be late but easy solution to your problem is;
Add
“AE”,”*”,”*”,0,0
“IN”,”*”,”*”,0,0
EDIT
“AE”,”*”,”*”,0,5 to “AE”,”*”,”*”,1,5
“IN”,”*”,”*”,0,5 to “IN”,”*”,”*”,1,5
to the csv file
But its not working for the configurable products……..
how can i resolve this for configurable products ?
Thanks
@Aseem The shipping method has nothing to do with the product type. This works based on the Shopping Cart Rule when you set it to apply free shipping.
Hello,
Nice article and very helpful. However, after following these instructions, I found that the only way that the Free shipping can work with this customization is if the rule is set to “For shipment with matching items only”.
This is kind of a problem, because I was trying to set up a rule to apply free shipping for any product coming from an specific category, and the system keeps giving Free Shipping if the order contains a product from that category AND products from any other category.
I even tried adding a condition like this one:
If ALL of these conditions are TRUE :
If an item is FOUND in the cart with ALL of these conditions true:
Category is 45
Category is not 1,2,3,4,5,6,7,8,9,10
Any suggestions?
@Helder please see the update section in this article for some additional notes about the Magento version and also how to do the “Free shipping per item”.
hey Robert,
my problem is that,i want to give free shipping to only US client,now plz give me solution, on here or send me mail as soon as possible……
thanx
in advance
My problem is in shipping methods….I want tried to enable the shipping table rates and the Fed ex rates the went to price cart rules enabled a new called shipping method…because I do not want the user to have a choice between the shipping methods given the type of products we carry. We live produce so some are very perishable and need to be next day and other items could be ground depending on our rules… the only choice we enabled for the user is a calendar to set a date for delivery
@Vishal, @james just a friendly reminder that the topic of this tutorial is how to modify the default code to make free shipping promotions work with older versions of Magento so the comments section is for clarifying aspects of this topic. It is, however, not a support forum for your Magento questions. For that, please post on the official magento forums or on stackoverflow.com
[...] http://magebase.com/magento-tutorials/enable-free-shipping-promotions-with-magento-table-rate-method… [...]
In Magento While the free shipping is enable in admin. But the weight is exceed more than 10 kg i need to add each kilo 4 rupees. Create our own module and it is applicable only for United States calfornia state.
Dear Robert,
I have a question and hope you are someone else can help.
I use tablerate shipping method,but the Condition i set is price v. destination,not weight.
when over $100 is free shipping
But I found :
the shopping cart Subtotal is $120.00
I use coupon code cut off $30
and the Grand Total is $90.00
when i estimate the shipping, It calculate shipping cost base on subtotal ,not grand total,
it shoudn’t be free shipping because it only charge $90,not over $1200
I need change it to calculate shipping cost base on grand total or the shipping cost after calculating subtotal – discount.
Hope that someone can help.
Thanks
Hi Robert,
I’ve the same problem as the post above me. I’m using 1.5.1.
This is a weird problem, I hope you have some insight in this.
Thanks
The shipping method code in this article does not deal with the calculation or determination of the fact that free shipping is available for the order. It only enabled this method to use that fact.
If you look at the code, you will see the call to:
if($request->getFreeShipping() === true) { ... }So the processing happens elsewhere and therefore your issue is not subject of our article or anything in this code. It may be a matter of tweaking your rule conditions and your discount/shipping calculation conditions.
Dear Robert,
I use tablerate shipping method,but the Condition i set is price v. destination,not weight.
when over $100 is free shipping
But I found :
the shopping cart Subtotal is $120.00
I use coupon code cut off $30
and the Grand Total is $90.00
when i estimate the shipping, It calculate shipping cost base on subtotal ,not grand total,
I need change it to calculate shipping cost base on grand total or the shipping cost after calculating subtotal – discount.
and please tell me where is this function $request->”getFreeShipping()”
if i found getFreeShipping() i can change the condition to check Grand total , instead of subtotal
please reply me ASAP
Thanks