Custom WordPress and WooCommerce Development

WooCommerce Customize Checkout Fields

Note: This was updated for compatibility with WooCommerce 3.0+. This will cause fatal errors if used with older versions of WooCommerce.

I was digging around in WooCommerce while trying to come up with a quote for a client. Part of the scope had me wondering if you could remove some fields from the checkout process. If you aren’t selling physical products a billing address can be too much information and could even be off-putting to potential customers.

I eventually tracked the fields down from the checkout template, to the checkout class to the get_address_fields() method in the WC_Countries class.

Removing Billing Address

Like a lot of things in WooCommerce you can modify values via filter. To remove all the physical address fields from the billing address here is the code I used:

// Remove some checkout billing fields
function kia_filter_billing_fields($fields){
    unset( $fields["billing_country"] );
    unset( $fields["billing_company"] );
    unset( $fields["billing_address_1"] );
    unset( $fields["billing_address_2"] );
    unset( $fields["billing_city"] );
    unset( $fields["billing_state"] );
    unset( $fields["billing_postcode"] );
    unset( $fields["billing_phone"] );
    return $fields;
}
add_filter( 'woocommerce_billing_fields', 'kia_filter_billing_fields' );Code language: PHP (php)

Yes this could go in functions.php but that kind of locks you into a specific theme. If this is a permanent change then you probably want to create a site-specific plugin and put it in the wp-content/mu-plugins/ folder.

Add a Custom Checkout Field

While I was fooling around I figured I would see if I could add a custom checkout field. Turns out this is a bit more complex, but ultimately do-able. The following code will add the field to the checkout page, save the data to order meta and display the order meta in the orders admin.

Update: After receiving multiple contacts about adding more than one field I have modified the sample code to add 2 fields.

// Add a new checkout field
function kia_filter_checkout_fields($fields){
    $fields['extra_fields'] = array(
            'some_field' => array(
                'type' => 'text',
                'required'      => true,
                'label' => __( 'Some field' )
                ),
            'another_field' => array(
                'type' => 'select',
                'options' => array( 'a' => __( 'apple' ), 'b' => __( 'bacon' ), 'c' => __( 'chocolate' ) ),
                'required'      => true,
                'label' => __( 'Another field' )
                )
            );

    return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'kia_filter_checkout_fields' );

// display the extra field on the checkout form
function kia_extra_checkout_fields(){ 

    $checkout = WC()->checkout(); ?>

    <div class="extra-fields">
    <h3><?php _e( 'Additional Fields' ); ?></h3>

    <?php 
    // because of this foreach, everything added to the array in the previous function will display automagically
    foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) : ?>

            <?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>

        <?php endforeach; ?>
    </div>

<?php }
add_action( 'woocommerce_checkout_after_customer_details' ,'kia_extra_checkout_fields' );Code language: JavaScript (javascript)

Note: there is no foreach() in the rest of the function so we must save and display each field individually

Save the extra data on checkout

function kia_save_extra_checkout_fields( $order, $data ){

    // don't forget appropriate sanitization if you are using a different field type
    if( isset( $data['some_field'] ) ) {
        $order->update_meta_data( '_some_field', sanitize_text_field( $data['some_field'] ) );
    }
    if( isset( $data['another_field'] ) && in_array( $data['another_field'], array( 'a', 'b', 'c' ) ) ) {
        $order->update_meta_data( '_another_field', $data['another_field'] );
    } 
}
add_action( 'woocommerce_checkout_create_order', 'kia_save_extra_checkout_fields', 10, 2 );Code language: PHP (php)

Display the extra data to users

// display the extra data on order received page and my-account order review
function kia_display_order_data( $order_id ){  
    $order = wc_get_order( $order_id ); ?>
    <h2><?php _e( 'Additional Info' ); ?></h2>
    <table class="shop_table shop_table_responsive additional_info">
        <tbody>
            <tr>
                <th><?php _e( 'Some Field:' ); ?></th>
                <td><?php echo $order->get_meta( '_some_field' ); ?></td>
            </tr>
            <tr>
                <th><?php _e( 'Another Field:' ); ?></th>
                <td><?php echo $order->get_meta( '_another_field' ); ?></td>
            </tr>
        </tbody>
    </table>
<?php }
add_action( 'woocommerce_thankyou', 'kia_display_order_data', 20 );
add_action( 'woocommerce_view_order', 'kia_display_order_data', 20 );Code language: JavaScript (javascript)

Display extra data in admin

// display the extra data in the order admin panel
function kia_display_order_data_in_admin( $order ){  ?>
    <div class="order_data_column">
        <h4><?php _e( 'Extra Details', 'woocommerce' ); ?></h4>
        <?php 
            echo '<p><strong>' . __( 'Some field' ) . ':</strong>' . $order->get_meta( '_some_field' ) . '</p>';
            echo '<p><strong>' . __( 'Another field' ) . ':</strong>' . $order->get_meta( '_another_field' ) . '</p>'; ?>
    </div>
<?php }
add_action( 'woocommerce_admin_order_data_after_order_details', 'kia_display_order_data_in_admin' );Code language: JavaScript (javascript)

Alternatively, display extra data as editable data (and save)

This should function like the shipping and billing address data and reveal inputs when the little pencil icon is clicked. Make sure to delete the previous function as two functions with the same name will cause a PHP error.

// display the extra data in the order admin panel
function kia_display_order_data_in_admin( $order ){  ?>
    <div class="order_data_column">

        <h4><?php _e( 'Extra Details', 'woocommerce' ); ?><a href="#" class="edit_address"><?php _e( 'Edit', 'woocommerce' ); ?></a></h4>
        <div class="address">
        <?php 
            echo '<p><strong>' . __( 'Some field' ) . ':</strong>' . $order->get_meta( '_some_field' ) . '</p>';
            echo '<p><strong>' . __( 'Another field' ) . ':</strong>' . $order->get_meta( '_another_field' ) . '</p>'; ?>
        </div>
        <div class="edit_address">
            <?php woocommerce_wp_text_input( array( 'id' => '_some_field', 'label' => __( 'Some field' ), 'wrapper_class' => '_billing_company_field' ) ); ?>
            <?php woocommerce_wp_text_input( array( 'id' => '_another_field', 'label' => __( 'Another field' ), 'wrapper_class' => '_billing_company_field' ) ); ?>
        </div>
    </div>
<?php }
add_action( 'woocommerce_admin_order_data_after_order_details', 'kia_display_order_data_in_admin' );

function kia_save_extra_details( $order_id, $post ){
    $order = wc_get_order( $order_id );
    $order->update_meta_data( '_some_field', wc_clean( $_POST[ '_some_field' ] ) );
    $order->update_meta_data( '_another_field', wc_clean( $_POST[ '_another_field' ] ) );
    $order->save_meta_data();
}
add_action( 'woocommerce_process_shop_order_meta', 'kia_save_extra_details', 45, 2 );Code language: HTML, XML (xml)

Add the field to order emails

The easiest way to add data to the emails is to add our meta to the list of meta that WooCommerce will print out automatically. For WooCommerce 2.3 and after, you will do it the following way:

// WooCommerce 3.0+
function kia_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
    $fields['some_field'] = array(
                'label' => __( 'Some field' ),
                'value' => $order->get_meta( '_some_field' ),
            );
    $fields['another_field'] = array(
                'label' => __( 'Another field' ),
                'value' => $order->get_meta( '_another_field' ),
            );
    return $fields;
}
add_filter( 'woocommerce_email_order_meta_fields', 'kia_email_order_meta_fields', 10, 3 );Code language: PHP (php)

If you’d rather customize the output in the emails you can add some text to any of the hooks available in the email templates.

function kia_display_email_order_meta( $order, $sent_to_admin, $plain_text ) { 
	$some_field = $order->get_meta( '_some_field' ); 
	$another_field = $order->get_meta( '_another_field' ); 
	if( $plain_text ){ 
		echo 'The value for some field is ' . $some_field . ' while the value of another field is ' . $another_field;
	} else { 
		echo 'The value for <strong>some field</strong> is ' . $some_field. ' while the value of <strong>another field</strong> is ' . $another_field . ';
	} 
} 
add_action('woocommerce_email_customer_details', 'kia_display_email_order_meta', 30, 3 );Code language: PHP (php)

Hope that helps you. I think there are a few plugins out there now if this was too intimidating, so I would suggest trying the WooCommerce Checkout Field Editor plugin which will provide a code-free user interface for editing the checkout fields.


Comments

139 responses to “WooCommerce Customize Checkout Fields”

  1. Igi Manaloto Avatar
    Igi Manaloto

    Thanks for this! I was desperately searching for the woocommerce_admin_order_data_after_order_details hook implementation then found your awesome article. <3

    1. You’re welcome! Glad it could be useful to you. I’ve been meaning to post a few more WooCommerce articles, but I keep procrastinating.

  2. Hi Kathy, I found this very interesting!
    But, what if I want to add a checkout field only for some specified product IDs? (or catgories).
    Thanks!

    1. Hi Giovanni. If you mean adding custom data to a specific product? That is an entirely different tutorial (that I haven’t written). If you mean to only show these fields if certain items are in the cart, then you will need to write some conditional logic.

  3. i have used this code for option box custom checkout page it’s working good but i am not able to send that custom field in order email.

    1. Sanjay, Please see my updates to the post.

  4. Hi,

    Could you help me with a drop down select input box for an extra field on the WooCommerce page? It would have to be just the same as you have above, but with a few options in the drop down. Like: “How did you hear about us?”
    Option 1
    Option 2
    Option 3
    Option 4

    Thank you!!

    1. You could try switching the form field type to select and supplying some options? I don’t know if everything will work, but it’s worth a shot:

      $fields['extra_fields'] = array(
                  'some_field' => array(
                      'type' => 'select',
                      'required'      => true,
                      'label' => __( 'Some field' ),
                      'options' => array( 'key' => 'Label',
                                  'key2'  => 'Label 2' )
                      )
                  );
      
  5. Noxtifer Avatar
    Noxtifer

    Hi, is it possible to save the extra field data in admin orders AND in the user profile in back-end?

    1. The data (as shown above anyway) is saved as post meta for the order. You could therefore display it in the My Account/My Orders section. Or if you really wanted I suppose it would be possible to save data as user meta. See update_user_meta().

      1. Would saving as user_meta just be a simple case of copying the above code and changing post_meta to user_meta and order_id to user_id?

        1. I lost a lot of comments to an over-aggressive spam-queue. Doubtful you need this any longer, but for anyone else the answer is yes. Assuming you have the user ID (which is available in the order object as the $order->user_id property, you can save user-specific data with update_user_meta().

  6. karkunum Avatar
    karkunum

    May I know how to add more than 1 custom fields. I have no experience in php. The above code I can just copy and paste but it will show only 1 custom field. What about more than one? I also need textarea…
    Thanks in advance.

    1. You will need to add additional keys to the $extra_fields array. kia_extra_checkout_fields() already has a foreach() so it will loop through all the fields in the array, but the rest of the functions would need to be updated accordingly. Sorry, but I can’t really want to get into providing custom support in my comments. I hope that helps. Good luck. Trying to dig into WooCommerce when you are new to PHP is a brave thing to be doing.

  7. Dan Humphrey Avatar
    Dan Humphrey

    Hi Kathy,

    First off – fantastic post, I’ve scoured Google and not found such an in-depth example. I was wondering if you’d be able to assist.

    I’m trying to take your example but convert it to do the following;

    Add 4 new fields to the registration page in woocommerce as well as checkout and my account. I can add the fields in but where I’m struggling is, making the data save to the database and showing that data in the account section.

    Here is a link to my modification of your code, you’d be a life saver if you can tell me where I’m going wrong.

    Link: codepen

    Thanks,
    Dan

    1. Thanks Dan. I’m glad you dig the post. Unfortunately, I can’t get into providing support in the comments, but if I had to quickly guess:

      add_action( 'woocommerce_checkout_after_customer_details' ,'kia_extra_checkout_fields' );
      add_action( 'woocommerce_after_customer_login_form' ,'kia_extra_checkout_fields' ); 
      add_action( 'woocommerce_after_my_account' ,'kia_extra_checkout_fields' ); 
      

      I don’t think WC()->checkout means anything after the order is placed (so in my account areas). You need to pull fields from the $order. Same with

      add_action( 'woocommerce_thankyou', 'kia_display_order_data', 20 );
      add_action( 'woocommerce_view_order', 'kia_display_order_data', 20 );
      

      Look again at my code. The $order_id is passed to those hooks, not $customer_id.

      The user ID is part of the order object: $order->user_id

  8. Hi, how can i add these custom fields value to my account details like in billing and shipping address? or in order details?

    many thanks

    1. kia_display_order_data() already displays in the my account area under order details. If you don’t like where it is displaying then attach the display function to another hook.

      1. thank you very much :D

  9. Thank you Kathy- that was an easy fix, very helpful! At some point in the future I would love to see the article that allows us to require the removed field based on certain items in the cart.

    1. You’re welcome Tobias. I’m glad you found it useful. Do you have an example of what you mean? Maybe I can write a follow up post.

  10. Thanks a LOT, Kathy! Fortunately this still works in WooCommerce 2.3.6 :)

    1. You’re welcome, Peter. It should work for a while until Woo comes out with a crazy mega overhaul. Even then, they tend to maintain backward compatibility and throw in deprecation notices so you have time to get updated.

  11. Chris Ng Avatar
    Chris Ng

    Does the “required” attribute trigger any validation? Or does it simply add an asterisk to the field label?

    1. I would assume that it would behave the same as other required fields, but I don’t actually know. You will have to test and find out. Let me know what you discover.

      1. Chris Ng Avatar
        Chris Ng

        Example of how to implement required validation can be found here: https://support.woothemes.com/hc/en-us/articles/203103527-Add-checkbox-field-to-the-checkout

  12. Even though I am using Woo 2.3.8 I was only able to get the emails working using the deprecated version. I am still digging into why that is, but at least it all works!

    The website tells the truth, Kathy is awesome! Thanks for the tutorial.

    1. Hi Jeff, glad you liked the tutorial. The woocommerce_email_order_meta_fields filter is definitely available in WooCommerce 2.3.8. Unfortunately, I am moving and travelling so I can’t look in to it. As a first thought you should make sure that if you are overriding the email templates, they are up to date and include the woocommerce_email_order_meta action hook: do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text );.

      1. Hi Kathy – thanks for the response. I wondered the same thing about the email templates as I had moved them all to my theme for customization. However, I never ended up customizing any of them except the email-header.php file. So I removed them all from my theme but that didn’t change anything with implementing the newer hook.

        1. Jeff, I’m afraid I’m out of ideas. I’m also going to Cuba for an international handball tournament with Team USA, so I can’t look any further into this right now. I hope you figure it out. If you do, please let me know what the trouble was.

  13. Hi All,

    And thank you for your support

    I have a different issue and i hoped that you can help me.

    If you can check the website above and in the check out page there is one additional field i added “How did you know about us?” and its required field.

    The issue is everytime you checkout you need to enter this field details i can’t keep the data saved.

    Kindly advice

    1. Hi Yasser,

      The article covers how to save the data from custom checkout fields. Look carefully at the kia_save_extra_checkout_fields() function. If you need further customization you can hire me via the contact page.

      -k

  14. Hi Kathy,
    A very detailed and informative post. I was wondering if I wanted users to upload image files during checkout then how would i be able to achieve the same?
    I have been searching for over a week but have a feeling ill get an answer on this forum.

    1. During checkout? Well you would need a script that handled image uploads, store that image on your server, and save the URL as meta for the order. It would be complicated. If you are trying to attach images to a specific product then I would recommend Product Addons.

  15. Hi Kathy,

    So you are adding this code as a plugin to your webpage?
    I need the part of adding the new field to the checkout and to the admin area, just that.

    Thanks!-

    1. Hi Rai, Yes I would add this as a plugin. You are free to adjust the code as you need for your own purposes.

  16. hi kathy,
    thank you for great article.

    I need a little help in changing few fields in checkout page. Actually I need to change their language using language switcher of qtranslate X plugin. So, I need to add shorcode for each fields. I managed to change it for all but it is not working for address, zip code and Town/city. Even this is not working for cart too i.e., they are not translated to Danish from English.

    Any help would be appreciated.

    Thanks
    Mrityunjay

    1. Hi Mrityunjay, sorry but I am not familiar with that plugin. However if you create a plugin from what I have written and add proper text-domains,

      for example, changing

      <?php _e( 'Some Field:' ); ?>
      

      to

      <?php _e( 'Some Field:', 'your-text-domain' ); ?>
      

      Then the strings should all be translatable by most all translation plugins.

  17. Thanks Kathy for sharing these tips :)

    1. Avec plaisir!

  18. Jason Meddle Avatar
    Jason Meddle

    Interestingly, _transaction_id meta key, which is saved into the database upon successful transaction, won’t be returned by your function kia_display_email_order_meta. Any idea why?

    1. Sorry, not really. You are sure that your gateway is setting a transaction id? something like: $order->payment_complete( $txn_id );

  19. Mayank Gupta Avatar
    Mayank Gupta

    Wonderful tips, Kathy :) Many thanks to you…

    Using these tips i could add 2 custom dates & 1 radio button, Pickup Date, Delivery Date and Order Type, to the checkout page. However, I want to add few validations, such as if Order Type –> “XXX” then Delivery Date picker should not allow user to select day before the Pickup Date selected by user.
    Can you please suggest how this can be done??

    1. My apologies, I just discovered quite a few comments in my spam queue. What you are describing is kind of beyond the scope of this tutorial. I know there are plugins for handling delivery dates, so I hope you found one of them.

  20. Hi!
    Thanks for this. Really helpful. I’m just wondering how I can now go about positioning the extra field(s)? Currently this just places a full length field at the bottom of the checkout page. I’d like it above a couple other fields in the first column. Cheers!

    1. Hi Marc, I’m glad this was helpful to you. If you look closely you will see that the checkout fields are being added to the woocommerce_checkout_after_customer_details hook. If you want the fields to display somewhere else you need to pick a different hook. You can see the hooks available in the templates/checkout/form-checkout.php template.

  21. Michelangelo Avatar
    Michelangelo

    Hi Kathy,
    congratulations for your site.

    I have a question…what if I need to put some data (a link for example) in the order confirmation email? Only if it has been bought a specific product?

    I have some products which need image upload. I would put the upload link in the confirmation mail, only if there is the right product into the order…

    1. You would need to loop through the items in the order. If you have the order object you can retrieve all the items with the $order->get_items() method.

  22. Vanessa Avatar
    Vanessa

    Hi!

    It would be helpful for us to see the option they chose besides the “a,b,c” options – but instead say “a – website” or “b – friend”.

    Is there a way to have this translate out to the order details on the backend?

    1. Hi Vanessa, thanks for stopping by. You aren’t obligated to echo out the post meta directly.

      instead of

      echo get_post_meta( $order_id, '_another_field', true );
      

      you could do

      $another_field = get_post_meta( $order_id, '_another_field', true );
      switch( $another_field ){
      case a:
         $print = __( 'Apple',' 'text-domain' );
         break;
      case b:
        $print = __( 'Bacon',' 'text-domain' );
        break;
      case c:
        $print = __( 'Cookie',' 'text-domain' );
        break;
      }
      

      or

      $another_field = get_post_meta( $order_id, &#039;_another_field&#039;, true );
      $options = WC()-&gt;checkout()-&gt;checkout_fields[&#039;extra_fields&#039;];
      if( isset( $options[$another_field] ) ){
         echo $options[$another_field];
      }
      

      I didn't test any of that, so it is all just suggestion.

      good luck, -k

  23. Hi Kathy,
    Thanks for the tut.
    how can I apply ‘checked’ feature in check box created by this method?.

  24. Hi Kathy,

    Thanks for this brilliante article.

    I am looking for a solution in our situation but could not retrieve it from above.
    Ik hope you will help me with this.

    The situation is as folowing:
    I am trying to make a tenniscourt reservation site with woocommerce and a plugin called woocommerce bookings.
    When i receive a booking form a tennis player i need to confirm this booking with an extra selectfield:
    Court 1, court 2, court 3 and court 4.
    This field may only apear in the admin section.
    So the tennisplayer get an extra conformation email with the court on wich he may play, court 4 (as an example).

    Thanks in advance,

    Wim

    1. Hi Wim, I’m glad you liked the article. It sounds like you are in need of some custom development. Unfortunately, I’m not free right now, but if you still need the work done at the end of August I might be able to fit you in then. You can use the contact page to get in touch and discuss the project scope and costs.

  25. Rob Goss Avatar
    Rob Goss

    Hello Kathy, Nice write up but how would I setup this payment method? it seems kind of complicated. I use Paypal for my Gateway so would I be able to use it also with this method. Thanks so much

    1. Hi Rob. This tutorial has nothing to do with payment gateways so PayPal is not effected.

      1. Rob Goss Avatar
        Rob Goss

        Hello Kathy, thank you so much for your fast reply. I’m trying to setup a payment method to collect payments and give my customers access to a page were they can download themes I build. Thanks for any help on this.

        1. Sounds like you just need to set up a simple product and set it to be downloadable. If it is a bespoke client theme that’s all you need. If you want to sell it to the public and handle licensing you might want to look into WooTheme’s Software Add-on or Easy Digital Downloads Software Licensing.

          1. Rob Goss Avatar
            Rob Goss

            Hello Kathy, I’m developing WordPress themes and will be displaying them on my website for customers to buy.

  26. Kathy,
    I’ve set this up using user id and meta instead and it all works great. When a user returns to checkout though the field is blank. How do I pull in the previously stored data just as woocommerce does with name fields etc. Cheers!

    1. Hi Marc, WooCommerce pulls its field data from user meta and/or session data.

      1. Thanks Kathy. I’m not sure if this is the correct way but I got it working with:


        function set_default_passport_value($fields){
        $current_user = wp_get_current_user();
        $fields['billing']['passport_field']['default']=$current_user->_passport_field;
        return $fields;
        }
        add_filter( 'woocommerce_checkout_fields', 'set_default_passport_value' );

        1. Hi Marc, Can you please share your complete code, i’m trying to achieve something similar, thank you!

  27. Hi Kathy,

    Is there a way to add an expiry “from” and “to” date into the database once the customer checks out? The date of expiry would be from the date of purchase till the same date next year. How do I add it to the database once the customer has paid and checked out? Wondering if you could point me in the right direction with this.

    Thanks.

    1. Hi Farhan,

      You can add any meta you’d like to the order in the kia_save_extra_checkout_fields function. Though if you are going to be dealing with expiry dates (and presumably renewing) then you will want to consider WooCommerce Subscriptions.

      cheers,
      -k

      1. Thanks Kathy, you are awesome! :)

  28. Nana Yaw Avatar
    Nana Yaw

    Wow, Kathy you are soo good, i’m amazed on your extensive knowledge of woocommerce. I’m glad there is someone like you out here. I would like a little help here though. I want to change some fields on checkout page based on country selected. Could you pleasssssssse help me out on it. Thank You.

    1. Hi Nana, Thanks for the compliments. I don’t handle support in my comments. You can try posting a detailed question at http://stackoverflow.com/questions/tagged/woocommerce. Cheers, -k

  29. Ok Kathy, thanks. You are great.

  30. Hey Kathy, amazing blog, thanks a lot for sharing. Hopefully you know the answer to my problem.
    I have added a custom field to my orders, specifically it is some tracking info that my site’s administrator will manually add to each order when marking them as “COMPLETED” and it will be displayed in the email my clients will receive.

    My problem is that this custom field is only stored after saving the order, so the field is not populated until the email has already been sent. The only way to effectively send all the info is to fill in this custom field, save the order, then marking it as completed and saving again! This is rather confusing and I want to know if there is a way to mark the order as completed and check for fields that have been filled in before sending the email and storing them, so all info is sent :) I appreciate any thoughts that can point me to the right direction!

    1. J, glad the article helped you. Without looking too hard, I can see that order data meta is saved via this action. You can see the function here which includes an $order->update_status() call… which is what would trigger the completed email. Therefore, I assume that if you process your meta on woocommerce_process_shop_order_meta with an earlier priority (earlier than 40, so try default 10) that your meta will be already stored and available when the email is sent. Give me a shout via the contact page if you need a quick bit of premium support to get it all working.

  31. Hello Kathy, Its Soo Good And Really helpful. And is it Possible to Hide Some Checkout Form Fields When Its Free(0$).

    1. Hi Thanku, I’m glad it was helpful. Yes, I’m sure that it is possible to hide fields when the cart total is $0, but it isn’t something I can get into right now. Good luck.

  32. Thank You

  33. Thank you. This is a very fantastic tutorial!
    How can i add the extra field after the code:

    in order to have <div class="address-field"></div><div class="extra-field"></div>?

    Best regards

    1. Hi Fabio. Take a look at the checkout-form.php template. You can see all the different hooks available. If you want to display your fields right after the address fields you should add your function to the woocommerce_checkout_after_customer_details hook. cheers, -k

      1. Thank you! last code for admin email works also on woocommerce 2.4.6?

        1. I tested and code // pre-WooCommerce 2.3 works well also for 2.4.6 =)

          I have last question and i hope you can help me. How can i display this custom field under customer detail (Dettagli cliente) with telephone and email?
          Now it’s above “Dettagli clienti”.. Thank you!

          1. Fabio, you should definitely use the post 2.3 code. The other code is deprecated and will eventually stop working. In fact, I am going to delete it from this tutorial as it is no longer relevant.

            As far as where the field displays, again I urge you to take a look at the checkout-form.php template. You can see all the different hooks available. If you want to display your fields right after the address fields you should add your function to the woocommerce_checkout_after_customer_details hook.

  34. I created a dropdown question (Do you have insurance?) to our checkout page. I am trying to do some conditional logic like, but not related to a product, just about this first question.

    Like:

    add_action( ‘woocommerce_before_checkout_form’, ‘question_insurance’ );

    function question_insurance( $checkout ) {

    echo '<div id="question_insurance"><h2>' . __('Do you have Insurance?') . '</h2>';

    woocommerce_form_field ( 'question_insurance', array(

    'type' => 'select',
    'class' => array('question-insurance-class form-row-wide'),
    'label' => __('Do you have insurance?'),
    'placeholder' => __('none', 'woocommerce'),

    'options' => array(
    'option_a' => __('No', 'no' ),
    'option_b' => __( 'Yes','yes' ),
    ),
    'required' => true,

    ), $checkout->get_value( 'question_insurance' ));

    echo ”;
    }

    add_action( ‘woocommerce_before_checkout_form’, ‘insurance_yes’ );

    function insurance_yes( $checkout ) {

    if (option_b) === true {
    echo ‘

    ‘ . __(‘its working’) . ”;
    # code…
    echo ‘

    ‘;
    }

    Any thoughts, tips, recommendations or responses WILL BE APPRECIATED !

    Thank you!

    1. In all these comments there are about 3 requests for conditional checkout fields. I might consider writing a tutorial on that. In the mean time, maybe Checkout Field Editor would be helpful.

  35. Hi,
    Just i want add personal details in my account page with save and edit option, Also i want to edit in dashboard. thanks..

    1. Hi Sureshraj,

      I think that’s a different tutorial all together. Maybe some day I might take it on, but not in the immediate future.

      Good luck,
      -k

      1. Thanks Kathy…

  36. Hi Kathy,

    Your code works great in 2.4.6 but I cannot seem to get the information to show in the admin email. It shows fine in the admin panel but not in the emails. Any thoughts?

    1. Are you sure your theme isn’t using modified email templates? The woocommerce_email_customer_details hook and woocommerce_email_order_meta_fields filter are still in use, so the code ought to still work.

      1. Thanks for the response Kathy. The theme does not have modified email templates. Seems a bit odd. I’m not sure what is causing it.

  37. Hi,

    If I edited and added some billing fields into checkout, how can I show this modifications into the admin profile panel

    Thank you so much for your time

    1. Ellery, I covered that in my tutorial. Double-check the kia_display_order_data_in_admin() function.

  38. Hello Kathy,

    I have pdf books which has password protected. how i can set custom field send when order is completed. so only completed order email has password which i have set in custom field in Woocommerce product.

    Please help me asap.

    Thanks
    Peter

    1. Sorry that this (and about 20 other comments) got lost in my spam queue. I presume you have this figured out by now, but the woocommerce_email_customer_details hook sends a fourth parameter, $email. In your callback you can then test the email’s id and only include the info on specific email. If I remember, I added that to WooCommerce myself! So for example, I think this would appear only on the completed email:

      function kia_display_email_order_meta( $order, $sent_to_admin, $plain_text, $email ) {
          if( $email->id == 'customer_completed_order' ){
      
              if( $plain_text ){
                  echo 'The password is bacon';
              } else {
                  echo '<p>The password is <strong>bacon</strong></p>';
              }
      
          }
      }
      add_action('woocommerce_email_customer_details', 'kia_display_email_order_meta', 30, 4 );
      
  39. small error in your e-mail code. It says this:

    $another_field;</p>;

    while I think it must be

    $another_field.'</p>';

    1. You’re right. Thanks for the heads up. I have fixed it now.

      1. great! Thanks for writing this btw, it helped me a lot when I needed an additional field in my billing fields on checkout. Stay Awesome :)

  40. Awesome ! Thank you !

  41. I’d like to display the info from the custom field on a separate (public) page, basically using this as a list of attendees. How would I go about doing this?

    1. Hi Josh. I try to stay away from support questions in the comments. The data is all saved as post meta for the order. So anywhere you can get the order ID you can use get_post_meta() to retrieve the data.

  42. Elisabeth Avatar
    Elisabeth

    Hi !

    It seems great and exactly what I need but I don’t know why it doesn’t work on mine.

    I’ve tried the paste the code to add a chechout field first on function.php.. bug.., and form-checking.php…bug too.
    So I’m lost. Maybe I’ve missed something ? Or haven’t understood where to paste the code ?

    1. The code belongs in your active theme’s functions.php… or better still as its own plugin (or a site-specific snippets plugin). I just confirmed that this still displays the new checkout fields, even on WC2.5beta. I would check it against a default theme like Twenty Sixteen (all the more reason for this to be in a plugin so you can switch themes without losing functionality).

      1. Elisabeth Avatar
        Elisabeth

        Perfect !

        I’ve used a dropdown. I would like to be sure the customer choose one option by himself, and not let it by default. Actually it must be empty by defaut to be sure customer choose one option.

        In your exemple :
        *’options’ => array( ‘a’ => __( ‘apple’ ), ‘b’ => __( ‘bacon’ ), ‘c’ => __( ‘chocolate’ ) )*
        Have I let *’a’* empty (*’a’ => __( ‘ ‘ )*) and maybe add an other code ?

        Also, code for adding field in order and customer email doesn’t work on mine.
        Maybe I forgot a <?php … ? php> or something else ?

        1. Please try again with kia_display_email_order_meta(). I was missing some ;. You can always enable WP_DEBUG to locate such errors. and I highly advise enabling debug mode when in development.

          If you don’t want to force a select option then add an option to the beginning of the array with a 0 or default value and check for that when processing.

          1. Elisabeth Avatar
            Elisabeth

            Are you talking about this code, isn’t ?

            When I paste it in function.php my checkout page bug
            When I paste it directly in customer-precessing-order.php, the code appears in the order email.

            I don’t understand what’s wrong.

          2. I’m sorry, I have no idea what you are referring to. Nothing in my tutorial is meant to be pasted into customer-precessing-order.php.

          3. Elisabeth Avatar
            Elisabeth

            Ok I actually don’t understand where to paste the code to add the field to order email..

          4. Reiterating that all the code in this tutorial “belongs in your active theme’s functions.php or better still as its own plugin (or a site-specific snippets plugin).”

          5. Elisabeth Avatar
            Elisabeth

            Cool ! It’s OK ! Many Thanks !

  43. Maria Maso Avatar
    Maria Maso

    Your contact form doesn’t appear to be working. :(

    1. Could you try again? It should be working now.

  44. Thank you for this tutorial.

    I’d like to collect an additional customer detail of the amount of money spent goes above a certain limit.

    Could you please help with how i could go about inserting this on the checkout form?

    1. If you are calculating an amount spent over a certain limit, it seems like you could do that automatically on checkout without inserting any new fields. If you want to shoot me an email via my contact form we can discuss hiring me for a bit of paid support.

      1. Thank you for your reply.
        Just noticed the typo in the comment. I meant to type:

        I’d like to collect an additional customer detail if the amount of money spent goes above a certain limit.

        The site is for a non-profit organisation collecting donations. If the amount donated is above a certain amount, the checkout form needs to collect their income tax reference number for tax filing purposes.

        Just looking for some pointers on how this can be done.

        1. You can show the fields conditionally, by wrapping the fields in an if() statement. You should be able to get the cart’s total to use in your comparison. WC()->cart->get_total() should get you the total. Good luck.

          1. Much appreciated Kathy! Shall work with your suggestion :)

  45. Hey Kathy, great tutorial just what I needed!

    Quick question – if I wanted to display the new fields as part of the Billing Details – so lets say: First Name; Last Name; Company; NEW FIELD… is there any way of doing this?

    I’ve looked at all the hooks but all I am able to do is display either before or after customer details.

    Your help is appreciated :)

    1. Thanks, I am glad it was helpful. To answer your question, I’m not sure, but I presume that you could filter them in via woocommerce_checkout_fields. (review my kia_filter_checkout_fields() function). Instead of creating a new extra_fields key in the $fields array, you would want to access the billing_fields key. You might need to do some array manipulation to get the new field in between existing fields, but it would be possible. Then WooCommerce should display it automatically and I don’t believe you’d need my kia_extra_checkout_fields() function. Just a guess. Good luck.

  46. Just wanted to say well done. Your article is almost 2 years old and you’re still responding to every comment! Kudos on being a great teacher and a patient human being.

    1. Hi Tali, thank you for the lovely comment! It really made my morning. This article is 2 years old? My goodness, I’m probably due for a new blog post but I don’t know what to write about. Any ideas?

  47. Anders Ringnér Avatar
    Anders Ringnér

    Great tutorial and quite helpful!

  48. congnghia Avatar
    congnghia

    Hi! i have a question.
    in my checkout page, i want to set: When a customer select a states in the States field, the City field will appear in the respective cities with that States. can you tell me how to do that?
    thanks!

    1. Hi, that question goes well beyond what this tutorial covers. You would need javascript to respond to the state selection and ajax to retrieve the cities. I’d suggest hiring a developer. Good luck.

  49. Hello Kathy! Thank you very very much for this tutorial. Worked like a charm :)

    I understand this is no support forum, but I would be very grateful if you could answer my question.
    Can you please tell me what the options should be if I also want the new info to be added to sent user e-mail ?

    Thanks in advance!

    Best Regards

    1. Hi Xonek, I’m glad the tutorial was helpful. I’m not sure what you are asking. If you add some data to the woocommerce_email_customer_details hook then it will display in all emails. -k

      1. Hello, thanks for the quick response. What I would like to do is include the new added fields to the e-mail of the user which makes an order. So that he can see in his e-mail all the information he has filled.
        Where exactly do you suggest I add the hook?

        Thanks! :)

        1. This should already be happening with either the kia_email_order_meta_fields or kia_display_email_order_metafunctions from the tutorial.

          1. Yes, it is! Tahnk you very much!

            Amazing :)

  50. Thank you Kathy, very useful code.
    Anybody knows how to put values (default ones or meta) in these fields?

  51. I want to know how add Custom Fields to date type .??
    thank you

    1. Sorry, but I don’t understand your question.

      1. Fabio Avatar
        Fabio

        Hi, congratulations for your article.
        I have added a custom field to my orders and I also see it in my admin order page.
        The problem is that I can’t edit the filed from the dashboard. Is it possibile to do it?
        Thanks a lot.
        Fabio

        1. Yes it is possible. Please check the revised post. And if that helps you then please consider buying me a cocktail.

  52. Paul Simmons Avatar
    Paul Simmons

    Good work,

    Could you please update the email code…facing an issue while displaying the custom fields data in invoice email & shipping PDFs on WooComm 2.4.7.

    Currently issue fixed with this plugin.. https://www.fmeaddons.com/woocommerce-plugins-extensions/additional-checkout-fields.html

    1. What is the issue you are facing? And I never promised that this would work with PDFs. I presume you have another plugin generating those?

  53. everything works great but my order page (admin) is returning the array i.e. b

    so it looks like this

    https://www.dropbox.com/s/wlgax8vb6ayfb1d/Screenshot%202016-06-01%2022.32.38.png?dl=0

    1. Sorry, I don’t see the problem in your screenshot. It looks like it says “Another field: B” which is exactly what it should say (assuming the field’s value was entered as B). Can you re-phrase what you are asking?

  54. for example: I don’t want it to say B…I want it to say “bacon”

    1. Well it is saving the value as b. You can either change the array so that it is no longer associative (so use array( 'apple', 'bacon', 'chocolate') ). If you are doing a multi-lingual site this isn’t the best idea b/c you’d save different values per language. But if you did it this way then you can save the value as bacon and the display will be automatic.

      Or what I’d probably do is keep saving the value as b and write a little helper function to convert b back into bacon wherever you need to display it. Example:

      function kia_get_another_option_string( $string = '' ){
          $options = array( 'a' => __( 'apple' ), 'b' => __( 'bacon' ), 'c' => __( 'chocolate' ) );
          if( $string && isset( $options[$string] ) ){
              return $options[$string]; // return the translatable string
          } else {
              return $options; // return the whole array (useful for defining the options)
          }
      }
      
  55. Ezequiel Avatar
    Ezequiel

    Hello Many thanks for your help. I have my checkout page and I want to place the field in the billing address: “Vat Number” the problem is that the field goes automatically to the bottom and I need this field near “Company Name” for the billing address. So do you know how can I place this behind company name? This was the function I used:

    // Hook in
    add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
    // Our hooked in function - $fields is passed via the filter!
    function custom_override_checkout_fields( $fields ) {
    $fields['billing']['billing_VAT Number'] = array( 'label' => __('VAT / P.IVA', 'woocommerce'), 'placeholder' => _x('VAT / P.IVA', 'placeholder', 'woocommerce'), 'required' => false, 'class' => array ('form-row-wide'), 'clear' => true );
    return $fields;
    }

    Plesae it will be nice if you can help me. Regards EZEQUIEL

    1. I’m not really sure. My best guess would be that you will need to manipulate the $fields array, splitting it, inserting the new key, and then merging it back together. Good luck.

  56. Hi, All works great but I need to show one of the extra_field in wp user admin page (not woocommerce). Coul’d you help me?
    Thank’s

    1. You want to add fields to the user profile admin page? That’s beyond the scope of this tutorial. Maybe try this