“Today a customer called in to let us know a product was being quoted by UPS for $90 to be shipped, while using the UPS calculator yourself showed a total cost of $30.”

– Client’s support ticket

That’s an upsetting bug report to get from a client, especially when it’s not your own code that is broken. This is for the official WooCommerce UPS Shipping Method plugin. It can be difficult to fix an external plugin.

As it turned out, the large dimension product could only fit in an even larger custom box size we had entered. The product in question was already packed and ready to be shipped as-is, though. The plugin was effectively trying to double-box the product. But there is no way to tell the plugin that the product does not need to be boxed.

In this article you’ll find my solution, where you can tell WooCommerce which products are already boxed and should not be combined with other packages. Here is the option we’ll be adding to your WooCommerce products:

Limitations of the UPS Plugin (as of 12/10/2019)

For the WooCommerce UPS Shipping plugin version 3.2.18, there are no actions or filters which expose the box packing API. This means the only alternative are “hacks” applied directly to the plugin. A bad practice, but it’s the most reasonable solution until a better alternative is available. I’ve already submitted my solution to the developer and hope they will be incorporated in the future.

For the mean time you’ll have to modify the main UPS plugin directly and cross your fingers the next update incorporates my filter. We need to add one filter and one class method. Keep in mind if the plugin gets an update (that does not incorporate my feedback), then you’ll need to repeat the process.

Step 1) Apply the fix to “class-wc-boxpack.php”:

Find the modified source code of this file at the following Gist. Remember this is for version 3.2.18. I recommend you review the revision if you are using a new version, and copy the added code to the appropriate location.

This addition creates a new method “add_package” to the WC_Boxpack class. There is no elegant way to add packages otherwise, as “$this->packages” is a private variable.

You can view the full file here: https://gist.github.com/RadGH/b7b69f65bbeb7212083058d1d644b0c9

Step 2) Apply the fix to “class-wc-shipping-ups.php”:

As mentioned above, I recommend you review the revision and only copy my additions to your existing file. Particularly if your version is different than 3.2.18.

My addition exposes a new filter, “woocommerce_shipping_ups_skip_packing”. This filter runs for every product in your cart when shipping is calculated, and allows a third party hook to “skip” packing the product. It does not actually add a package, but provides a reference to $boxpack which allows you to create packages yourself.

You can view the full, modified file here: https://gist.github.com/RadGH/ad8d8e599366a27c81bc84dd1f66aaa9

Step 3) Add some modifications to your functions.php:

Finally we can add new features to the packing system using the above filter and add_package methods.

Once again, I’ve created a Gist to make this straightforward. In this case you can simply copy the three functions and corresponding filters to your existing functions.php (or similar include file): https://gist.github.com/RadGH/7c8f0ef77e242ce011932d41e9c06b8e

This last piece has three components:

  1. tt_ups_maybe_use_separate_package_for_product()
    This function is called for every product being calculated for shipping. It checks if the “_packed_separately” option has been enabled for a product. If so, it adds a package for that specific product and returns true to “skip” the default box packing system.
  2. tt_packed_separately_field()
    This function adds a checkbox to the Product Data box on the dashboard. It lets you check a box to enable “Packed Separately” on a product.
  3. tt_save_packed_separately_field()
    Lastly, this function saves the checkbox value to the product’s metadata when the WooCommerce product meta is processed.

Testing your solution

Once you have all of the features in place, check the box to enable “Packed Separately” for a product. When you view the shipping estimate on the cart, you should notice the UPS pricing is different. This depends on your UPS settings just how different it is.

In my case, the UPS rate was $117.97 when shipped in a larger box. When packed separately, the cost was only $25.69! This cost more accurately reflects the actual cost of shipping the product.

If you aren’t seeing such significant results, try going to WooCommerce Settings > Shipping > UPS (general settings, not settings within a shipping zone). You’ll see a checkbox to enable Debug Mode, which will show a bunch of additional information when your shipping methods are calculated.