Add Variation To Cart in WooCommerce: Don’t Forget The Attributes!

The point of this post is to help others that are having a problem dynamically adding a variation of a product (or subscription product in my case) to cart.  I get to that at the bottom of this post if you want to skip the story.

The Problem

I have a pretty high up there client in the box subscription world.  I’ve been brought in to do some WooCommerce functionality with WooSubscriptions and everything else involved.

The checkout process is pretty customized.  We have a page that displays all the attributes available for the subscription variable product.  There’s a bunch of fancy selection boxes and lists and gift inputs and so on.  It’s front end heavy but communicates with a custom endpoint through the REST API that I wrote to add the item to cart.  Problem is, the sub form doesn’t give me a variation id, only the variable subscription product id and all the selected attribute values.

Finding the Variation

The first step is to find which variation they’ve selected.  Someone long before me went through the rigorous process of creating some 50-60 variations of this variable subscription product to match all the different options a user could select.

So I use a WP_Query search the for any post id that has all the meta_key/meta_value matches and select it.  It was a bit of a pain to figure out the best process here but this works.

Adding the Variation to Cart

Took me a few to find the right parameters for adding a variation to cart.  Now that I had the post id of that variation it looked pretty simple from what I found online:

$added = WC()->cart->add_to_cart( $query->post->post_parent, 1, $data['variation_id'] );

This did the trick.  Since I used a WP_Query to get the post I could select the parent (which is the main subscription variable product) needed for first parameter.  Then the quantity, then the variation id.  Which was $query->post->ID but I assigned it to some data my API was returning.

The user checked out and the variation was in the order.  A day after pushing this code the site owner asked where the order details went.  Turns out it original showed the selected attributes in the admin order panel.  I spent a couple hours figuring this out, which I feel dumb now, but going in blind what can you expect.

You have a fourth parameter you can for $variation_data.  This gives it the attribute love it wants and adds it to the order.  Why woo doesn’t just do this automatically if a variation is added? Beats me.  But here’s how you do it using a nice woo provided function for variations.

$added = WC()->cart->add_to_cart( $query->post->post_parent, 1, $data['variation_id'], wc_get_product_variation_attributes( $data['variation_id'] ) );

New Job, New Kid

Woke up this morning and saw a tweet @ me while heading out to work.

I accepted a position at FlowPress a couple weeks ago.  I start on November 7th and I’m crazy excited.  My dream the past couple of years has been to work for a WordPress agency remote.  My reasons:

  1. I love coding WordPress.  But in every job I’ve had I’ve been in charge or tasked in some way with digital marketing, banners and graphics, fixing co-worker computers and in the smaller companies helping move desks and furniture around.  I’m sick of this, I want to do what I’m good at and what I’m dedicated to.
  2. Why do all these jobs require me to come to an office? And why do I have to dress in a certain way? I sit in meetings that have nothing to do with me then I sit in my office and almost no one talks to me.  The times people do they could easily just call, email, text or smoke signal.  There is NO reason for me to drive some where every day.  Over the past three years I’ve been driving anywhere from 30 to 45 minutes each way to go sit in an office for no reason.

I work best when there’s no frivolous B.S. I have to deal with like a commute or dumb meetings about new rules surrounding the use of the office kitchen or what items should be in gift bags at a fund raising event… yes, these are actual meetings I’ve had at previous jobs as the WEBMASTER.

FlowPress

I’ll be a developer/engineer at FlowPress working strictly with WordPress systems.  This is my passion.  I cannot wait to start and look forward to being part of that team and growing with the company.

I’ve been chatting it up on Slack and made it to a couple of stand up meetings already.  I feel like I’m meshing well and will be a good fit.  We may actually be flying up to Toronto to hang with the team in person mid December!

August Knight

My start date was kind of floating.  My wife was due November 14th to bring our son into the world.  August Knight Flannagan decided to come three and a half weeks early and was born on October 21st at 8:51am.

While it was scary having a premature baby, he is completely healthy and so is momma.  I’m overjoyed to have him in our home and it’s cool he and I have birthdays only three days apart.

My wife had to go back into the hospital for 24 hours the day after we got home due to high blood pressure.  So I got to take care of him alone, overnight.  I was a nervous wreck but stayed strong and capable and we had an uneventful day/night together.

Perfect Timing

Honestly, his timing was perfect.  Now I’m able to start sooner with FlowPress.  We got our regiment down at home and I’ll be able to focus 100% when I start on Monday.

I was worried.  No one likes to start a new job with a bunch of unknowns being worked through at home.  If he came right as I was beginning my work with FlowPress I’d have been pulled away every day or two for a doctor appointment or to spend 24 hours alone with him while my wife was in the hospital or while figuring out sleeping patterns and so on.  The burden of dealing with that while starting this new venture is now gone!

So What’s Up

I’ll be dedicating myself to the new gig but keeping myself out there in the WordPress world as a contributor as well.  You will still find me blogging here and at The WP Crowd and I’m gonna try to up my Twitter game a bit.  I mean, I’ve been on there a year now, I should really start using it regularly.

WooCommerce Buy One Get One Half Off (50% Off) Hook/Plugin – IN PROGRESS

We have a deal coming up for all of November at my work.  Buy one, get one half off.  There’s no way to do this in vanilla WooCommerce.  I looked at Dynamic Pricing and it didn’t seem to offer this ability and if it did it was crazy complicated.  I looked at some other plugins out there and found one that may work but it was pro version only and I didn’t want to pay to find out.

I figured this is pretty straight forward need so why not write up a function real fast.  Here’s my train of thought followed by a code example.  This is only a proof of concept and I still need to add – price limits (items must be over a certain price for this to work), category limits and the ability to apply this more than once to an order.  But as of now it will take the second highest priced item and give it a 50% discount.  If you have two of the same item as the highest price it will discount the amount to make it the same as taking 50% off just one of the items.

First we need to hook into woocommerce_before_calculate_totals.  This way we can change the price on the cart and on the checkout.

add_action( 'woocommerce_before_calculate_totals', 'add_custom_price' );
function add_custom_price( $cart_object ) {

Then I set variables for highest price, quantity of that item, a counter so we know if the shopper has more than 1 item in our discount range (for future use with pricing bottoms) and next highest price item.

$highest_price_id = 0;
$highest_price_quantity = 0;
$cnt = 0;
$highest_price = 0;
$next_highest_price_id = 0;
$next_highest_price = 0;

I need to optimize this, there should be no need for looping the cart twice but in a hurry to prove the concept works this morning and get something ready for our promo I did it this way.  I loop through the cart and gather all my data: highest priced item, quantity and so on.  Then we loop the contents again and reduce price where needed.

foreach ( $cart_object->cart_contents as $key => $value ) {
   if( $value['data']->price > $highest_price ) {
      $highest_price = $value['data']->price;
      $highest_price_id = $value['product_id'];
      $highest_price_quantity = $value['quantity'];
      $cnt++;
   }

   if( $value['data']->price < $highest_price && $value['data']->price > $next_highest_price ) {
      $next_highest_price = $value['data']->price;
      $next_highest_price_id = $value['product_id'];
      $cnt++;
   }
}

The final loop we first check if:

  1. Highest priced item is more than 1 quantity and we are on it in the loop
  2. There’s no other item that’s considered the second highest price.  If there is, we want to discount that and not one of the highest priced items.
  3. If any of that fails then we check if this is the next highest priced item and run our discount here
foreach ( $cart_object->cart_contents as $key => $value ) {
   if ( $highest_price_quantity > 1 && $value['product_id'] === $highest_price_id && $next_highest_price === 0 ) {
      $value['data']->price = $value['data']->price - ( $value['data']->price / $value['quantity'] ) * .5;
   } elseif ( $value['product_id'] === $next_highest_price_id && $cnt > 1 ) {
      $value['data']->price = $value['data']->price - ( $value['data']->price / $value['quantity'] ) * .5;
   }
}

The discount is based on quantity.  If someone has two of the same $99 item we don’t want to make them both $48.  We want to discount just the first item but I’m not sure if that’s even doable.  We could generate a coupon or some other more complicated options but I went with the simple approach.  Let’s take the quantity, divide the price by that (so we have two $99 items, 99/2 is $48) then take 50% of that and subtract it from the price.  Each item will have 25% subtracted basically and add up to 50% total discount on 2 items.

I’ve been testing this and it seems to be working.  I JUST put this together though so needs a lot more testing to make sure it’s working correctly.

https://gist.github.com/ChrisFlannagan/0d2010c49f582d5d89fa6f9740bf5703

Tracking Conversions in WooCommerce with Simple Link Codes the Easy Way & More

woocommerce-tracking-code-plugin-simpleI wrote about this as I was building it out.  It’s evolved a bit and is now on the WordPress Plugin Repository.

https://wordpress.org/plugins/quick-tracking-conversions-for-woocommerce/

It’s simple.  You setup codes you want to track for conversions in WooCommerce.  If you have an email blast coming up then just create a code for it and attach that code to the end of all links in the email blast.  This works for affiliates, whatever.

The link looks like this: https://whoischris.com/?qtc_woo_tracking_code=testcode

Of course you can replace “testcode” with anything you want and have as many tracking codes as you’d like.  Then in the admin, you input the code you want to see the results of.  You get a total and # of conversions.  I have every intention of adding more in depth analytics but this is a proof of concept.

Passwords to Conversions Analytics

What I encountered the following week at work presented a new problem.  We are starting a site for retailers and professionals in our industry.  We sell a specialized tool only to licensed professionals and we want them to be able to carry our consumer product on their shelves, so they need to be able to buy at a discounted, bulk price.

Fortunately this site is on its own domain and I can make the functionality global.  So here’s what I needed to happen:

  • All shopping functionality should be hidden behind a password/access code that we hand out.
  • Different rep groups selling to professionals need to have their own code that can be tracked
  • We want to see total conversion for each code used

My thoughts lead to why not use the existing conversions plugin I built?  I’ll just hide all of WooCommerce behind a password wall.  Any password the admin creates can be used to access it, I just drop a cookie.

I also drop a cookie for the Quick Tracking Conversions plugin and voila, our shoppers have access and we can see what password/access code they are using to make their purchase.  The new extension can be found here:

https://github.com/ChrisFlannagan/qtc-passwords

 

Quick Campaign Conversion Tracking in WooCommerce

My company hired a marketing firm that is starting our Constant Contact campaigns amongst other things.  We want to track conversions and at this point we don’t need anything too fancy.  Between that, Facebook ads/posts, Google Analytics and our affiliates, there’s a lot of pixels, JavaScript and php functions that need to be added to our system.  It’s a bit overwhelming and each has its own installation instructions/methods.

Right now, we just want to see conversions.  We want to know what source provide how many purchases and at what value.

I searched for some quick methods and plugins that might help but again, too much complicated setup for simple conversion tracking.  So I built a thing.

Quick Tracking Conversions for WooCommerce

I envisioned a super simple system where you can take on a code to the end of a link and all visits to your site with that code would be tracked and recorded when converted.  I wanted to start with simply recorded full, purchase conversions.

I didn’t want to have to setup a campaign with a code and details in an admin before generating links.  I want to just tell our marketing person put something like ?tracking_code=MyEmailCampaign on the end of all links in a Constant Contact.

So I built a plugin.  It’s light weight, secure and solid.  It does it’s job and it does it right.  You add whatever campaign code you want to links for Facebook, Email blasts, affiliates or anything at all that you want to track conversions from a link.  Here’s an example link that could be in an email:

https://example.com/product/t-shirts?qtc_woo_tracking_code=Oct2016-email-blast

After the email goes out and orders come in I can simply go to the admin page of the plugin, type in Oct2016-email-blast and submit the form.  It will show me number of conversions and total money generated so far.

How It Works

The plugin checks for $_GET[‘qtc_woo_tracking_code’] and sets its value in a cookie.  If the user converts it adds a post_meta to the order for that tracking code.

This allows me to pull all details of every order made.  We can get products purchases, shipping methods, totals, taxes and everything.

Here’s the repo if you want to check it out.  It’s simple right now and has Google Analytics Enhanced Ecommerce option you can enable as well.  There’s room to add all sorts of conversions such as product viewing, add to cart and so on.  This plugin will grow.

https://github.com/ChrisFlannagan/woo-flanny-conversion-tracker

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