Skip to content

How to Add a Customizable Field to a WooCommerce Product

UPDATED 9/29/2019: Noticed some code typos and updated some of the display sections for compatibility with WooCommmerce 3.7.

In this WooCommerce tutorial I will be showing you how to add a custom field to the front-end of a WooCommerce product. We’ll be adding a text input that a customer could use to enter some special instructions or a custom inscription, etc. In theory, you could expand this to do all kinds of customizations (like allow the customer to upload an image), but this is a tutorial so let’s keep it kind of simple. Or in lieu of banging your head against a wall you could just buy WooCommerce Product Add-ons (This is an affiliate link).

We’ll start with adding the input to the single product page template then add the custom text to the cart, order, and even the checkout emails!

Please note that all code could go in your theme’s functions.php but really, this is functionality, so please put it in a plugin! This is going to be pretty code-heavy, so if you need a refresher on actions and filters and the like then you might want to review the basics before diving in to this.

First step is to add the text input to the front end

You can technically add this input anywhere, but since it is a core WooCommerce hook, woocommerce_before_add_to_cart_button is about 99% likely to work with any theme. Nothing too special going on here. We’re just adding a text input. Pay attention the input’s name. We’re going to be using that a lot.

Validate and sanitize the input data

If your field is optional, then you can delete this function completely. Or you could modify it to validate however, you’d like. For simplicity’s sake I’ve triggered an error if the customer tries to add the item to the cart without filling in any custom text.

Add the custom data to the cart item

At first there’s a lot of mystery going on with the cart. Where the heck is that data coming from anyway? All the products are stored in an array in _$SESSION data. For the most part, Woo saves the product ID and the quantity and a handful of other things, but conveniently has a filter that will allow us to pass some of our own data to the cart item.

Preserve the Cart Data

The cart is reloaded from the $_SESSION on every page load. This must be a security feature, but I am not actually 100% sure. I do know that the first time I started messing around I didn’t understand why the previous function was adding the info to the cart, but as soon as I loaded the cart it disappeared. That drove me crazy for a bit until someone pointed out the woocommerce_get_cart_item_from_session filter. Basically, we’ll just check if we already had the data in the $cart_item array, and if so, maintain it.

Save the Custom Data On Checkout

WooCommerce has improved quite a bit in how it handles this data. Now we can call a simple woocommerce_add_order_item_meta() and it kind of acts like post meta, but for the item in this specific order. The data ends up in its own table.

Display all the Things!

Now that we actually have some usable data in the cart, it is time to display it to the customer. First, we’ll want to show it in the cart.

Then we’ll want to show it in the order overview page, which should also be the same template shown in the My Account area and all emails too.

Update: Instead of having ‘order_item’ appear in the order table, we can customize the label with the following code:

Bonus, order again!

Should the customer want to order the exact same item with the exact same field we can do that too by adding the order item meta to the new cart item created when ordering again.

And that’s it! You can download the entire thing here.

Posted in

9 Comments

  1. Rodolfo on March 22, 2019 at 3:32 pm

    Legend, thanks a million Kathy!

    Side note, I suggest to replace “woocommerce_add_order_item_meta” with “wc_add_order_item_meta”

    • kathy on March 25, 2019 at 3:42 am

      Hi Rodolfo, glad you liked it. You’re right… it needs an update.

  2. Mahmoud Hassan on March 26, 2019 at 7:58 pm

    Thanks! it did exactly what i want!

  3. Sophia on May 8, 2019 at 3:38 pm

    Thank you for this!! Super helpful.

    How would I add a couple custom text boxes?

    • kathy on May 9, 2019 at 12:25 am

      @Sophia while it is possible to as many fields as you want, I strongly recommend Product Add-ons for that purpose.

  4. Kenton on September 17, 2019 at 2:59 pm

    Hi, this is absolutely amazing! Thanks so much. Everything works as expected however on the final overview page of the order as well as the email, instead of saying custom text: what was entered, is says “custom_option: what was entered.” I cannot seem to figure out why. Any suggestions? Thanks!

    • kathy on September 28, 2019 at 4:07 pm

      Hi @Kenton, I noticed a few typos thanks to your comment, so I think those are fixed now. And dropped the email order meta snippet as the data is saved as meta on the order item and not on the order. But to your question, WooCommerce defaults to the meta key custom_option when displaying the meta. I’m not sure when they added the ability to filter that label, but it’s possible now (WC3.7) and I’ve added a snippet to account for it by filtering woocommerce_order_item_display_meta_key. I’ve updated the code above, but it’s also available as a complete plugin. I hope that helps!

  5. Benjamin on November 6, 2019 at 11:01 am

    Hi, just perfect and awesome but a little little mistake ! Options can’t be display in the cart for one reason :

    $cart_item[‘custom_option’] is declared many time and it missing an underscore “_ ” like the inital name=”_custom_option”.

    Like you say, “pay attention the input’s name. We’re going to be using that a lot.”

    Thanks again for all of this !

    • kathy on November 6, 2019 at 1:43 pm

      Good catch! I recently updated this post and must’ve introduced this error then. Instead of adding the underscore everywhere, I’m going to remove it from the woocommerce_order_again_cart_item_data filter. In the DB and in the front-end input name it will have an underscore, but in the cart data array, it will not have an underscore prefix.

Leave a Comment