Adding custom checkout fields in WooCommerce

This article describes the process of adding WooCommerce custom checkout fields to your WordPress site, as well as how to ensure that the data is being stored properly in the database and add the fields to the Order Details page and order emails.

All the code snippets in this article should be added to the functions.php file in your theme-child folder.

The first thing you need to do is add an action that details the custom checkout fields. Each field has an array of properties:

  • type – type of field (select, password, text, textarea)
  • label – input field label
  • placeholder – placeholder in the input field
  • class – css class for the input
  • required – true or false, (defines if the field is required)
  • clear – true or false (applies a clear fix to the field/label)
  • label_class – css class for the label
  • options – for select boxes (options array of key => value pairs)

The example that I am using is for an event site which is asking for additional information at checkout to allow the site owners to gather some additional information on the people coming to the event. Below is the code used to add 6 new fields under the heading ‘Additional Information.’


/**
* Add the field to the checkout
*/

add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );

function my_custom_checkout_field( $checkout ) {
   echo '<div class="my_custom_checkout_field"><h2>' . __('Additional Information') .'</h2>';

woocommerce_form_field( 'home_stay', array(

   'type' => 'select',
   'label'      => __('Home Stay', 'woocommerce'),
   'placeholder'   => _x('Home Stay', 'placeholder', 'woocommerce'),
   'required'   => true,
   'class'      => array('form-row-wide'),
   'clear'     => true,
   'options' => array('option-1' => 'I can offer housing', 'option_2' => 'I am not in a place to offer housing', 'option_3' => 'I need housing'),
       ), $checkout->get_value( 'home_stay' ));

woocommerce_form_field( 'emergency_contact_name_1', array(

'type' => 'text',
   'label'      => __('Emergency Contact #1', 'woocommerce'),
   'placeholder'   => _x('Name', 'placeholder', 'woocommerce'),
   'required'   => true,
   'class'      => array('form-row-wide'),
   'clear'     => true,
       ), $checkout->get_value( 'emergency_contact_name_1' ));
       

woocommerce_form_field( 'emergency_contact_phone_1', array(

   'type' => 'text',
   'label'      => __('Emergency Contact Phone Number', 'woocommerce'),
   'placeholder'   => _x('xxx-xxx-xxxx', 'placeholder', 'woocommerce'),
   'required'   => true,
   'class'      => array('form-row-wide'),
   'clear'     => true,
       ), $checkout->get_value( 'emergency_contact_phone_1' ));
       

woocommerce_form_field( 'emergency_contact_name_2', array(

'type' => 'text',
  'label'      => __('Emergency Contact #2', 'woocommerce'),
   'placeholder'   => _x('Name', 'placeholder', 'woocommerce'),
   'required'   => false,
   'class'      => array('form-row-wide'),
   'clear'     => true,
       ), $checkout->get_value( 'emergency_contact_name_2' ));
       

woocommerce_form_field( 'emergency_contact_phone_2', array(
   'type' => 'text',
   'label'      => __('Emergency Contact Phone Number', 'woocommerce'),
   'placeholder'   => _x('xxx-xxx-xxxx', 'placeholder', 'woocommerce'),
   'required'   => false,
   'class'      => array('form-row-wide'),
   'clear'     => true,
       ), $checkout->get_value( 'emergency_contact_phone_2' ));
       

woocommerce_form_field( 'medical_conditions', array(

'type' => 'select',
  'label'      => __('Do you have any medical conditions that we should know about (e.g. seizures, diabetes, severe allergies, fainting spells, etc.)?', 'woocommerce'),
   'placeholder'   => _x('nothing', 'placeholder', 'woocommerce'),
   'required'   => true,
   'class'      => array('form-row-wide'),
   'clear'     => true,
   'options' => array('option-1' => 'No', 'option_2' => 'Yes'),
       ), $checkout->get_value( 'medical_conditions' ));

   echo '</div>';
}

This code adds these checkout fields to the website:

Screen Shot 2015-02-04 at 1.18.08 PM

Next, we need to add error checking for the 4 checkout fields that are required. Using the name from the woocommerce_form_field (above), we just need to define the text for the error that will show up if the user doesn’t enter or select an option in that field. Always ensure that the error text is descriptive so that the user understands what action they need to take.


/**
* Process the checkout
*/

add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');

function my_custom_checkout_field_process() {

   // Check if set, if its not set add an error.

   if ( ! $_POST['home_stay'] )
       wc_add_notice( __( 'Please select an option for Home Stay' ), 'error' );
   if ( ! $_POST['emergency_contact_name_1'] )
       wc_add_notice( __( 'Please enter an emergency contact' ), 'error' );
   if ( ! $_POST['emergency_contact_phone_1'] )
       wc_add_notice( __( 'Please enter an emergency contact phone number' ), 'error' );
   if ( ! $_POST['medical_conditions'] )
       wc_add_notice( __( 'Please select an option for Medical Conditions' ), 'error' );

}

Now, we need to add an action that stores the data the user entered into the custom checkout fields. Without this code, the information the user entered will disappear into the ether of the internet. The code stores the custom checkout fields to the associated WooCommerce order_id.


/**
* Update the order meta with field value
*/

add_action('woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );

function my_custom_checkout_field_update_order_meta( $order_id ) {

   if ( ! empty( $_POST['home_stay'] ) ) {
       update_post_meta( $order_id, 'home_stay', $_POST['home_stay'] );
   }
   if ( ! empty( $_POST['emergency_contact_name_1'] ) ) {
       update_post_meta( $order_id, 'emergency_contact_name_1', $_POST['emergency_contact_name_1'] );
   }
   if ( ! empty( $_POST['emergency_contact_phone_1'] ) ) {
       update_post_meta( $order_id, 'emergency_contact_phone_1', $_POST['emergency_contact_phone_1'] );
   }
   if ( ! empty( $_POST['emergency_contact_name_2'] ) ) {
       update_post_meta( $order_id, 'emergency_contact_name_2', $_POST['emergency_contact_name_2'] );

   }
   if ( ! empty( $_POST['emergency_contact_phone_2'] ) ) {
       update_post_meta( $order_id, 'emergency_contact_phone_2', $_POST['emergency_contact_phone_2'] );
   }
   if ( ! empty( $_POST['medical_conditions'] ) ) {
       update_post_meta( $order_id, 'medical_conditions', $_POST['medical_conditions'] );
   }

}

The final two steps are adding actions that pull the data we just stored in the back end to the Order Details page (in the WooCommerce backend) and to the email that the site owner can choose to receive when an order is placed.


/**
* Display field value on the order edit page
*/

add_action('woocommerce_admin_order_data_after_billing_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );

function my_custom_checkout_field_display_admin_order_meta($order){

  echo '<p><strong>'.__('Home Stay').':</strong> ' . get_post_meta( $order->id, 'home_stay', true ) . '</p>';
  echo '<p><strong>'.__('Emergency Contact 1').':</strong> ' . get_post_meta( $order->id, 'emergency_contact_name_1', true ) . '</p>';
  echo '<p><strong>'.__('Emergency Phone 1').':</strong> ' . get_post_meta( $order->id, 'emergency_contact_phone_1', true ) . '</p>';
  echo '<p><strong>'.__('Emergency Contact 2').':</strong> ' . get_post_meta( $order->id, 'emergency_contact_name_2', true ) . '</p>';
  echo '<p><strong>'.__('Emergency Phone 2').':</strong> ' . get_post_meta( $order->id, 'emergency_contact_phone_2', true ) . '</p>';
  echo '<p><strong>'.__('Medical Conditions').':</strong> ' . get_post_meta( $order->id, 'medical_conditions', true ) . '</p>';
}

Note that in the image the 6 extra fields are now in the Order Details of the WooCommerce backend.

Screen Shot 2015-02-04 at 1.22.48 PM


/**
* Display field value on the order email
*/

add_filter('woocommerce_email_order_meta_keys', 'my_custom_checkout_field_order_meta_keys');

function my_custom_checkout_field_order_meta_keys( $keys ) {
$keys[] = 'home_stay';
$keys[] = 'emergency_contact_name_1';
$keys[] = 'emergency_contact_phone_1';
$keys[] = 'emergency_contact_name_2';
$keys[] = 'emergency_contact_phone_2';
$keys[] = 'medical_conditions';
return $keys;
}

That’s it. Once this is all done, test your code by creating some test orders and ensure that all the data you require is added. For more information on custome checkout fields, check out Custom Checkout Fields Tutorial