WooCommerce Shipping Zones have been introduced in WooCommerce 2.6. This is a new feature and it enables you to change how much will you charge for certain shipping zones. In this tutorial we will learn how to configure them and use them in our code.
This will be a large tutorial so be prepared to learn a lot! Also, as I like to do when doing something new, grab a cup of coffee, tea or any of your favourite development drink and let’s start:)
Don’t need a guide on using them? Jump straight to the code examples.
This is a feature that has changed the Shipping screen and also how Shipping Methods function. Since the WooCommerce and the Automattic team care about their users, they have coded them to be backward compatible.
That means that if you are using any custom shipping method coded with the shipping method API, it should work without any errors. That is the good side. The bad side is a minor one, but it still is: you can’t use shipping zones with your custom shipping method.
Unless, the developer who made it, updates it with the new shipping method API.
This is fairly easy. Open the Shipping settings under WooCommerce > Settings > Shipping.
On that screen, there are three navigation options: Shipping Zones, Shipping Options and Shipping Classes. We will focus in this tutorial on the first navigation option Shipping Zones. The summary of the other two:
On the initial screen which is the Shipping Zones screen, you can edit or remove the available zones and also define new zones. If there are no zones defined, WooCommerce will use the the default Rest of the World which is used for locations which are not included in any of other zones.
The best way to learn what we can do with the zones, is to create one. We will first create our zone and then we will also edit it. Click on the Add Shipping Zone button and you will get a new row with empty fields.
You can limit your shipping zone to specific Postal Codes but for this example I will use only several countries. My data will be:
Once you enter your own data, save them by clicking on the button Save Changes. Now we can decide which shipping methods will be used for our zone.
To add shipping methods, we can use the right “+” button or we can click on the View link when we hover over our shipping zone. This will get us to the screen of that shipping zone.
I will add only the Flat Rate shipping method. If we click on that method from the Shipping Zones screen, we will get to a new screen with the settings for that shipping method. If we click on that method from the screen of a Shipping Zone we will get a modal opened in the same window with the same settings.
This shipping method is also developed with the Shipping Classes in mind. If you have added a shipping class, you will be able to define the cost for that shipping class under the Flat Rate.
Note that each setting is specifically defined for that Shipping Zone. It will not relate to other Shipping Zones with the same Shipping Method.
If you hover over this shipping method on the screen, you will get two options: Edit or Remove. Clicking on edit you can set the cost of this shipping rate and also cost of any shipping class if exists.
We now know everything about adding a new shipping zone and defining one.
You can edit the shipping zone from the screen Shipping Zones. Once you click on the Edit link, you will see both fields editable as when you were adding a new shipping zone. Now easily rename your zone, edit or remove the locations.
When developing WooCommerce websites, you could have to develop your own shipping methods or automatically add shipping zones. You could even be asked from your client to add the shipping zones yourself, so creating them programmatically can be much easier. Let’s see how we can use WooCommerce Shipping Zones in the code.
This feature is consists of two parts: Shipping Zones and Shipping Zone. The first is used to handle all the zones together and the later is to handle one particular zone.
All shipping zones can be handled by using one new class in WooCommerce: WC_Shipping_Zones. This class can be used to get a zone, delete a zone, get all zones, get shipping method and even get the appropriate zone by a package.
All zones can be returned by this class using a simple method get_zones(). Since this is a static function we can call it like this:
The returned zones will be in an array of zones with the zone_id as their key. This is the structure you could get:
This is not a whole array, and the shipping methods can be really long with their definitions. But this was just an example so that you can have an understanding of how they are returned from the method get_zones().
If we know the ID of our zone then we can easily get a single zone definition. This is done by using the method get_zone(). Since this is also a static method, we can call it in the same way we did in the example above. We also need to pass the zone_id to that method:
This function will return an object of the Shipping Zone or false. From that, you can easily operate with that zone using that object. We will learn about it a little bit later in this tutorial.
This method of getting a single zone is almost similar. In fact, the previous method get_zone() is a wrapper method of this one. This method is get_zone_by() and the required parameters are $by (string) and $id (number).
The parameter $by can be:
Here are two examples of using that method to get the same zone. The returned value will be an object of Shipping Zone or false.
WooCommerce Shipping Zones can be easily deleted by using the method delete_zone(). We only have to pass the zone ID in that method to delete that zone.
The package is an object (array) that can be retrieved from the cart. The package object is also used for calculating shipping method’s costs. By passing a package to the method get_zone_matching_package(), a Shipping Zone object is returned.
The class WC_Shipping_Zones can also return a shipping method’s object. This is done by using the method get_shipping_method() by passing an instance ID.
We have now learned a lot about using WooCommerce Shipping Zones class. By using that class we can get a WC_Shipping_Zone object. Now it is time to learn what we can do with that object.
The Shipping Zone object is an object instantiated from the class WC_Shipping_Zone. We can instantiate it by passing the $zone parameter. That parameter can be:
If the passed parameter is a 0 (zero) then the zone which is instantiated would be the default zone “Rest of the World”. If a parameter is passed and it is not a number or an object, the instantiated object would be a zone with the name “Zone”.
Once we get the object, we can do various things with it.
When we instantiate the object of a Shipping Zone, we can add or remove locations to it, rename it and similar. The important thing is also to save that changes. If the object is a new Shipping Zone with no ID, then we will also create it. The update and create methods are wrapped inside a single method save().
The object that we have passed in before did not have an ID. With the save() method, we have saved the new zone to the database. Now our zone object has also an ID.
A Shipping Zone can only be deleted if there is an ID present in the object.
We can check upon the object’s ID by using the method get_id(). If the Shipping Zone was deleted, then the method would return 0. Besides the ID, we can also get the zone name, order, locations and shipping method using these methods:
The class WC_Shipping_Zone allows us to set some values. This methods will set the new values while overriding the older ones:
The first three methods require a simple parameter such as a number for the id or order and a string for the name. The last one requires an array:
Besides settings values so that the previous ones are deleted, we can also add values. By adding values, the previous ones are still there and are not overwritten. We can add locations and shipping methods.
When adding a location, we must pass two parameters: code and type. Type can be:
When adding a shipping method, we must pass one parameter: shipping method ID.
The object from class WC_Shipping_Zone allows us to clear locations. They can be cleared by the type. In that way, we can delete all locations or only locations from a specific type.
Here is an example of using WooCommerce Shipping Zones from my eBook “WooCommerce for Developers“. In this example we will check if there is already a zone with the same name. If there is no zone with that name, we will create one and also add our shipping method to it.
In this example we are first getting all the zones and we are storing the names of those zones in an array. Then we check that array for our name. If that name does not exist there, we then create our new shipping zone.
Before we create the zone we also add our location (Croatia). After the zone has been saved in the database, we also add a shipping method. Both the WooCommerce Shipping Zones and the WooCommerce Shipping Method are described in great detail in my eBook “WooCommerce for Developers”.
Using this new feature is WooCommerce is of great help for many Shipping Methods. If the shipping method is developed with the WooCommerce Shipping Zones in mind, then even a regular user can easily change what they need when using the custom Shipping Methods.
What would also be nice:
What I would like to see is to have a way to block certain Shipping Zones from being edited or some part of them. This block could be used to stop users from editing locations for a certain shipping zone that is created by a shipping method.
If you have already worked with the WooCommerce Shipping Zones, share your experience with us in the comments below 🙂
Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.