Search

Customizing checkout fields using actions and filters

Customizing checkout fields using actions and filters should be a task you are comfortable with.

If you are unfamiliar with code and resolving potential conflicts, we have an extension that can help: WooCommerce Checkout Field Editor. Installing and activating this extension overrides any code below that you try to implement; and you cannot have custom checkout field code in your functions.php file when the extension is activated.

Note: We are unable to provide support for customizations under our Support Policy. If you cannot get the code to work, consider purchasing the extension or contact an Affiliated Woo Worker.
Custom code should be copied into your child theme’s functions.php file.

How are checkout fields loaded to WooCommerce? ↑ Back to Top

The billing and shipping fields for checkout pull from the countries class (class-wc-countries.php) and the get_address_fields function. This allows WooCommerce to enable/disable fields based on the user’s location.

Before returning these fields, WooCommerce puts the fields through a filter. This allows them to be edited by third-party plugins, themes and your own custom code.

Billing:

$address_fields = apply_filters('woocommerce_billing_fields', $address_fields);

Shipping:

$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->checkout_fields);

That means you have full control over checkout fields – you only need to know how to access them.

Lesson 1 – Overriding core fields ↑ Back to Top

Hooking into the  woocommerce_checkout_fields filter lets you override any field. As an example, let’s change the placeholder on the order_comments fields. Currently it’s set to:

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

We can change this by adding a 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;
}

You can override other parts, such as 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;
}

Or remove fields:

// 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 ) {
     unset($fields['order']['order_comments']);

     return $fields;
}

Here’s 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
    • shipping_first_name
    • shipping_last_name
    • shipping_company
    • shipping_address_1
    • shipping_address_2
    • shipping_city
    • shipping_postcode
    • shipping_country
    • shipping_state
  • account
    • account_username
    • account_password
    • account_password-2
  • order
    • 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 specific cases you 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 optional:

// 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;
}

Defining select options

If you are adding a field with type ‘select’, as stated above you would define key/value pairs. For example:

$fields['billing']['your_field']['options'] = array(
  'option_1' => 'Option 1 text',
  'option_2' => 'Option 2 text'
);

Lesson 2 – Adding custom shipping and billing fields ↑ Back to Top

Adding fields is done in a similar way to overriding fields. For example, let’s add a new field to 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;
}
It's alive!

It’s alive!

What do we do with the new field? Nothing. Because we defined the field in the checkout_fields array, the field is automatically processed and saved to the order post meta (in this case, _shipping_phone). If you want to add validation rules, see the checkout class where there are additional hooks you can use.

Lesson 3 – Adding a custom special field ↑ Back to Top

To add a custom field is similar. Let’s add a new field to checkout, after the order notes, by hooking into the following:

This gives us:

WooCommerce Codex - Checkout Field Hook

Next we need to validate the field when the checkout form is posted. For this example the field is required and not optional:

A checkout error is displayed if the field is blank:

WooCommerce Codex - Checkout Field Notice

Finally, let’s save the new field to order custom fields using the following code:

The field is now saved to the order.

If you wish to display the custom field value on the admin order edition page, you can add this code:

This is the result:

checkout_field_custom_field_admin

Example – Make phone number not required

Lesson 4 – Adding Custom Fields to Emails ↑ Back to Top

To add a custom field value to WooCommerce emails — a completed order email, for example — use the following snippet:


https://gist.github.com/woogist/2e89c92a3f7a75b98dd1

Back to the top