WooCommerce Per Product Shipping Price Without Needing Extension or Plugin

Please note the commenter that pointed out a flaw in this if you have products with different shipping methods: 

The problem with this, is if you also have weight based shipping selected, and only want specific pricing for a handful of products, and someone selects one of those products AND a product which is included in weight based shipping, the customer is given two options for shipping, the flat rate (cheaper) and the weight based (more expensive). -Adam Winchester

I’m a big fan of WooCommerce, seriously.  I hate how much they nickel and dime for small features like this though.  It’s easier for me to move past it because I’m able to do a lot of tweaking in the code with hooks to get what I need done thereby saving a few dollars.  But sometimes, like this example, you can do it with no coding at all.

The shipping system in general can be pretty confusing so I’m going to walk you through how you can have custom, flat rate shipping prices for different products.

Shipping Zones & Methods

Under WooCommerce Settings click the Shipping tab.  Here you need to add a new zone.  For my example I call it US Flat Rate with a Flat Rate shipping method.

Now the confusing interface part.  In order to set details for flat rate you need to click on the words “Flat Rate” in your newly saved Shipping Zone row.  Let’s not do that yet though, click over to “Shipping Classes” option on this page.

Shipping Classes

This is where we will create our per item shipping prices.  Let’s say we have three products: T-Shirt, Mug and Hat.  We are going to create three shipping classes.

t-shirt-row

Now repeat for the other two items.

Back to Shipping Zones

Bounce back over to shipping zones, click on the “Flat Rate” link on your new shipping class row and let’s do some pricing.

Set the main cost to $0.00 then for each shipping class add the price for that item.  It’s that simple.  Go to your T-Shirt product and under shipping select the T-Shirt class.  Now it will  have that flat price added to the product for shipping on checkout.

WooCommerce Subscriptions Limit Total Quantity of Subscriptions or Payment Plans in Cart

We use WooCommerce Subscriptions to setup payment plans for our products.  Deposits was our first choice but it only sent “Invoices” for future payments and did not auto charge the credit card used at initial purchase.  Not ok as our products are very expensive and people tended to ignore those invoices.

We also need to limit these purchase to one per customer.  Easier said than done.  I found a WooCommerce extension that would do the trick but we already pay so much a year for extensions we need I try to avoid that for simple functionality.

Limit Subscription

This won’t work for my needs.  The option on a subscription product only limits users from having multiple subscriptions to that particular product.  We only want one subscript for ANY product.

Solution Limits

My solution works for one shopping cart session.  I’m working on preventing others which shouldn’t be too hard by just checking the database at checkout time for active subscriptions to that user.

The Hook & Function

I went with woocommerce_add_to_cart_validation after going through quite a few other hooks and filters.  The hardest thing about finding a solution is finding what all hooks and filters are available.  Takes some serious google-fu to find the right one quickly.

This filter allows you to run a function before an item is validated and sent to the cart.  We tell our add_filter that we need two of the parameters so we can get the product id as well as the validity of the admission.  This is done with the 4th parameter we set to “2.”

Detect Variations Too

If you are using variable Subscriptions you will need to plan ahead that some items in the cart may be variations.  These have a separate class.  We must first detect if the product being added is an instance of WC_Product_Subscription which is a “Simple Subscription” in WooCommerce.  Or is an instance of WC_Product_Variable_Subscription which is like it says a version of a subscription product with variations.

The odd part that caught me off guard is when we are checking items already in the cart.  We check for WC_Product_Subscription like normal but once in the cart the product is of the WC_Product_Subscription_Variation class meaning it’s just a variation of a product and not the full product variable class.

https://gist.github.com/ChrisFlannagan/3aaf4f58a627fa307180604886f2335c