About WordPress

WordPress is the most popular blogging tool on the web and is used by millions of people worldwide. It uses a Content Management System (CMS) allowing users to control their content in a simple and easy to use interface.


WordPress has been around for nearly 10 years (originally named B2) and was designed to be a blogging tool. However, because it is completely free and customisable it has evolved beyond a tool just for blogs and is now used for full websites allowing people to share a whole range of information and keep it up to date. It has won countless awards and is the most popular CMS system around.

Open Source

One of the main reasons why WordPress is so popular is that you can edit everything about it and any one can change the way it works and looks. So people who are highly experienced can add, change and customise the framework and people who are new to it can just use the basic standard system. If you are willing to learn there are also a vast amount of tutorials and forums available online.


Along with being able to edit the structure and user interface WordPress also allows users and developers to change the style of the website easily with the click of a button and thousands of styled templates are available to choose from. Themes also have lots of customisable options and features.


As an added benefit, WordPress also has add-ons for themes (known as plugins) which give additional functionality helping to create a more dynamic and personal web experience. Plugins can be anything from anti-spam to weather reports. Again these are open source so for highly experienced developers, they can edit and build their own plug-ins or for people with no experience they can just the standard plug-ins.
WordPress gives a lot of flexibility to both web developers and users, which is why we build many of our sites using this system.

Apart from its ease of use and the availability of themes and plugins, WordPress can be easily modified to include custom features and functions. Hooks and filters are built into the CMS that allow you to add functionality or strip out something that is not required.


WooCommerce lets you turn your WordPress-powered website into an incredibly user-friendly online store. It’s a full eCommerce toolkit for WordPress users that want to sell things online.


In this article we describe about Customizing checkout fields using actions and filters.

Customizing checkout fields using actions and filters

How are checkout fields loaded into WooCommerce?

The fields for the checkout (billing and shipping) come from the countries class (class-wc-countries.php) and the get_address_fields function- this is so locale settings are applied to the fields letting WooCommerce enable/disable fields based on the users location.

Before returning the fields, WC will run the fields through a filter. This allows them to be edited by third party plugins and themes (and your own custom code).


$address_fields = apply_filters(‘woocommerce_billing_fields’, $address_fields);


$address_fields = apply_filters(‘woocommerce_shipping_fields’, $address_fields);
The checkout class adds the loaded fields to its ‘checkout_fields’ array, as well as adding a few other fields like “order notes”.

$this->checkout_fields[‘billing’] = $woocommerce->countries->get_address_fields( $this->get_value(‘billing_country’), ‘billing_’ );

$this->checkout_fields[‘shipping’]   = $woocommerce->countries->get_address_fields( $this->get_value(‘shipping_country’), ‘shipping_’ );

$this->checkout_fields[‘account’]    = array(

    ‘account_username’ => array(

    ‘type’ => ‘text’,

    ‘label’ => __(‘Account username’, ‘woocommerce’),

    ‘placeholder’ => _x(‘Username’, ‘placeholder’, ‘woocommerce’)


    ‘account_password’ => array(

        ‘type’ => ‘password’,      

       ‘label’ => __(‘Account password’, ‘woocommerce’),

        ‘placeholder’ => _x(‘Password’, ‘placeholder’, ‘woocommerce’),

        ‘class’ => array(‘form-row-first’)


    ‘account_password-2’ => array(

        ‘type’ => ‘password’,

        ‘label’ => __(‘Account password’, ‘woocommerce’),

        ‘placeholder’ => _x(‘Password’, ‘placeholder’, ‘woocommerce’),

        ‘class’ => array(‘form-row-last’),

        ‘label_class’ => array(‘hidden’)



$this->checkout_fields[‘order’]  = array(

    ‘order_comments’ => array(

        ‘type’ => ‘textarea’,

        ‘class’ => array(‘notes’),

        ‘label’ => __(‘Order Notes’, ‘woocommerce’),

        ‘placeholder’ => _x(‘Notes about your order, e.g. special notes for

delivery.’, ‘placeholder’, ‘woocommerce’)




This array is also passed through a filter:

$this->checkout_fields = apply_filters(‘woocommerce_checkout_fields’,


This means you have full control over checkout fields – you just need to know how to access them!

Overriding core fields

Hooking into the  woocommerce_checkout_fields filter will let you override any field. As a demonstration, lets try changing the placeholder on the order_comments fields. Currently its set to:

_x(‘Notes about your order, e.g. special notes for delivery.’, ‘placeholder’, ‘woocommerce’)

We can change this by adding a simple function to our theme functions.php file:

// Hook in

add_filter( ‘woocommerce_checkout_fields’ , ‘custom_override_checkout_fields’ );

// Our hooked in function – $fields is passed via the filter!

function custom_override_checkout_fields( $fields ) {

     $fields[‘order’][‘order_comments’][‘placeholder’] = ‘My new placeholder’;

     return $fields;


Thats it! You can override other parts too, like the labels:


// Hook in

add_filter( ‘woocommerce_checkout_fields’ , ‘custom_override_checkout_fields’ );

// Our hooked in function – $fields is passed via the filter!

function custom_override_checkout_fields( $fields ) {

     $fields[‘order’][‘order_comments’][‘placeholder’] = ‘My new placeholder’;

     $fields[‘order’][‘order_comments’][‘label’] = ‘My new label’;

     return $fields;


You can even remove fields entirely:

// Hook in

add_filter( ‘woocommerce_checkout_fields’ , ‘custom_override_checkout_fields’ );

// Our hooked in function – $fields is passed via the filter!

function custom_override_checkout_fields( $fields ) {


     return $fields;


Here is a full list of fields in the array passed to woocommerce_checkout_fields:

·     billing

·     billing_first_name

·     billing_last_name

·     billing_company

·     billing_address_1

·     billing_address_2

·     billing_city

·     billing_postcode

·     billing_country

·     billing_state

·     billing_email

·     billing_phone


·     shipping_first_name

·     shipping_last_name

·     shipping_company

·     shipping_address_1

·     shipping_address_2

·     shipping_city

·     shipping_postcode

·     shipping_country

·     shipping_state


·     account_username

·     account_password

·     account_password-2


·     order_comments

Each field contains an array of properties:

·       type – type of field (text, textarea, password, select)

·       label – label for the input field

·       placeholder – placeholder for the input

·       class – class for the input

·       required – true or false, whether or not the field is require

·       clear – true or false, applies a clear fix to the field/label

·       label_class – class for the label element

·       options – for select boxes, array of options (key => value pairs)

In some specific cases you will need to use the woocommerce_default_address_fields filter. This filter is applied to all billing and shipping default fields:

·       country

·       first_name

·       last_name

·       company

·       address_1

·       address_2

·       city

·       state

·       postcode

For example to make the address_1 field not required:

// Hook in

add_filter( ‘woocommerce_default_address_fields’ ,

‘custom_override_default_address_fields’ );

// Our hooked in function – $address_fields is passed via the filter!

function custom_override_default_address_fields( $address_fields ) {

     $address_fields[‘address_1’][‘required’] = false;

     return $address_fields;


Adding custom shipping and billing fields

Adding fields is done in a simular way to overriding fields. As an example, lets add a new field to the shipping fields – shipping_phone

// Hook in

add_filter( ‘woocommerce_checkout_fields’ , ‘custom_override_checkout_fields’ );

// Our hooked in function – $fields is passed via the filter!

function custom_override_checkout_fields( $fields ) {

     $fields[‘shipping’][‘shipping_phone’] = array(

        ‘label’     => __(‘Phone’, ‘woocommerce’),

    ‘placeholder’   => _x(‘Phone’, ‘placeholder’, ‘woocommerce’),

    ‘required’  => false,

    ‘class’     => array(‘form-row-wide’),

    ‘clear’     => true


     return $fields;


Now we have this new field, what do we do with it? We don’t need to do anything! Because we’re defined the field in the checkout_fields array the field will be automatically processed and saved to the order post meta (in this case the field will be _shipping_phone). If you want to add extra validation rules see the checkout class; there are additional hooks in there you can use.

Adding a custom special field

We’ve covered adding fields to billing/shipping/checkout fields but what if we want something more custom? Lets add a new field to the checkout, we can add this new field after order notes by hooking into the following:


* Add the field to the checkout


add_action( ‘woocommerce_after_order_notes’, ‘my_custom_checkout_field’ );

function my_custom_checkout_field( $checkout ) {

    echo ‘<div id=”my_custom_checkout_field”><h2>’ . __(‘My Field’) .

    woocommerce_form_field( ‘my_field_name’, array(

        ‘type’          => ‘text’,

        ‘class’         => array(‘my-field-class form-row-wide’),

        ‘label’         => __(‘Fill in this field’),

        ‘placeholder’   => __(‘Enter something’),

        ), $checkout->get_value( ‘my_field_name’ ));

    echo ‘</div>’;



Next we need to validate the field when the checkout form gets posted. For the sake of this example we’ll make it required:


* 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[‘my_field_name’] )

        wc_add_notice( __( ‘Please enter something into this new shiny field.’ ), ‘error’ );


This will show an error on the checkout if the field is left blank:
Finally, lets save the new field to the order custom fields using the following code:


* Update the order meta with field value


‘my_custom_checkout_field_update_order_meta’ );

function my_custom_checkout_field_update_order_meta( $order_id ) {

    if ( ! empty( $_POST[‘my_field_name’] ) ) {

        update_post_meta( $order_id, ‘My Field’, sanitize_text_field( $_POST[‘my_field_name’] ) );



Sorted! The field will now be saved to the order.

And one more thing, if you wish to display the custom field value on the admin order edition page, you can add this code:


* Display field value on the order edit page



‘my_custom_checkout_field_display_admin_order_meta’, 10, 1 );

function my_custom_checkout_field_display_admin_order_meta($order){

   echo ‘<p><strong>’.__(‘My Field’).’:</strong> ‘ . get_post_meta( $order->id, ‘My Field’, true ) . ‘</p>’;


Example – Make phone number not required

add_filter( ‘woocommerce_billing_fields’, ‘wc_npr_filter_phone’, 10, 1 );

function wc_npr_filter_phone( $address_fields ) {

               $address_fields[‘billing_phone’][‘required’] = false;

               return $address_fields;



Ajay has been working with Android development since 2014 and currently leads the Android Engineering at ti Technologies. He has the passion for coding and provides the solution with high-quality code for all our mobile app development projects. He does research on new technologies and contributes to open source projects and testing.