Calculating Flat Rate Based on Customer’s Shipping Address

(I used Shipping 7.x-2.x and Flat Rate 7.x-1.0 for this one. For now I’m going to assume that you have your Flat rate shipping method and flat rate service set up).

What we would like to do here is to tell Drupal Commerce to calculate a shipping service’s fee based on our customer’s shipping address. For example: If a customer would like her product shipped to Cooltown, the courier service will charge $15, if she’d like the product shipped to Supercooltown, the courier service will charge $5.

We will use Rules for this.

Step by step:

  1. Go to Store -> Configuration -> Shipping -> Calculation rules and add a new calculation rule.
  2. Deciding if the commerce line item’s type is Shipping
    1. Add a new condition and select Data comparison.
    2. Data selector should be ‘commerce-line-item:type’
    3. The comparison operator will be ‘equals’
    4. Data value will be Shipping
  3. Deciding if the shipping service is the one you want to change the rate for
    1. Add a new condition and select Data comparison.
    2. Data selector should be ‘commerce-line-item:commerce-shipping-service’
    3. The comparison operator will be ‘equals’
    4. For data value you have to select the shipping service you want to change the rate for
  4. Add a condition "Entity has field". The data selector should be commerce-line-item:order and the value should be the field that has your the shipping information you want. I think in most of the cases this will be commerce_customer_shipping field.
  5. Add on OR to the condition list. Rules, by default, assumes that there is an AND connection between your added conditions and between the upcoming conditions there needs to be OR.
  6. Now we need to decide what component of the shipping address will we use to decide the shipping rate. For my situation, using the postal code was the best decision, so I’ll continue with that in this tutorial, but you can use any other available address component.
    1. Add a new condition and select Order address component comparison
    2. Data selector should be ‘commerce-line-item:order’
    3. In the Address section choose Shipping information’s address
    4. In the Address component section select the component you want use to decide the shipping rate.
    5. Operator should be ‘equals’
    6. In the Value section, put the specific address component you want to apply this rule for. Example: If I want to use this rule for orders that will be shipped to Kaposvár, Hungary then I should give the value 7400 which is its postal code.
    7. Click Save
    8. Put this condition into the OR group and if you create new order address compontent conditions, put them into it as well.
  7. We’ve finished with the conditions, now let’s go to the Actions section and create a new action which will set the shipping rate to a specific amount if the above conditions are met.
    1. Add action and select Set the unit price to a specific amount
    2. Data selector should be commerce_line_item
    3. Value should be the price wou want to charge when shipping to this location you described in the conditions
    4. Price compontent type should be your shipping service’s name.
    5. Set the price rounding mode as you wish and hit Save

That’s it! If everything goes well, the rule will change the our shipping service’s rate when it’s needed.

I attached a screenshot of my rule, in case it would be helpful to you to see what we just did.

If you have any questions or corrections to this tutorial feel free to let me know in the comments section below.


simon591 on June 14, 2012


I used Shipping 7.x-2.0-beta1 and Flat Rate 7.x-1.0-beta1 to create shipping rates by country using your documentation but for step 3 ("Deciding if the shipping service is the one you want to change the rate for") I don't have the "commerce-line-item:commerce-shipping-service" data selector.

Do you have a solution for this problem ?

joecanti on August 31, 2013


Can you tell me if this method works by distance?

So that the postage rate depends on the distance the customer is from the seller?

EG 0 - 25 miles = free postage

25-100 miles = £10

I've been trying to find a solution to this for a long time - any help would be really appreciated.

Many thanks, Joe

Bird-Kid on April 23, 2014

as other people already commended above, i am experiencing these errors:

a) during data comparison with data selector ‘commerce-line-item:commerce-shipping-service’, i get an empty selection box for value selection. – as if it was not finding any services (while in fact there are four.)

b) albeit it's not stated in this guide, I want to avoid having two shipping fields in the formatted compontents table. if I select "Base Price", it shows the new total price on the shipping pages, but gets set back to the original base price on the review page. I can manually select a specific shipping service, then it works fine for this one, but really i want to use it for multiple shipping services and set it so it adds to the unit price of every shipping service.

I am getting seriously frustrated here..

Bird-Kid on June 17, 2014

upon updating to the latest commerce kickstart bundle (atm version 7.x-2.15) the issue addressed in section "a)" in my previous comment has been fixed: i am no longer presented with an empty list, but with a proper selection list.

however, as of now, I'm still not aware of a pretty solution to dynamically add the price to the current shipping service. I have had to use a rather ugly solution using a PHP evaluation in the "Add an amount to the unit price" action:
- for the "price component type" data selector I picked "commerce-line-item:commerce-shipping-service"
- and in addition to that i had to add the following PHP evaluation:

return 'flat_rate_'.$value;
whereas "$value" will evaluate to the machine name of the shipping service.
this mimics the way the array keys for the shipping components are created. – it's everything but pretty solution, but at least it's working for now. still, a way to dynamically add to whatever is the current shipping service would be great.

echo on July 6, 2014

This *did* work for me, and gave me a way to start a complex calculation rule that I was stuck at. Thank you so much for posting this!

Channel Islander on January 29, 2015

This was so clearly explained, so thoroughly documented, and WORKS EXACTLY AS IT SAYS.

Three qualities that are very much lacking in 95% of all Drupal documentation, whether official docs or answers on forums like these.

Perfect blend of clear instructions and explanation of why the instructions are so.

This post should be used as an example of how to ACTUALLY help people.

Thank you so much.

mvdve on April 21, 2015

I still have an empty commerce_shipping_services value list. Does somebody knows what or which module is causing the trouble?