Add Custom Cart Item Data in WooCommerce

One of the greatest things about WooCommerce is the flexibility it gives you as a store owner. I’m currently working on a side project where I needed to add some custom data to a product when adding it to the cart. Using hooks means I can achieve this quite easily.

In the following tutorial I will guide you through the process of adding a field to your product, showing that data in your cart, saving it to the order, and then displaying it to the customer and admin users.

This is an advanced tutorial. You’re best off building this functionality into a custom plugin, but I’ll leave that decision up to you.

Want to download the code from this tutorial as an example plugin?

Simply enter your name and email to receive the complete and formatted version of this code as a feature plugin for FREE. I've also added a little bonus to the code!

You will receive occasional emails from Iconic, but you're more than welcome to unsubscribe at any time. I won't spam or share your details with anyone, ever.

Add a Custom Field to Your Product

Firstly, we’ll want to add a custom field to our product. Let’s consider this scenario as our example; you run a store which makes custom engraved wooden signs. You want your customer to be able to enter the text for their engraving into an input field on your product, which is then saved with the order for the production team to start building the sign.

I have set up a simple product 1 to act as the base of our customisable product.

Before the add to cart button, let’s add a simple input field called “Engraving”.

We want our custom field to be within the add to cart form, otherwise the data will not be posted along with the form when the customer adds it to their cart. Within the /single-product/add-to-cart/simple.php template, there are a number of hooks we could use. It makes sense to add our field before the add to cart button, so we’ll use the woocommerce_before_add_to_cart_button hook.

There’s a few things going on here:

  • Firstly, I’m checking that this is our product with a hardcoded ID. Ideally we’d have a meta field in the edit product page where we can toggle the engraving field from showing. But for the sake of clarity and speed, I’ve done it like this.
  • Next, we’re breaking out of PHP and outputting our field HTML.
  • I’ve dropped in a maxlength on the input field.
  • Finally, I add the action to output that field before the add to cart button.

Add Engraving Data to the Cart Item

Our customer can now enter their engraving text before they add the product to the cart. Currently, when they do add the product to the cart, nothing will happen. We need to grab that data when it’s posted, and add it to our product before it’s added to the cart.

WooCommerce is quite clever in the way it adds multiple items to the cart. For example, if we add the sign to the cart twice with the same text, we’d want that to show as a single item in the cart with a quantity of 2. However, if we add the product to the cart with 2 different engravings, we’d want that to show as 2 separate items in the cart.

WooCommerce has this covered. It uses any item meta we add to the cart item (among other things) to generate the cart ID. This means if our item meta is unique, it will be shown as a unique product in the cart.

To catch this engraving data when the product is added to the cart, we want to use the woocommerce_add_cart_item_data filter.

This filter accepts 3 parameters:

  • $cart_item_data
    An array containing any other cart item data for this product. As with any filter in WordPress, this is also what we want the function to return.
  • $product_id
    The ID of the product we’re adding to the cart.
  • $variation_id
    If we’re adding a variation, this is the variation ID.

Firstly, we’re using filter_input() to sanitise our posted data. If $engraving_text is empty (i.e. no value was entered or the data was not even posted), then we go right ahead and return the $cart_item_data.

If it does have a value, we assign it to the $cart_item_data array with a key of iconic-engraving. Then we return $cart_item_data.

Our custom engraving data is now associated to the item in the cart. However, it won’t actually save with the order or show up anywhere yet.

Display Engraving Data in the Cart

Now that we’ve associated our engraving data with the cart item, we can access it and display it in the cart. By default, WooCommerce shows variation data in the cart after the product title, so it makes sense for us to add it there. We can use the woocommerce_get_item_data filter to add our engraving data to the cart item.

As you can see, woocommerce_get_item_data accepts 2 parameters:

  • $item_data
    This is an array containing additional data for our cart item.
  • $cart_item
    This is an array of our cart item and its associated data.

Because we assigned our engraving data to the cart item, it is now accessible in the $cart_item array. Firstly we check that it exists. If not, we return the item data as normal. Otherwise, we add our data to the $item_data array, assigning it a key and a value. The key will be used as the data item title.

You’ll notice there is also a display array item. If this is populated it will be used on the frontend instead of the value array item. This allows you to have a different value to what is displayed on the frontend. In this case, I left it empty so the value field is used instead. You can also leave it out of the array entirely, if you wish.

Save Engraving Data to the Order

The next step is to save the data to the order when it is processed. This is actually very straightforward when we use the new CRUD methods in WooCommerce. All we need to do is hook into the woocommerce_checkout_create_order_line_item hook and add our order item meta. WooCommerce will then handle displaying that data in the order receipt, account area, and admin area.

The woocommerce_checkout_create_order_line_item action accepts 4 parameters:

  • $item
    This is the order line item object.
  • $cart_item_key
    This is the string containing our cart item key.
  • $values
    This is an array containing all the data for our cart item, including our custom data.
  • $order
    This is a WC_Order instance containing the new order object.

Firstly, we check whether the iconic-engraving value is set. If not, we return and do nothing else. If it is, we use the add_meta_data() method on the $item to add the engraving data to our order item.

The add_meta_data() method accepts 3 parameters:

  • $meta_key
    This is the meta key. This is also what is displayed alongside the order item to the customer, so I have entered it as the label “Engraving”.
  • $meta_value
    This is the value of our meta data, the engraving text in this instance.
  • $unique ( bool – optional )
    Setting this to true makes sure this meta key is unique. It is false by default.

One interesting thing to note; if you want to add meta data to order item that only the admin can see, prefix the $meta_key with an underscore: $item->add_meta_data( '_private_meta', 'Some Value' ). This will then show in the admin area only.

As mentioned, this meta data is now saved to the order item, and is displayed throughout:

Conclusion

So there you have it; that’s how you add custom cart item data and then save it to your final order. There’s many scenarios for this, so I hope this tutorial gets you off to a good start. Let me know what you do with it in the comments below.

Want to download the code from this tutorial as an example plugin?

Simply enter your name and email to receive the complete and formatted version of this code as a feature plugin for FREE. I've also added a little bonus to the code!

You will receive occasional emails from Iconic, but you're more than welcome to unsubscribe at any time. I won't spam or share your details with anyone, ever.

Footnotes

  1. Image courtesy of The Rustic Dish

97 Comments

  1. yusra says:

    the data i am typing in text box at single product page is not being displayed on my cart page.
    where should i write this filter add_filter( ‘woocommerce_add_cart_item_data’, ‘iconic_add_engraving_text_to_cart_item’, 10, 3 );
    i am writing it on same simple product page but nothing is happening

    • James Kemp says:

      Hey, you would need to add this functionality as a custom plugin (preferred), or to your theme/child theme’s functions.php file (not preferred!).

      • yusra says:

        ok james .let me add it as a plugin in my plugins folder and active it..i hope it will work.. thank u soo much for quick response .

        • James Kemp says:

          It’ll need some additional setup to work out of the box as a plugin, if you’re not too familiar with it I’d suggest the theme functions.php file, or there’s a plugin called Code Snippets which may work for you: https://en-gb.wordpress.org

          • yusra says:

            it is working in both conditions 🙂 .. in themes functions.php file and as a plugin too ..
            you have done a great job James…. thnks alot

            i have one question more..
            i am using WCfrontend manager.[my client’s site is based on multivendor concept]
            how can i make it possible for my vendor to see this custom data.

          • James Kemp says:

            Hey, I’m not familiar with using that plugin, I’m afraid. Best of luck!

          • yusra says:

            its ok james. thnx again
            but can u tell me how can i pass an array of data instead of a word typed in the text box, or how can i send multiple variables instead of a word typed in the text box

          • James Kemp says:

            Hey, just change your input field name to: name="iconic-field[engraving]"

            Then you will have an array under “iconic-field” with “engraving” as the first array item key. You can add more like so:

            name="iconic-field[another-input]"
            name="iconic-field[something-else]"

            etc.

          • yusra says:

            james this is my drop down list (coming from database)

          • James Kemp says:

            Hey, why does it need to be an array? Selecting an option would return a single value.

          • yusra says:

            on the basis of that single value m calling some data from database that needs to be shown in cart and ordered item list.
            the data is in an array. thts why i need to passan array

          • James Kemp says:

            But you’re only passing through one value from the data pulled from the database, right? The value selected in the select field?

          • yusra says:

            M done with it successfully…
            i wanted to pass multiple values coming from database on the basis of option selected in dropdown at single product page.
            what i have done is just pulled data from data base on the basis of drop down selection and with the help of concatenation i stored all variables in $cart_item_data[‘iconic-engraving’], so that the have reached till the end i.e Store admin

            thnx once again james for your support, help and quick responses

          • yusra says:

            https://disqus.com/home/dis
            waiting for your reply in this post

  2. Hassan Arzouni says:

    I have used this code to add several custom input fields, but i do not want the information to be printed on the cart page so i did not use that snippet, however i do want the information to be shown in the order page in my dashboard, anyway to work around that?

    • James Kemp says:

      Hey,

      Use the underscore prefixed format to hide the field data on the frontend, then you’d need to hook into the admin order screen and add the meta value yourself

      • Hassan Arzouni says:

        hello again,
        can you explain your answer to me a bit more, please
        first i want to say thank you for the quick reply, i did not expect that to be honest.
        where should i call the action to have the meta data show in the order page

        • Hassan Arzouni says:

          i do not think i am clear enough, we created an add_action(‘woocommerce_checkout_create_order_line_item’, ‘whatever’ 10, 4)
          am i supposed to call this function ?
          i looked all over but did not find do_action(‘woocommerce_checkout_create_order_line_item’);

          • James Kemp says:

            Hey, that hook is part of WooCommerce ( https://github.com/woocomme… )

            You’re latching onto it to trigger your function of ‘whatever’ at that point. You do not need to do anything other than add_action to trigger your function at that point.

            Does that help?

          • Nermin Phelopis says:

            Me too, I want to add the option to the item to show it in the order email, but the option working in all places excepted the order email, please advice

  3. Andreas Wilthil says:

    Hi. Good post. Do you have any clues on what to do if the order-meta should add an extra cost to the product?

  4. Patrick Oliveira says:

    Hi. I ‘m trying to show my fields at single-product page, but it’s not working. I tested my code and saw that the function is not passing by the ‘if’ condition, when I remove the ‘if’ the field show itself! My code is exatly equals yours…

    • James Kemp says:

      Hey,

      If you want the field to show on all products you can safely remove the if statement. I mention in the post that I’ve hardcoded a product ID for the sake of the tutorial, just so the field only shows on 1 product.

      Hope this helps!

  5. Matt Frisch says:

    Thanks for the great post. I suggest one minor change. To display the item in the cart, it’s better to use the hook ‘woocommerce_get_item_data’ (instead of ‘woocommerce_cart_item_name’ as you have done). With this, the field will automatically display as meta data below the product name. Here is an example:

    function iconic_get_engraving_item_data( $other_data, $cart_item ) {

    if ( $cart_item[‘iconic-engraving’] ) {

    $other_data[] = array(
    ‘key’ => __( ‘Engraving’, ‘iconic’ ),
    ‘value’ => $cart_item[‘iconic-engraving’],
    ‘display’ => ”,
    );
    }

    return $other_data;
    }
    add_filter( ‘woocommerce_get_item_data’, ‘iconic_get_engraving_item_data’, 10, 2 );

  6. Nermin Phelopis says:

    Hi, I want to apply this option to a lot of product id and i have added the following code, but it didn’t work, please advice
    function iconic_output_engraving_field() {

    global $product;
    global $woocommerce;

    if ( $product->id !== 411 || $product->id !== 412 ){
    return;
    }

    ?>


  7. Carlos Isaias Ruiz says:

    I think this could work for several fields

    https://gist.github.com/zim

  8. Brian Hwang says:

    Hi, how does it different from woocommerce product add on plugin?

    • James Kemp says:

      Hey, main difference is this is a DIY version with no visual interface. This is targeted at developers looking to implement their own version.

  9. Галина says:

    Thanks for post!

  10. Miltos Tarasiadis says:

    At which line of simple.php file I have to add all this code?
    Thanks

  11. Noam Ahituv says:

    nice (!)

  12. Bjornen Nilsson says:

    Hi!

    How to I make this field only visible on one or more chosen categories?
    Example; I have three categories for T-shirt and would be using this as a plugin to let buyers chose what name to get printed on the shirt. But, I don’t want to show the field on all product categories – just those I choose.

    Please advise on how to do this and thanks for a great script!

  13. Judy Tsai says:

    Hi, I am trying to use this for my site but I am running an issue.

    If you add only this product to the cart, it works.

    But if there is already other product in the cart, the meta information (The engraving) will be added to all items within the cart.
    Or if you add another product that DOES NOT have meta information (the engraving) after adding this product (with engraving) to the cart, then it will erase all the meta information so the engraving text for this product is gone.

    Is there anyway I can fix this so the engraving is specific to this product and doesn’t get erased or added to other products?

    Thank you!!

  14. Dino Lonzano says:

    Hi great post I used already used this for my website though I am not a PHP developer. But I want to know how to make the input field “required” and if the cart was submitted how to display a W error notice . I appreciate if you can help

  15. David R says:

    Is there a way to limit the total number of custom engravings to 3, regardless of whether it is 3 separate products or 3 of the same product?

  16. Ben Tongue says:

    Thank you!! This post has saved me sooo much time! I do have a question and I hope you can help me. One of my ‘customs fields’ is actually hidden and is the product price (which was created via an API). How do override the product price with this field?

  17. Maurizio Spicuglia says:

    Great post!! .. You save my life….. thanks.

  18. hityou05 says:

    Great Post! Have you an idea on how to sort cart_items fields after adding customs ones? thnks

  19. Andy Little says:

    Great article. Excellent level of detail. Adding the underscore in the order meta key was perfect for what I needed. Thanks

  20. Sally says:

    Awesome. Thank you!

  21. carlos says:

    WAOOO amazing!!! It was not easy to me, but with your help, I did it. Thank you so much

  22. Boris Demrovski says:

    Man, you are a lifesaver, literally! I am doing this test job for a mob company, stuck at this part, and previous three test subjects have disappeared after failing on this step. Hoping to get through.

    • James Kemp says:

      I believe it’s all about knowing how to find a solution to a problem, rather than already knowing what the solution is. Good luck!

      • Boris Demrovski says:

        Exactly! But sometimes I feel as if I am completely stuck. On this particular project, mostly NOTHING related to Woocommerce wasn’t supposed to use its default functionality, but heavily customized. It got me so tired, can’t wait to put it behind, even though I learnt so much, but it freaks me out how huge Woocommerce is and how little I know right now…

        What is left still, is to add custom table row ‘Delivery method’ (different from shipping method) below the Shipping, with ‘Pick up at dealer’s shop: Dealer name and address’ or ‘Deliver to your shipping address’ options.

  23. yfain says:

    It is not clear where the code has to be posted. It will not work. Cause the only file you named is the simple.php. If you paste everything there, nothing works.

    • James Kemp says:

      If you’re unsure the best bet is to download the example plugin, which can be installed as a normal plugin and modified. otherwise, your theme’s functions.php file – but this is not best practise.

  24. Martin says:

    Great read !

    Do You think Its possible to add item meta directly in cart view ?

  25. Harry says:

    This is a great article! Quick question, how do now display this custom cart data in a new column on the orders admin page?

  26. Harry says:

    Great tutorial!

    How would you display the cart item data in a custom orders column?

    // new column
    function iconic_new_order_column( $columns ) {
    $columns[‘iconic_engraving’] = ‘Engraving’;
    return $columns;
    add_filter( ‘manage_edit_shop_order_columns’, ‘iconic_new_order_column’);

    // populate new column
    function iconic_populate_new_order_column( $columns ) {
    if( $column_name == ‘iconic_engraving’ ){
    //
    echo (‘What needs to go here to display cart item data?’);
    }
    }
    add_action( ‘manage_posts_custom_column’, ‘iconic_populate_new_order_column’ );

  27. Roshan says:

    Can we enable this to particular products only, not for all?

  28. Folken59 says:

    Hello,
    Thanks for this excellent tutorial .

    But I want one thing more : how can i do the same thing in the admin?

    On woocommerce admin, i would like to add other products to the order(edit order). But when i do this, the new line item is the default from woocommerce.on the pop up box for searching product, there is only the search title field.

    It could be great if we can have the same custom field before adding it to the existing order.

    Can you please write the code for adding a new field in the admin?

    Help me please

  29. Marc says:

    I never normally write a comment but this post just helped me do what would have taken me days to figure out about 1/2 a day. Thank you SO much! What a brilliant well-written helpful post!!

  30. Andy says:

    i want to upload image product. i try many plugins but not working, i need your help, same as your code.

  31. Ugene says:

    Thank you very much for this great tutorial. It is one great piece of information and also is working as i am writing.

  32. Aaron says:

    Thank you for this!
    What I REALLY am trying to work out is how to take the name and email via an add-to-cart button.
    For example, I am offering a book for free. There’s a button that, when clicked adds the book to the cart but takes the buyer immediately to an upsell, etc. BUT! people have a habit of abandoning. So what I want to accomplish is have a form with Name and Email and a button that functions as above but also sends the name and email to the cart/checkout prepopulating the purchased AND, as a bonus, if they abandon the process I still get their name and email.
    Any ideas on this one?

  33. Matt says:

    Really useful article as always James.

    If I’ve got an item in the cart and I’ve added a custom meta value as the item has been added to the cart, what would you say is the easiest way to then update that value at a later date? I’m hoping to update it via Ajax. The Ajax part isn’t the issue but knowing how to update the value is. I know certain key bits of data such as the cart item key and of course the name I gave to the new meta value.

  34. Guts says:

    Thanks a lot <3

  35. Kim Ruddock says:

    Great tutorial James. I’m trying to do something somewhat different based on a client request. They want to add a field to the cart page rather than the product page. So the cart item meta data would be assigned to the product after the product has been already added to the cart. I’ve been looking for ways to update the cart item meta outside of the add to cart action but coming up with nothing so far. Is something like this even possible?

  36. Hey James, Great information Glad to find your article. Will love to follow you from now. Thanks

  37. Moses Barok says:

    i installed plugin, where i have to go to enable this function in admin area? i can’t see this field in woocommerce setting page?

  38. Callum says:

    This is wonderful, thanks for the clear instruction. I have a question- what if the user removes the item from the cart, how do we ‘null and void’ their custom entry. I’m testing the script on a site right now, and after I remove the item, if I return to the Product page the previously entered custom text appears. So somewhere its getting stuck in Woocommerce’s session / cookie. Is there a way to systematically unset meta_data on cart empty?

    Thanks so much!

  39. Schalk says:

    Hi,
    How tricky is it do do the same, but:
    – Two option radio Button
    – Must be compulsory / Required
    – Only show on Cart Page. ie the User click on the relevant radio button below the product listed in the cart.

    If you can help, please.
    Thank you

  40. How do I add email address field on cart page when the first items is added

  41. Gihan says:

    How to enable to edit this text field value in cart page.please help me

  42. alijafar k says:

    Thanks very much for the tutorial. what if i want to add a calender? and i want the date to show each order in the order page

  43. Sa says:

    How can we add a price to the example field in your tutorial and have it calculate?

  44. Jon says:

    Excellent tutorial – I managed to adapt your code to do exactly as I wanted. Thanks.

    Sometimes with customising Woocommerce, it seems that knowing what hooks exist, and what they do, is 90% of the battle.

  45. Mr Alexander says:

    Very nice and thorough guide, details the entire process of managing cart item data.

  46. Brent Miller says:

    In the line,…

    …what is ‘iconic’ referring too?

  47. Quvang says:

    Hello,

    Can anyone help me with finding out why it is adding itself twice, once in variations and once just before the add to cart button? :S

  48. Andre C says:

    Hey is it possible to use your function with http://yourdomain.com/?add-to-cart=id&iconic-engraving and how could I adapt it?

  49. Victor says:

    I’m still new with WordPress and WooCommerce coding. So, why do you name your meta key this way, __( ‘Engraving’, ‘iconic’ ). I thought keys are usually named like _my_hidden_key or just this_is_key. Why are there two names in a bracket?

  50. intelijens says:

    Thank you @JamesKemp. Instructions and explanations were very clear. Really appreciate you posting this up for us! Cheers!

  51. Esteban says:

    Hey there, great post, thanks a lot!

    Now, what if I want to add a custom metadata when the product is added, not from its own page, but from somewhere else (from a category archive page for example) by using the add to cart ajax button.

    Any idea about how that can be achieved?
    I appreciate the help provided, and thanks again.

Leave a Reply

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