WooCommerce: Add Custom Field on Checkout Based on Product Quantity in Cart
In this tutorial, I will show you how to add dynamic checkout fields based on cart quantity on WooCommerce checkout page. The custom field will be multiply by product quantity, that means if a customer has 3 quantity in the cart then your custom field will repeat 3 times and display 3 fields on the checkout page.
Let’s say you have a booking system on your WooCommerce store and you want to capture the additional information at checkout if someone books for more than one quantity. For e.g., if you have Events/Workshops site and want to capture Name, Email, phone, and Address of everyone who attended your Event/Workshop and someone books for 3 quantity on your website then you need additional dynamic custom fields to capture the details of other 2 attendees. So if someone adds 3 quantity to the cart then the checkout page adds additional fields for other 2 attendees if 4 quantity added to the cart then it adds fields for other 3 attendees.
Within the following function, we will check how many quantities the user has in their cart and adds the additional fields to the checkout page if the quantity is more than 1. And save the field values to display it in the order in admin side.
Go to your functions.php file and add the following code at the end of the file or you can create your own plugin to add this function.
//Custom WooCommerce Checkout Fields based on Quantity add_action( 'woocommerce_before_order_notes', 'person_details' ); function person_details($checkout) { global $woocommerce; $count = $woocommerce->cart->cart_contents_count; $i = 1; for($k=2; $k<= $count; $k++) { $i++; print ('<h3>Please enter details of attendee '.$i.'</h3>'); woocommerce_form_field( 'cstm_full_name'.$i, array( 'type' => 'text', 'class' => array('my-field-class form-row-wide'), 'label' => __('Full name'), 'placeholder' => __('Enter full name'), ), $checkout->get_value( 'cstm_full_name'.$i )); echo '<div class="clear"></div>'; woocommerce_form_field( 'cstm_phone'.$i, array( 'type' => 'text', 'class' => array('my-field-class form-row-first'), 'label' => __('Phone'), 'placeholder' => __('Enter phone number'), ), $checkout->get_value( 'cstm_phone'.$i )); woocommerce_form_field( 'cstm_email'.$i, array( 'type' => 'email', 'class' => array('my-field-class form-row-last'), 'label' => __('Email address'), 'placeholder' => __('Enter email address'), ), $checkout->get_value( 'cstm_email'.$i )); echo '<div class="clear"></div>'; woocommerce_form_field( 'cstm_address'.$i, array( 'type' => 'textarea', 'class' => array('my-field-class form-row-wide'), 'label' => __('Full address'), 'placeholder' => __('Enter full address'), ), $checkout->get_value( 'cstm_address'.$i )); } } /** * Save value of fields */ add_action('woocommerce_checkout_update_order_meta', 'customise_checkout_field_update_order_meta'); function customise_checkout_field_update_order_meta($order_id) { global $woocommerce; $count = $woocommerce->cart->cart_contents_count; $i = 1; for($k=2; $k<= $count; $k++) { $i++; if (!empty($_POST['cstm_full_name'.$i])) { update_post_meta($order_id, 'Name of Attendee'.$i, sanitize_text_field($_POST['cstm_full_name'.$i])); } if (!empty($_POST['cstm_phone'.$i])) { update_post_meta($order_id, 'Phone of Attendee'.$i, sanitize_text_field($_POST['cstm_phone'.$i])); } if (!empty($_POST['cstm_email'.$i])) { update_post_meta($order_id, 'Email of Attendee'.$i, sanitize_text_field($_POST['cstm_email'.$i])); } if (!empty($_POST['cstm_address'.$i])) { update_post_meta($order_id, 'Address of Attendee'.$i, sanitize_text_field($_POST['cstm_address'.$i])); } } } /** * Add fields to order emails **/ add_filter('woocommerce_email_order_meta_keys', 'my_custom_checkout_field_order_meta_keys'); function my_custom_checkout_field_order_meta_keys( $keys ) { $i = 1; for($k=2; $k<= 50; $k++) { $i++; $keys[] = 'Name of Attendee'.$i; $keys[] = 'Phone of Attendee'.$i; $keys[] = 'Email of Attendee'.$i; $keys[] = 'Email of Participant '.$i; $keys[] = 'Address of Attendee'.$i; } return $keys; }
Hi Wasim, how are you?
I used you code from post WooCommerce: Add Dynamic Custom Field on Checkout Based on Product Quantity in Cart and it works perfectly. However, how do i change the field from optional to required?
Thank you in advance!
Dear Wan,
Just add ‘required’ => true, to make a field required.
For Example:
Hi Wasim,
Thank you so much for helping me! Will get back to you if there is anything. Wish you all the best in anything you do!
Wan Ahmad
You always welcome
This is great, how can this be altered for the Woocommerce Bookings extension?
Hey Max,
This plugin can’t be altered for Woocommerce Booking extension as it has many other features. This snippet is only getting other peoples details if there are multiple quantities in the cart.
Hey Wasim,
Thanks so much for your post, that’s exactly what I am trying to do.
I copied your code in functions.php but it didn’t work for me.
I am just starting with Woocommerce, so I appreciate any help you can give me on how I can make this work.
Do I need to add anything else for this to work?
Regards,
Leon
Hi Leon,
Can you contact me here https://wasimsama.com/contact/ regarding your issue so I can help you further?
Hi Wasim
We’ve added the code above to our functions.php. Now we want to display the fields in the confirmation e-mail. How can we do this?
Thanks for your feedback and greetings
Larissa
Hello Larissa,
Please use the following snippet to add fields in the order notification email.
I also have added this snippet in the post. Please check complete code in the post above.
Hi Wasim
Thank’s for your feedback.
I’ve added the snippet like this:
_____________________________________
get_formatted_billing_full_name() ); ?>
<?php
/*
* @hooked WC_Emails::order_details() Shows the order details table.
* @hooked WC_Structured_Data::generate_order_data() Generates structured data.
* @hooked WC_Structured_Data::output_structured_data() Outputs structured data.
* @since 2.5.0
*/
do_action( 'woocommerce_email_order_details', $order, $sent_to_admin, $plain_text, $email );
/*
* @hooked WC_Emails::order_meta() Shows order meta data.
*/
do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email );
/*
* @hooked WC_Emails::customer_details() Shows customer details
* @hooked WC_Emails::email_address() Shows email address
*/
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );
/*
* @hooked WC_Emails::email_footer() Output the email footer
*/
do_action( 'woocommerce_email_footer', $email );
add_filter(‘woocommerce_email_order_meta_keys’, ‘my_custom_checkout_field_order_meta_keys’);
function my_custom_checkout_field_order_meta_keys( $keys ) {
$i = 1;
for($k=2; $k<= 50; $k++) { $i++; $keys[] = 'Name of Attendee'.$i; $keys[] = 'Phone of Attendee'.$i; $keys[] = 'Email of Attendee'.$i; $keys[] = 'Email of Participant '.$i; $keys[] = 'Address of Attendee'.$i; } return $keys; }
_____________________________________
But unfortunately doesn't work.
Thank's for your help and greetings
Larissa
Hello Larissa,
It Looks Like you added the snippet in Woocommerce email template. You need to add this snippet in function file where you added other code to display fields on the checkout. Also, replace ‘Name of Attendee’, ‘Phone of Attendee’, ‘Email of Attendee’, ‘Email of Participant ‘, ‘Address of Attendee’ with your field names.
Hi Wasim, thanks for sharing this code snippet for custom repeater field. I used it slightly modified (i=0, k=1) as the person booking the event will be a parent and booking for their children so i need to collect names, age for all children. your code has been very helpful.
Now, how would you display this on the order page? I know how to display for one person, not in loop.. Can you help pls?
Hi Wasim, not sure if my previous msg went through..Thanks for sharing this code, very helpful! I’d like to see these fields i nhe order form as well, how can I do that?
One more question, IS this how you would add a drop down in this repeater field?
woocommerce_form_field( ‘participant_gender’.$i, array(
‘type’ => ‘select’,
‘class’ => array(‘my-field-class form-row-last’),
‘label’ => __(‘Gender’),
‘options’ = array(
” => __( ‘Select’ ),
‘Male’ => ‘Male’,
‘Female’ => ‘Female’),
),
$checkout->get_value( ‘participant_gender’.$i ));
Hi there. This works so very well except that although highlighting the fields in the additional inforamtion section after adding the required = true, it will still let the user skip through to checkout. Any reason why that you can think of?
You need to add validation for the required field.
For Example:
Thank you for this code, it helped me a lot!
But for some reason I have encountered an issue showing the data in admin order details page, is there something missing in the code?
Thanks!
Hello Wasim, thanks for your great blog post. Is it possible to limit limit this function to particular items in the cart? E.g. I’d like to add this custom field for some product IDs, but not other product IDs. Thanks
Hi there. This is exactly what I was looking for, thanks so much for sharing.
All working as expected apart from the additional fields are not showing on the order admin page. They show on the checkout and emails, just not inside the order detail page. Any ideas why this may be the case?
Thanks again,
Min/Max Quantities Woocommerce if you want to give minimum and maximum input limit for cart that you can be setup for it so vendor can be maintain stock good way
Hi Wasim,
thank you for your work, I was looking for this kind of code for a long time.
I have a little problem, I receive informations on emails, it’s perfect but I can’t retrieve the informations on admin order. I don’t have any informations about this fields.
If you can help me with that.
I really thank you.
Got the exact same issue, would be super nice if you could help with that part !
Thank you