PHPwoocommerceintermediate
WooCommerce Custom Checkout Fields
Add custom fields to WooCommerce checkout with validation and order display
Faisal Yaqoob
December 23, 2025
#woocommerce#checkout#custom-fields#validation#orders
Code
php
1 // Add custom fields to checkout page 2 add_action('woocommerce_after_order_notes', 'custom_checkout_fields'); 3 function custom_checkout_fields($checkout) { 4 echo '<div id="custom_checkout_fields"><h3>' . __('Additional Information') . '</h3>'; 5
6 // Text field 7 woocommerce_form_field('delivery_instructions', array( 8 'type' => 'textarea', 9 'class' => array('form-row-wide', 'delivery-instructions'), 10 'label' => __('Delivery Instructions'), 11 'placeholder' => __('Any special delivery notes?'), 12 'required' => false, 13 ), $checkout->get_value('delivery_instructions')); 14
15 // Select field 16 woocommerce_form_field('gift_wrapping', array( 17 'type' => 'select', 18 'class' => array('form-row-wide'), 19 'label' => __('Gift Wrapping'), 20 'options' => array( 21 '' => __('No gift wrapping', 'woocommerce'), 22 'standard' => __('Standard - $5', 'woocommerce'), 23 'premium' => __('Premium - $10', 'woocommerce'), 24 'deluxe' => __('Deluxe - $15', 'woocommerce'), 25 ) 26 ), $checkout->get_value('gift_wrapping')); 27
28 // Checkbox field 29 woocommerce_form_field('newsletter_signup', array( 30 'type' => 'checkbox', 31 'class' => array('form-row-wide'), 32 'label' => __('Sign up for our newsletter'), 33 ), $checkout->get_value('newsletter_signup')); 34
35 // Phone field with validation 36 woocommerce_form_field('alternative_phone', array( 37 'type' => 'tel', 38 'class' => array('form-row-wide'), 39 'label' => __('Alternative Phone Number'), 40 'placeholder' => __('+1 (555) 123-4567'), 41 'required' => false, 42 ), $checkout->get_value('alternative_phone')); 43
44 // Date field 45 woocommerce_form_field('preferred_delivery_date', array( 46 'type' => 'date', 47 'class' => array('form-row-wide'), 48 'label' => __('Preferred Delivery Date'), 49 'required' => false, 50 'custom_attributes' => array( 51 'min' => date('Y-m-d', strtotime('+1 day')) 52 ) 53 ), $checkout->get_value('preferred_delivery_date')); 54
55 echo '</div>'; 56 }
WooCommerce Custom Checkout Fields
Add custom fields to your WooCommerce checkout page with validation, saving, and display in orders and emails.
// Add custom fields to checkout page
add_action('woocommerce_after_order_notes', 'custom_checkout_fields');
function custom_checkout_fields($checkout) {
echo '<div id="custom_checkout_fields"><h3>' . __('Additional Information') . '</h3>';
// Text field
woocommerce_form_field('delivery_instructions', array(
'type' => 'textarea',
'class' => array('form-row-wide', 'delivery-instructions'),
'label' => __('Delivery Instructions'),
'placeholder' => __('Any special delivery notes?'),
'required' => false,
), $checkout->get_value('delivery_instructions'));
// Select field
woocommerce_form_field('gift_wrapping', array(
'type' => 'select',
'class' => array('form-row-wide'),
'label' => __('Gift Wrapping'),
'options' => array(
'' => __('No gift wrapping', 'woocommerce'),
'standard' => __('Standard - $5', 'woocommerce'),
'premium' => __('Premium - $10', 'woocommerce'),
'deluxe' => __('Deluxe - $15', 'woocommerce'),
)
), $checkout->get_value('gift_wrapping'));
// Checkbox field
woocommerce_form_field('newsletter_signup', array(
'type' => 'checkbox',
'class' => array('form-row-wide'),
'label' => __('Sign up for our newsletter'),
), $checkout->get_value('newsletter_signup'));
// Phone field with validation
woocommerce_form_field('alternative_phone', array(
'type' => 'tel',
'class' => array('form-row-wide'),
'label' => __('Alternative Phone Number'),
'placeholder' => __('+1 (555) 123-4567'),
'required' => false,
), $checkout->get_value('alternative_phone'));
// Date field
woocommerce_form_field('preferred_delivery_date', array(
'type' => 'date',
'class' => array('form-row-wide'),
'label' => __('Preferred Delivery Date'),
'required' => false,
'custom_attributes' => array(
'min' => date('Y-m-d', strtotime('+1 day'))
)
), $checkout->get_value('preferred_delivery_date'));
echo '</div>';
}
Validate Custom Fields
// Validate custom checkout fields
add_action('woocommerce_checkout_process', 'validate_custom_checkout_fields');
function validate_custom_checkout_fields() {
// Validate alternative phone if provided
if (isset($_POST['alternative_phone']) && !empty($_POST['alternative_phone'])) {
$phone = sanitize_text_field($_POST['alternative_phone']);
// Basic phone validation
if (!preg_match('/^[\d\s\-\+\(\)]+$/', $phone)) {
wc_add_notice(__('Please enter a valid alternative phone number.'), 'error');
}
}
// Validate delivery date if provided
if (isset($_POST['preferred_delivery_date']) && !empty($_POST['preferred_delivery_date'])) {
$delivery_date = sanitize_text_field($_POST['preferred_delivery_date']);
$min_date = strtotime('+1 day');
if (strtotime($delivery_date) < $min_date) {
wc_add_notice(__('Preferred delivery date must be at least 1 day from now.'), 'error');
}
}
// Make delivery instructions required for specific shipping methods
if (isset($_POST['shipping_method']) && in_array('local_pickup', $_POST['shipping_method'])) {
if (empty($_POST['delivery_instructions'])) {
wc_add_notice(__('Please provide pickup instructions.'), 'error');
}
}
}
Save Custom Fields to Order
// Save custom fields to order meta
add_action('woocommerce_checkout_update_order_meta', 'save_custom_checkout_fields');
function save_custom_checkout_fields($order_id) {
// Save delivery instructions
if (!empty($_POST['delivery_instructions'])) {
update_post_meta($order_id, 'delivery_instructions',
sanitize_textarea_field($_POST['delivery_instructions']));
}
// Save gift wrapping
if (!empty($_POST['gift_wrapping'])) {
update_post_meta($order_id, 'gift_wrapping',
sanitize_text_field($_POST['gift_wrapping']));
// Add fee for gift wrapping
$order = wc_get_order($order_id);
$wrapping_costs = array(
'standard' => 5,
'premium' => 10,
'deluxe' => 15,
);
$wrapping_type = sanitize_text_field($_POST['gift_wrapping']);
if (isset($wrapping_costs[$wrapping_type])) {
$order->add_fee(__('Gift Wrapping'), $wrapping_costs[$wrapping_type]);
$order->calculate_totals();
$order->save();
}
}
// Save newsletter signup
if (isset($_POST['newsletter_signup'])) {
update_post_meta($order_id, 'newsletter_signup', 1);
// Add customer to newsletter list (example)
$order = wc_get_order($order_id);
$email = $order->get_billing_email();
// add_to_newsletter($email); // Your newsletter function
}
// Save alternative phone
if (!empty($_POST['alternative_phone'])) {
update_post_meta($order_id, 'alternative_phone',
sanitize_text_field($_POST['alternative_phone']));
}
// Save preferred delivery date
if (!empty($_POST['preferred_delivery_date'])) {
update_post_meta($order_id, 'preferred_delivery_date',
sanitize_text_field($_POST['preferred_delivery_date']));
}
}
Display in Admin Order Page
// Display custom fields in admin order details
add_action('woocommerce_admin_order_data_after_billing_address', 'display_custom_fields_in_admin');
function display_custom_fields_in_admin($order) {
$order_id = $order->get_id();
echo '<div class="custom-checkout-fields"><h3>' . __('Additional Order Information') . '</h3>';
// Delivery instructions
$delivery_instructions = get_post_meta($order_id, 'delivery_instructions', true);
if ($delivery_instructions) {
echo '<p><strong>' . __('Delivery Instructions:') . '</strong><br>' .
esc_html($delivery_instructions) . '</p>';
}
// Gift wrapping
$gift_wrapping = get_post_meta($order_id, 'gift_wrapping', true);
if ($gift_wrapping) {
echo '<p><strong>' . __('Gift Wrapping:') . '</strong> ' .
esc_html(ucfirst($gift_wrapping)) . '</p>';
}
// Alternative phone
$alt_phone = get_post_meta($order_id, 'alternative_phone', true);
if ($alt_phone) {
echo '<p><strong>' . __('Alternative Phone:') . '</strong> ' .
esc_html($alt_phone) . '</p>';
}
// Preferred delivery date
$delivery_date = get_post_meta($order_id, 'preferred_delivery_date', true);
if ($delivery_date) {
echo '<p><strong>' . __('Preferred Delivery Date:') . '</strong> ' .
esc_html(date('F j, Y', strtotime($delivery_date))) . '</p>';
}
// Newsletter signup
$newsletter = get_post_meta($order_id, 'newsletter_signup', true);
if ($newsletter) {
echo '<p><strong>' . __('Newsletter Signup:') . '</strong> Yes ✓</p>';
}
echo '</div>';
}
Display in Order Emails
// Add custom fields to order emails
add_filter('woocommerce_email_order_meta_fields', 'custom_fields_in_emails', 10, 3);
function custom_fields_in_emails($fields, $sent_to_admin, $order) {
$order_id = $order->get_id();
$delivery_instructions = get_post_meta($order_id, 'delivery_instructions', true);
if ($delivery_instructions) {
$fields['delivery_instructions'] = array(
'label' => __('Delivery Instructions'),
'value' => $delivery_instructions,
);
}
$gift_wrapping = get_post_meta($order_id, 'gift_wrapping', true);
if ($gift_wrapping) {
$fields['gift_wrapping'] = array(
'label' => __('Gift Wrapping'),
'value' => ucfirst($gift_wrapping),
);
}
$delivery_date = get_post_meta($order_id, 'preferred_delivery_date', true);
if ($delivery_date) {
$fields['preferred_delivery_date'] = array(
'label' => __('Preferred Delivery Date'),
'value' => date('F j, Y', strtotime($delivery_date)),
);
}
return $fields;
}
Update Order Details on My Account Page
// Display custom fields on order details page (customer account)
add_action('woocommerce_order_details_after_order_table', 'display_custom_fields_on_order_details');
function display_custom_fields_on_order_details($order) {
$order_id = $order->get_id();
$delivery_instructions = get_post_meta($order_id, 'delivery_instructions', true);
$gift_wrapping = get_post_meta($order_id, 'gift_wrapping', true);
$delivery_date = get_post_meta($order_id, 'preferred_delivery_date', true);
if ($delivery_instructions || $gift_wrapping || $delivery_date) {
echo '<section class="woocommerce-order-custom-fields">';
echo '<h2>' . __('Additional Information') . '</h2>';
echo '<table class="woocommerce-table">';
if ($delivery_instructions) {
echo '<tr><th>' . __('Delivery Instructions:') . '</th>';
echo '<td>' . esc_html($delivery_instructions) . '</td></tr>';
}
if ($gift_wrapping) {
echo '<tr><th>' . __('Gift Wrapping:') . '</th>';
echo '<td>' . esc_html(ucfirst($gift_wrapping)) . '</td></tr>';
}
if ($delivery_date) {
echo '<tr><th>' . __('Preferred Delivery Date:') . '</th>';
echo '<td>' . esc_html(date('F j, Y', strtotime($delivery_date))) . '</td></tr>';
}
echo '</table>';
echo '</section>';
}
}
Styling
#custom_checkout_fields {
margin: 20px 0;
padding: 20px;
background: #f9f9f9;
border-radius: 5px;
}
#custom_checkout_fields h3 {
margin-top: 0;
}
.custom-checkout-fields {
margin: 20px 0;
padding: 15px;
background: #f9f9f9;
border: 1px solid #e0e0e0;
border-radius: 4px;
}
.custom-checkout-fields p {
margin: 10px 0;
}
Features
- Multiple Field Types: Text, textarea, select, checkbox, date, and tel inputs
- Validation: Built-in validation for phone numbers and dates
- Order Integration: Saves to order meta and displays everywhere
- Email Display: Shows custom fields in order confirmation emails
- Admin Display: Shows fields in WooCommerce admin order page
- Customer Display: Shows on order details in My Account
- Dynamic Pricing: Can add fees based on field selections (gift wrapping example)
- Conditional Logic: Can make fields required based on other selections
Dependencies
- WooCommerce
Related Snippets
WooCommerce Custom Product Fields
Add custom fields to WooCommerce products with admin UI and frontend display
PHPwoocommerceintermediate
phpPreview
// Add custom fields to product general tab
add_action('woocommerce_product_options_general_product_data', 'add_custom_product_fields');
function add_custom_product_fields() {
global $post;
...#woocommerce#wordpress#product-fields+2
12/23/2025
View
Add Custom WooCommerce Checkout Field
Add a custom field to WooCommerce checkout page and save it to order meta
PHPwoocommerceintermediate
phpPreview
// Add custom field to checkout
function add_custom_checkout_field($checkout) {
echo '<div id="custom_checkout_field"><h3>' . __('Additional Information') . '</h3>';
...#woocommerce#checkout#custom-field+1
1/9/2025
View
WooCommerce Bulk Discounts and Quantity Pricing
Implement bulk discounts, quantity-based pricing, and tiered discounts in WooCommerce
PHPwoocommerceadvanced
phpPreview
// Apply bulk discount based on quantity
add_action('woocommerce_before_calculate_totals', 'apply_bulk_discount');
function apply_bulk_discount($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
...#woocommerce#pricing#discounts+2
12/23/2025
View