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.

phone number validation
/**
 * 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:

JavaScript validation of a billing last name checkout field

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:

A lot of validation errors at once in WooCommerce Checkout

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

Custom error message in WooCommerce Checkout

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

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

Follow me on Twitter