Categories
WooCommerce Extensions

Cities Shipping Zones for WooCommerce

Cities List

How to modify cities names?
Update countries codes, and cities codes and names:

add_filter( 'woocommerce_states', 'csz_modify_woocommerce_states', 40 );
function csz_modify_woocommerce_states( $states ) {
	$states['AT']['AT90001'] = 'Vienna';
	return $states;
}

How to remove some cities from the list?
Update cities codes:

add_filter( 'woocommerce_states', 'csz_remove_woocommerce_states', 50 );
function csz_remove_woocommerce_states( $states ) {
	$unnecessary_cities = [ 'AT10101', 'AT10201', 'AT10301' ];
	foreach ( $unnecessary_cities as $city ) {
		unset( $states[ substr( $city, 0, 2 ) ][ $city ] );
	}
	return $states;
}

How to keep only specific cities in the list?
Update country code and cities codes:

add_filter( 'woocommerce_states', 'csz_set_woocommerce_states', 20 );
function csz_set_woocommerce_states( $states ) {
	$country = 'AT';
	$cities = [ 'AT10101', 'AT10201', 'AT10301' ];
	$new_states = [];
	foreach ( $cities as $city ) {
		if ( isset( $states[ $country ][ $city ] ) ) {
			$new_states[ $city ] = $states[ $country ][ $city ];
		}
	}
	$states[ $country ] = $new_states;
	return $states;
}

How to remove from the list all the cities of certain states?
Update states codes:

add_filter( 'csz_country_states', 'csz_remove_states_cities' );
function csz_remove_states_cities( $states ) {
	$unnecessary_states = [ 'EE001', 'EE004', 'EE006' ];
	foreach ( $unnecessary_states as $state_code ) {
		if ( isset( $states[ $state_code ] ) ) {
			unset( $states[ $state_code ] );
		}
	}
	return $states;
}

How to keep in the list only cities of certain states?
Update country code and states codes:

add_filter( 'csz_country_states', 'csz_keep_states_cities' );
function csz_keep_states_cities( $states ) {
	$country_code = 'EE';
	$keep_states = [ 'EE001', 'EE004', 'EE006' ];
	if ( substr( array_keys( $states )['0'], 0, 2 ) === $country_code ) {
		foreach ( $states as $state_code => $state_name ) {
			if ( ! in_array( $state_code, $keep_states ) ) {
				unset( $states[ $state_code ] );
			}
		}
	}
	return $states;
}

How to create shipping zones for quarters inside a city?
Create shipping zone with that city and restrict to the relevant postcodes, or (what is less recommended) split the city into areas (update city code and areas names, if the store is located inside this city update the store location in WooCommerce settings):

add_filter( 'woocommerce_states', 'csz_split_woocommerce_states', 30 );
function csz_split_woocommerce_states( $states ) {
	$city_code = 'AT90001';
	$sub_cities = [ __( 'Northern', 'woocommerce' ), __( 'Southern', 'woocommerce' ) ];
	$count = 101;
	foreach ( $sub_cities as $sub_city ) {
		$states[ substr( $city_code, 0, 2 ) ][ $city_code . $count ] = $states[ substr( $city_code, 0, 2 ) ][ $city_code ] . ' - ' . $sub_city;
		$count++;
	}
	unset( $states[ substr( $city_code, 0, 2 ) ][ $city_code ] );
	return $states;
}

Which uses shop owners make with the customer city?

  • Set shipping rates per cities
  • Sales stats by city (Dashbaord => WooCommerce => Reports => Sales by city)
  • Displaying certain products by city (filter by city category)
  • Selling certain products per city (plugin that limits by state)
  • Shipping certain products per city (associating the products to a class without price in the relevant shipping method)
  • Applying taxes per city (using the city code in the state field in the settings)
  • Enabling payment / shipping methods per city (conditional payment / shipping plugin)
  • Displaying the cities in external checkout page (retreiving the states via WooCommerce REST API)
Bulk Edit Tool

What is the required format?
Semicolon (;) between each city. For example: Wien; Rust; Steinbrunn

How to modify cities in list to the required format?
Replace [\r\n]+ (regex) with ; in Notepad++.

How to enter all the locations within certain distance from a city with distances list?
Enter exclamation mark (!) followed by the city code, if necessary add minium and maximum distance seperated by semicolon (;).

Integrations

Why the city appear twice in my integrated software?
You will have to remove the sending of the state field via its plugin’s code.

Why the city field is empty in my integrated software?
You will have to modify its way of retreiving data from the order- from: $_POST['billing_city'] into $order->get_billing_city() or into $_POST['billing_state'] if $order was not created yet. Or add action that copies $_POST['billing_state'] into $_POST['billing_city']. Do the same for the shipping field.

Distance Fee

How to apply distance fee?
Given a (domestic) city’s distances list, it will be possible to add distance based fee for the shipping rate or product price (for example- to sell moving services).

Why the tax is not calculated on the distance fee?
Enter in the shipping method cost greater than zero.

Where the configured product distance fee will be displayed?
The product the fee will be added to its price and will be displayed in the subtotal of the mini cart widget.

How I shall organize the distances list for some city?
Use as index the locations codes or names (as they appear in the dashboard and update $key_format), verify to set distance to the city itself, the distances should be greater than 0.

WooCommerce REST API

Use the class:

add_filter( 'woocommerce_rest_api_get_rest_namespaces', 'wc_states_api' );
function wc_states_api( $controllers ) {
	$controllers['wc/v3']['data-states'] = 'WC_REST_Data_States_Controller';
	return $controllers;
}

class WC_REST_Data_States_Controller extends WC_REST_Data_Controller {
	protected $namespace = 'wc/v3';
	protected $rest_base = 'data/states';
	function register_routes() {
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<state>[\w-]+)/zone', [
			'methods'		=> 'GET',
			'callback'		=> [ $this, 'get_zone' ],
			'args'			=> [ 'state' => [ 'description' => __( 'State / County', 'woocommerce' ), 'type' => 'string' ] ],
			'permission_callback'	=> [ $this, 'get_items_permissions_check' ],
		] );
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<state>[\w-]+)/state', [
			'methods'		=> 'GET',
			'callback'		=> [ $this, 'get_state' ],
			'args'			=> [ 'state' => [ 'description' => __( 'State / County', 'woocommerce' ), 'type' => 'string' ] ],
			'permission_callback'	=> [ $this, 'get_items_permissions_check' ],
		] );
	}
	function get_zone( $data ) {
		return [ 'id' => wc_get_shipping_zone( [ 'destination' => [ 'country' => substr( $data['state'], 0, 2 ), 'state' => $data['state'], 'postcode' => '' ] ] )->get_zone_id() ];
	}
	function get_state( $data ) {
		foreach ( get_option( 'wc_csz_countries_codes' ) as $country_code ) {
			$country_cities = '';
			$country_states = '';
			include( WP_PLUGIN_DIR . '/cities-shipping-zones-for-woocommerce/i18n/cities/' . $country_code . '.php' );
			if ( isset( $country_states ) ) {
				foreach ( $country_states as $state_code => $state_name ) {
					if ( isset( $country_cities[ $state_code ][ $data['state'] ] ) ) {
						return $country_states[ $state_code ];
					}
				}
			}
		}
		return false;
	}
}

How to retrieve the shipping zone a city belong to?

/wp-json/wc/v3/data/states/<city_code>/zone

How to retrieve the state name a city belong to?

/wp-json/wc/v3/data/states/<city_code>/state
Uninstall Plugin / Countries / Locations
  • WooCommerce Shipping Zones settings: Remove the locations
  • Plugin Settings: Remove the countries
  • WooCommerce Settings: Update the store location
  • Plugins: Deactivate and delete the plugin
  • Database: Consider to convert/erase the state field values of orders and users that were created/updated while the plugin was applied on the countries they belong to

10 replies on “Cities Shipping Zones for WooCommerce”

Hi,

I was trying to use your “Cities Shipping Zones for WooCommerce” plugin. However, the country I am trying to use this plugin is not supported. I would to request to add “United Arab Emirates” to the supported countries.

Thank you in advance.

Dear Ganji, altough you may use the plugin in India, it can not be integrated with online payment or shipping software
since the address format in India contains state but the plugin replace the state field with a city one.

Raditya, Indonesia is supported but the address format in Indonesia contains states, so if you use the plugin you will not able to integrate your website with online payment or shipping software.

That’s a bummer! Guess I’ll have to add them by zip codes, which is a lot of work to do. Thanks for the fast reply and wish you have a great day!

Dear, please help on following
1. could you please add Myanmar as a supported country
2. how to add different cities in Myanmar, where shipping zone applies as customer enters the city at check out page.

Thank you

Leave a Reply

Your email address will not be published. Required fields are marked *