Checkout Validation
I decided to publish a separate tutorial where we are going to talk about WooCommerce checkout form AJAX validation. Some of the fields in this form already has some default validation like email or zip-code validation, I will show you how to turn it off if you wish and how to add some custom validation rules as well.
Turn off Default Validation
If you need to remove validation for some of WooCommerce checkout fields, letβs say email, phone or postcode, all you have to do is to remove validate
parameter from a field. You can do it in woocommerce_checkout_fields
filter hook.
Phone number validation
By default WooCommerce allows you to use only numbers, -
and _
for your phone number. If you input some letters into the fields, you will get an error like this.

/**
* Turn off checkout phone number validation
*
* @author Misha Rudrastyh
* @link https://rudrastyh.com/woocommerce/custom-checkout-validation.html#phone-number-validation
*/
add_filter( 'woocommerce_checkout_fields', 'misha_no_phone_validation' );
function misha_no_phone_validation( $fields ) {
// billing phone
unset( $fields[ 'billing' ][ 'billing_phone' ][ 'validate' ] );
// shipping phone
unset( $fields[ 'shipping' ][ 'shipping_phone' ][ 'validate' ] );
// uncomment the following lines if you would like to make a phone field optional
//unset( $fields[ 'billing' ][ 'billing_phone' ][ 'required' ] );
//unset( $fields[ 'shipping' ][ 'shipping_phone' ][ 'required' ] );
return $fields;
}
ZIP code validation
WooCommerce validates postcode automatically for some countries only. Anyway, you can still completely turn it off.
/**
* Remove checkout ZIP code validation
*
* @author Misha Rudrastyh
* @link https://rudrastyh.com/woocommerce/custom-checkout-validation.html#zip-code-validation
*/
add_filter( 'woocommerce_checkout_fields', 'misha_no_zip_validation' );
function misha_no_zip_validation( $fields ) {
// billing postcode
unset( $fields[ 'billing' ][ 'billing_postcode' ][ 'validate' ] );
// shipping postcode
unset( $fields[ 'shipping' ][ 'shipping_postcode' ][ 'validate' ] );
return $fields;
}
Remove email validation
/**
* Remove email validation
*
* @author Misha Rudrastyh
* @link https://rudrastyh.com/woocommerce/custom-checkout-validation.html#email-validation
*/
add_filter( 'woocommerce_checkout_fields', 'misha_no_email_validation' );
function misha_no_email_validation( $fields ) {
unset( $fields[ 'billing' ][ 'billing_email' ][ 'validate' ] );
unset( $fields[ 'shipping' ][ 'shipping_email' ][ 'validate' ] );
return $fields;
}
Custom Checkout Validation
You can also validate custom checkout fields or default ones with your own validation. And now we are about to create one. My goal would be to check both first name and last name fields to make sure that there are no numbers entered, only letters.
When creating custom validation rules, we’re using woocommerce_after_checkout_validation
, not woocommerce_checkout_fields
by the way.
/**
* Custom validation for billing first name and last name fields
*
* @author Misha Rudrastyh
* @link https://rudrastyh.com/woocommerce/custom-checkout-validation.html#custom-validation
*/
add_action( 'woocommerce_after_checkout_validation', 'misha_validate_fname_lname', 10, 2 );
function misha_validate_fname_lname( $fields, $errors ){
if ( preg_match( '/\\d/', $fields[ 'billing_first_name' ] ) || preg_match( '/\\d/', $fields[ 'billing_last_name' ] ) ){
$errors->add( 'validation', 'Your first or last name contains a number. Really?' );
}
}
If you’re creating validation rules for a custom field, you can also get it from the $fields
array, like $fields[ 'custom_checkout_field' ]
.
Here is my result:

JavaScript validation
Did you notice something weird on the previous screenshot? π No? Do you see that the error message says that either first name or last name is incorrect, but both of the fields are highlighted in green, not in red?
Let me show what I mean:

Much better, huh? How to implement it?
WooCommerce JavaScript validation function is in checkout.js
but it only checks if email matches the pattern and if the required fields are not empty. We have to add some custom JavaScript somewhere to create our own validation function. All we need is to operate with two wrapper classes: woocommerce-validated
and woocommerce-invalid
.
Below is a very simple example for the Billing Last Name field, you can improve this code for any field if you want.
$( 'body' ).on( 'blur change', '#billing_last_name', function(){
const wrapper = $(this).closest( '.form-row' );
// you do not have to removeClass() because Woo do it in checkout.js
if( /\d/.test( $(this).val() ) ) { // check if contains numbers
wrapper.addClass( 'woocommerce-invalid' ); // error
} else {
wrapper.addClass( 'woocommerce-validated' ); // success
}
});
Just in case if you do not know where to put the code β you can insert it to any of your website existing JS files or even to website wp_footer()
.
And here is the complete code.
<?php
/**
* Custom validation for billing first name and last name fields
*
* @author Misha Rudrastyh
* @link https://rudrastyh.com/woocommerce/custom-checkout-validation.html#custom-validation
*/
add_action( 'woocommerce_after_checkout_validation', 'misha_validate_fname_lname', 10, 2 );
function misha_validate_fname_lname( $fields, $errors ){
if ( preg_match( '/\\d/', $fields[ 'billing_first_name' ] ) || preg_match( '/\\d/', $fields[ 'billing_last_name' ] ) ){
$errors->add( 'validation', 'Your first or last name contains a number. Really?' );
}
}
add_action( 'wp_footer', function(){
// we need it only on our checkout page
if( ! is_checkout() ) {
return;
}
?>
<script>
jQuery(function($){
$( 'body' ).on( 'blur change', '#billing_last_name', function(){
const wrapper = $(this).closest( '.form-row' );
// you do not have to removeClass() because Woo do it in checkout.js
if( /\d/.test( $(this).val() ) ) { // check if contains numbers
wrapper.addClass( 'woocommerce-invalid' ); // error
} else {
wrapper.addClass( 'woocommerce-validated' ); // success
}
});
});
</script>
<?php
} );
How to Show Only One Error Message?
Below on the screenshot is what I mean:

So, how to prevent it and display just one error message instead?

Easy peasy π
add_action( 'woocommerce_after_checkout_validation', 'misha_one_err', 9999, 2);
function misha_one_err( $fields, $errors ){
// if any validation errors
if( ! empty( $errors->get_error_codes() ) ) {
// remove all of them
foreach( $errors->get_error_codes() as $code ) {
$errors->remove( $code );
}
// add our custom one
$errors->add( 'validation', 'Please fill the fields!' );
}
}
Please note, that the above code removes all types of errors, not only “this field is required” kind of stuff. So, you can check what type of error it is before removing it.
Types of errors:
required-field
terms
(Terms and Conditions checkbox)payment
So, you can add a condition like this for example:
if( 'terms' !== $code ) {
$errors->remove( $code );
}

Misha Rudrastyh
Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me
Hey Misha, me again
Well, this approach of your works really fine and thank you for that. Now I did tweak your code a little and comes up with this one:
I want to retain the error shown if a specific filed is empty and generate the error “Please fill in all required fields to place order!” ONLY if all fields are empty. I’m aware that there’s something wrong in my code above. Can you help me with this?
I also notice that the error for the terms and conditions below the checkout form (if checkbox is not checked) was gone.
Yes, in this case we have to check the type of validation error before removing it, so there are three types of errors:
required-field
,terms
andpayment
, in your code you can just add it:Hello Misha,
Thank you for this one. It took me months to find this answer on how to show only one error message in checkout page. One quick question, is this also applicable to those fields in Woocommerce My Account billing address and account details? What hook should I use?
Hey π
I’m glad, always welcome!
No, for billing addresses there is a different hook
woocommerce_after_save_address_validation
, but I’m afraid it won’t work for you the same way.Try this code:
hey Misha! could you explain a bit more about how to implement the JS code – i don’t get if it’s needed to do both PHP in functions file and JS in Footer.
thanks
Hey,
Everything is explained in the tut π Please ask a more specific question.
Thanks for this great article! I’m wondering if there is any possible to setup “forbidden” input for address field (billing & shipping).
I don’t want to allow the word “Postbox” inside the address fields because we can’t ship to postboxes.
Thanks a lot for your great help!
Hi Finn,
I think you can use this example just replace the condition with:
WC passes args to it’s function by reference:
protected function validate_checkout( &$data, &$errors )
So i think it worth to receive this args inside the hook’s callback also in the same way if you gonna change fields values:
function misha_validate_fname_lname( &$data, $errors )
Because hook
woocommerce_after_checkout_validation
is action, not filter (not expected anything to be returned)I would suggest to alter the misha_one_error function a bit to avoid removing validation errors :
Thank you for your comment! I’ve updated it in the tut π
Hi Misha,
Thank you for the wonderful guide. However, I am confused regarding the JS code.
I have a drop-down in my city list and I’ve set the following validation. It works fine but I wanted the field to be highlighted as well (The one done in your example for last_name):
What tweaks do I need to make to achieve this?
Hey,
The first thing that comes to my mind is to check in JS if there is a certain validation notice on the page, like:
Hey, I didn’t understand this.
I used your code to validate the last name and it worked like a charm. I want to replicate this for billing_city
Thanks a lot for this great great article. It really inspired me for my very own solution which I really would like to share with all readers here as well.
I had the need to display as well custom validation messages as inline messages on my Woocommerce checkout fields besides the “required” messages. So I created a gist with my solution. Maybe its useful for readers which have the same special case as I did.
Thanks again for this inspiring article, Misha!
https://gist.github.com/lucasjahn/2da5405d3bd7d3e12555e902c25ed784
Hi Misha, thanks for your great tutorial.
i have a question, how can we customize required error messages in a way that have multiple messages as woocommerce default but remove word of ‘billing’ from the beginning of it?
Hi Roghiye,
I think in this case it would be enough to use
woocommerce_checkout_required_field_notice
filter hook andstr_replace()
function.I spent hours searching for this.
it works.
Thank you very much. Thank you. Thank you. Thank you. Thank you.
Super-glad to help π