WooCommerce – notifications for multiple pickup locations via shipping zones

Multiple pickup locations via shipping locations

In this tutorial we’ll go through a fairly complex way of customizing WooCommerce order notifications for multiple pickup locations. This is inspired from a well described problem found on the WooCommerce support forum on wordpress.org,

While we normally advocate #nocode solutions we are going to use abut 12 lines of custom code to accomplish what we need. The more experienced reader will know how to add these lines of codes to an existing theme or plugin. For the less experienced user we suggest adding the code via the free plugin Code Snippets.

The problem

We’re copying this directly from the WordPress forum question:

1) I want to create a store with about 100+ shipping points.

2) One shipping point for each shipping zone. Each shipping point will have a manager.

3) When an order is placed, the order should be assigned to a shipping point (according to the zip code).

4) Admin gets notifications when a order is placed.

5) shipping point manager gets notification when an order is placed for his point.

Solution overview

We’re going to solve this problem with the following approach:

  1. Set up one WooCommerce shipping zone for each pickup location. WooCommerce has the built in functionality to automatically map a customers zip code to a shipping zone. With this method we solve the entire problem of mapping zip codes to a location “for free”.
  2. We’re going to use Code Snippets to a few lines of PHP code to copy shipping zone data into regular order meta data fields. This makes them accessible in WunderAutomation in the next step.
  3. We’re using WunderAutomation to send out notifications to the pickup location managers when a new order arrives.

WooCommerce shipping zones

We set up one WooCommerce shipping zone per pickup location. Each of these shipping zones will be tied to one or more zip codes using the built in functionality in WooCommerce. Read more about setting up shipping zones here. A typical shipping zone will be configured like this:

As you can see, we’re stuffing 3 pieces of information into the zone name separated with a comma (,). This is called overloading. We need to save:

  • The name of the shipping zone / pickup location
  • The name of the manager of the pickup location
  • The contact details (email) of the location manager

The reason for the overloading is that there’s no apparent way in WooCommerce to add additional data about a shipping zone. Overloading data into a single field like this is normally considered to be a bit “hacky”. Our only other real option would be to add a custom post type where we could create one post for each pickup location and add meta data (custom fields) to that post instead. But we think that would be a lot harder to maintain in the long run since you always need to make sure the list of shipping zones match the list of custom posts.

There’s a balance to be found here. As long as the need for additional data is only a couple of extra fields, overloading into the zone name might be OK. But if we end up maintaining lots of fields, it’s quickly going to become difficult to overview and using a custom post type would be a better solution. For the this tutorial we’re going to use overloading since the original forum question only expressed a need for two additional fields.

Custom PHP code

The second part of this solution is to to add a piece of custom PHP code. We added this to our test site using the Code Snippet plugin. It makes it really easy to add custom PHP to a site without having to setup a child theme or add a custom plugin. We named our snippet “Add shipping Zone meta to order”:

The code what we paste in to the code snipped edit window is fairly straight forward:

<?php
add_action('woocommerce_order_status_processing', 'mysite_shippingzonemeta', 9, 1);
function mysite_shippingzonemeta($order_id)
{
	$order = new WC_Order($order_id);
	$allShippingItems = $order->get_items('shipping');
	$shipping = reset($allShippingItems);
	$instance_id = (int)$shipping->get_instance_id();
	$shippingZone = WC_Shipping_Zones::get_zone_by('instance_id', $instance_id);
	$parts = explode(',', $shippingZone->get_zone_name());

	add_post_meta($order_id, '_shipping_zone_name', $parts[0], true);
	add_post_meta($order_id, '_shipping_zone_manager', $parts[1], true);
	add_post_meta($order_id, '_shipping_zone_manager_email', $parts[2], true);
}
  • We’re declaring an action to be executed when an order is moved into the ‘processing’ status. Depending on your exact WooCommerce setup it could make more sense to use order status ‘completed’. It depends mainly on the payment processor in use and how you intend to work with the orders internally.
  • Note that we declare this action with priority: 9. This is because we want it to run before the WunderAutomation action that is always declared as priority 10.
  • In the function that gets called, we get the order item for shipping. In theory there could be multiple shipping items but we explicitly pick the first one on the order.
  • From the shipping order item we extract the instance which in turn gives us the shipping zone.
  • Then we take the shipping zone name and split it into three parts
  • Lastly, we take all the part and add as meta data on the order.

(Note that this is a simple code sample with just the “gist” of the functionality, suitable for a tutorial. In a real production environment you would need to add error handling)

Sending notifications with WunderAutomation

Last part of this setup is to send a notification to the store manager. We do this by setting up a workflow in WunderAutomation.

Trigger

We’re using the same trigger as we did in the custom PHP above. The WunderAutomtion trigger “Order processing” is actually using the same WordPress action as we did before. This action will be executed with priority 10 and as noted above, the custom code runs with priority 9, this makes us certain that when the below trigger runs, the order meta data fields are already added.

Filters

We’re not creating any filters for this tutorial. Based on the conditions given in the original forum question we’re assuming that this WooCommerce store is only dealing with the orders that needs to be picked up at one of the pickup locations.

Actions

We’re defining one single “Send a text email” action using a few parameter placeholders to extract the needed information:

FieldValueDescription
To{{ customfield | field: ‘_shipping_zone_manager_email’ }}This placeholder picks up the specified custom from the order meta data. This matches the custom field identifier we assigned in the custom PHP
Ccadmin@example.comAs a safety net, a copy of the email is sent to the store admin
SubjectNew order {{ order.id }}Sets an email subject with the order id

We use a couple of different parameter placeholders in the email content. The name of the shipping zone manager, the name of the shipping zone. We also include a link to the order details in WooCommerce for the manager get easy access to the order content.

Hi {{ customfield | field: '_shipping_zone_manager' }}

{{ customfield | field: '_shipping_zone_name' }} has a new order.

Order {{ order.id }} 
Customer: {{ billing.full_name }}
Phone: {{ billing.phone }}

Click here to see order details:
https://example.com/wp-admin/post.php?action=edit&post={{ order.id }}

Summary

Let’s go back to the list of requirements for this solution and see how we fared.

I want to create a store with about 100+ shipping points.

This is solved using the built in shipping zones.

One shipping point for each shipping zone. Each shipping point will have a manager

In our solution, each shipping zone also represent a pickup location. We keep track of the manager name and contact details by overloading 2 extra pieces of information in the shipping zone name

When an order is placed, the order should be assigned to a shipping point (according to the zip code).

This is taken care of by the built in shipping zone functionality in WooCommerce. It also gives the benefit that WooCommerce blocks orders with a zip code that isn’t mapped to a zone.

Admin gets notifications when a order is placed.

This is actually covered in two ways. First, the admin will get the normal WooCommerce order notification email, this is built in to WooCommerce. Second, we add the admin email to the notifications that are sent out to the location managers.

Shipping point manager gets notification when an order is placed for his point.

This is solved using the WunderAutomation workflow we created in the last step of this tutorial.

If you have any questions or feedback on this approach, please let us know in the comments below.

Leave a Reply

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