How to add an input field to WooCommerce cart items

This is a simple method to add a text input field to each WooCommerce cart item. Customers can enter text into the field which will be saved as meta data to the cart item – so you will receive it with the order.

Add a textarea field to a WooCommerce cart item

First, we just need to add the textarea field. We use the woocommerce_after_cart_item_name hook so our textarea will appear after the product name.

* Add a text field to each cart item
function prefix_after_cart_item_name( $cart_item, $cart_item_key ) {
$notes = isset( $cart_item['notes'] ) ? $cart_item['notes'] : '';
'<div><textarea class="%s" id="cart_notes_%s" data-cart-id="%s">%s</textarea></div>',
add_action( 'woocommerce_after_cart_item_name', 'prefix_after_cart_item_name', 10, 2 );
* Enqueue our JS file
function prefix_enqueue_scripts() {
wp_register_script( 'prefix-script', trailingslashit( plugin_dir_url( __FILE__ ) ) . 'update-cart-item-ajax.js', array( 'jquery-blockui' ), time(), true );
'ajaxurl' => admin_url( 'admin-ajax.php' )
wp_enqueue_script( 'prefix-script' );
add_action( 'wp_enqueue_scripts', 'prefix_enqueue_scripts' );

You can see below how it’ll look in the cart (using the Storefront theme).

WooCommerce cart item textarea

At the moment, the user will be able to enter text into the field but the text won’t save. We are going to use some AJAX to save the text.

The code above not only adds the textarea to the cart item, it also enqueues a JavaScript file ready for our AJAX.

It’s assumed that you’re using the code on this page to create a new plugin. If so, you should create a new JS file with the code below and place the file in the root directory of your plugin.

However, if you’ve added the PHP above to your theme functions.php or as a snippet on your site, you’ll need to change the location of the JS file by updating line 21 of the snippet above to identify the location of the JS file.

$('.prefix-cart-notes').on('change keyup paste',function(){
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
var cart_id = $(this).data('cart-id');
type: 'POST',
url: prefix_vars.ajaxurl,
data: {
action: 'prefix_update_cart_notes',
security: $('#woocommerce-cart-nonce').val(),
notes: $('#cart_notes_' + cart_id).val(),
cart_id: cart_id
success: function( response ) {

Now, when the user types anything, the contents of the text field get sent back to the server ready to be saved as meta data to the cart item.

* Update cart item notes
function prefix_update_cart_notes() {
// Do a nonce check
if( ! isset( $_POST['security'] ) || ! wp_verify_nonce( $_POST['security'], 'woocommerce-cart' ) ) {
wp_send_json( array( 'nonce_fail' => 1 ) );
// Save the notes to the cart meta
$cart = WC()->cart->cart_contents;
$cart_id = $_POST['cart_id'];
$notes = $_POST['notes'];
$cart_item = $cart[$cart_id];
$cart_item['notes'] = $notes;
WC()->cart->cart_contents[$cart_id] = $cart_item;
wp_send_json( array( 'success' => 1 ) );
add_action( 'wp_ajax_prefix_update_cart_notes', 'prefix_update_cart_notes' );
add_action( 'wp_ajax_nopriv_prefix_update_cart_notes', 'prefix_update_cart_notes' );
function prefix_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
foreach( $item as $cart_item_key=>$cart_item ) {
if( isset( $cart_item['notes'] ) ) {
$item->add_meta_data( 'notes', $cart_item['notes'], true );
add_action( 'woocommerce_checkout_create_order_line_item', 'prefix_checkout_create_order_line_item', 10, 4 );

The prefix_update_cart_notes function does a security check using the WooCommerce cart nonce then saves the content of the textarea as meta data in the cart item. You can check out this article for more information about updating cart meta for items that have already been added to the cart.

Add the custom text to the order meta

Finally, we want to pass our meta data to the order so that we can use it after the customer has checked out. The prefix_checkout_create_order_line_item function takes care of that, iterating through each item and saving notes when it finds them.


    • Hi Edwin – yes, you’d need to add a conditional statement in the prefix_after_cart_item_name function to check whether the cart item contained the product ID.

  1. Thanks this is so cool for what I was looking for, helpme a lot, for the folks looking the same features I make this work by addind manually the urls on function prefix_enqueue_scripts() {
    wp_register_script( ‘prefix-script’, trailingslashit( ‘’) . ‘update-cart-item-ajax.js’,

    ‘ajaxurl’ => ‘’

    and also changing the update-cart-item-ajax.js script action as follow:
    type: ‘POST’,
    url: prefix_vars.ajaxurl,
    data: {
    action: ‘wp_ajax_prefix_update_cart_notes’,
    security: $(‘#woocommerce-cart-nonce’).val(),

  2. Well. I tried using different approaches. Didn’t get the right result.
    Hoping you will reply quickly tho.
    So to make things clear on what I’ve done.
    I took the first code (woocommerce-cart-input.php) and pasted in, as is, on the functions.php on my child theme.
    Yet the JS file didn’t load (as again, I’m using a child theme, so some changes need to be done and I’m not quite sure what)
    so I did what tucson-az commented on the github page ( and placed the JS code within the cart, checkout and shop page.

    The option is being added to the cart page, but nothing is being saved, or let me check out.

    So, I’m looking for some more clear instructions on how is the best way to implement this on my website.
    Thank you so much šŸ™‚

    • Hi Yoske

      I’ve updated the article to provide some further explanation. You’ll need to either use this code to create a new plugin or, if you add the PHP to your theme’s functions.php file or as a snippet, you’ll need to ensure you tell the snippet where to find the JS file.



  3. Hi, thank you!
    It really helped me! and it works, but when I add text to the custom field and then I update the cart – the field get clear, if I’m not refreshing and straightforward to checkout, the field is added to the order as i need,

    you have an idea how to keep the value even after clicking update Cart or change quantity?

  4. Should the last line of the final code example be this?

    add_action( ‘woocommerce_checkout_create_order_line_item’, ‘prefix_checkout_create_order_line_item’, 10, 4 );

      • As I was working on implementing this today, I realized that entire function is not quite right. It shouldn’t have the foreach loop, and it should be looking for the individual meta data in the $values array, like this:

        function prefix_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
        if( isset( $values[‘notes’] ) ) {
        $item->add_meta_data( ‘notes’, $values[‘notes’], true );

        • One other issue I ran into that is now resolved. This was working fine for me if I was logged in, but if I wasn’t, the AJAX spinner on the cart page would just go forever, and there would be an HTTP 400 Bad Request error in the console.

          This is because (and I do this just rarely enough that I always forget it in the meantime) WordPress has two separate hooks for back-end and (non-logged-in) front-end AJAX calls. So in the final code sample above, in addition to this line:

          add_action( ‘wp_ajax_prefix_update_cart_notes’, ‘prefix_update_cart_notes’ );

          You should also have this right after it:

          add_action( ‘wp_ajax_nopriv_prefix_update_cart_notes’, ‘prefix_update_cart_notes’ );

  5. Hi

    I have added the three files to a zip file and uploaded it as a plugin. However I get a js 400 error, when i start typing into the custom field.

    What iā€™m I going wrong? Does these scripts not work any longer?

  6. Hi
    I want upload customer image per cart line item on the cart page.No idea for this problem.But I haven’t done it yet.You can help me?
    Thanks All.

  7. Hi Gareth

    I dont have any questions i just want to thank you for a great work it fixed my problem that customer didnt want to let go of.

    Thank you

Leave a Reply

Your email address will not be published. All fields are required.