WooCommerce: Custom checkout field

No code solutions

You can easily do this with these Free Plugins

Coding Solutions

To customise checkout fields, we need to use these filter hook

woocommerce_checkout_fields

This hook defined in woocommerce/includes/class-wc-checkout.php:300 and contains only 1-parameter.

/**
  * Sets the fields used during checkout.
	*
	* @since 3.0.0 or earlier
	*
	* @param array[] $checkout_fields
*/
$this->fields = apply_filters( 'woocommerce_checkout_fields', $this->fields );
PHP

Every field must be an array and contains some keys ( type, label, id, priority, class, required, description, custom_attributes )

  • label* : Display text as label of field
  • id* : Unique id
  • priority* : Valid number, provide lower value to display upper position
  • Type : provide type of input field ( text, number ) or select / checkbox. Default value is text.
  • class : provide some classes for styling purposes. If field is wide column, use form-row-wide , else for first column use form-row-first and last column use form-row-first to display something like First name, Last name fields.
  • required : boolean value, field is required or not.
  • description : display some information after input/select field
  • custom_attributes : You pass additional field related HTML attributes here as key-value pairs.

Let’s see some example

Text Field
add_filter( 'woocommerce_checkout_fields', 'change_checkout_fields' );

function change_checkout_fields( $fields ) {
	$fields['billing']['custom_field_license'] = array(
		'label'       => __( 'License Code', 'custom-text-domain' ),
		'class'       => array( 'form-row-wide' ),
		'required'    => true,
		'placeholder' => __( 'Please insert license code', 'custom-text-domain' ),
		'id'          => 'custom_field_license',
		'priority'    => 40,
	);
	return $fields;
}
PHP

If field is required, WooCommerce will automatically check it’s empty or not!

Number Field
$fields['billing']['custom_randon_value'] = array(
		'type'              => 'number',
		'label'             => __( 'Random Number', 'custom-text-domain' ),
		'required'          => true,
		'class'             => array( 'form-row-wide' ),
		'description'       => __( 
		          'Please insert random number (1-25)', 'custom-text-domain' ),
		'custom_attributes' => array(
			'min' => 1,
			'max' => 25,
		),
		'id'                => 'custom_randon_value',
		'priority'          => 40,
	);
PHP
Select Field
$fields['billing']['custom_field_license_type'] = array(
		'type'        => 'select',
		'class'       => array( 'form-row-wide' ),
		'input_class' => array( 'country_select' ),
		'label'       => __( 'License Type', 'custom-text-domain' ),
		'required'    => true,
		'placeholder' => __( 'Please choose license type', 'custom-text-domain' ),
		'options'     => array(
			'basic'      => __( 'Basic', 'custom-text-domain' ),
			'enterprise' => __( 'Enterprise', 'custom-text-domain' ),
		),
		'id'          => 'custom_field_license_type',
		'priority'    => 41,
	);
PHP

Here i created fields inside billing section, You can also create fields inside shipping section on same way

$fields['shipping']['custom_field_license'] = array( ... );
PHP
Validate field values

To validate checkout fields, we need to use these action hook

woocommerce_after_checkout_validation

This hook defined in woocommerce/includes/class-wc-checkout.php:957 and contains 2-parameters.

Let’s see an example,

add_action( 
  'woocommerce_after_checkout_validation', 
  'checkout_field_validation', 10, 2 
);

/**
 * Checkout field validation.
 *
 * @param array $data data.
 * @param mixed $error error.
 *
 * @return void
 */
function checkout_field_validation( $data, $error ) {
	if ( ! empty( $data['custom_field_license'] ) 
	      && 8 !== strlen( $data['custom_field_license'] ) 
	) {
		$error->add( 'billing', 'Invalid License!' );
	}
}
PHP
Save Data

To saving checkout data we need to use these action hook

woocommerce_checkout_update_order_meta

This hook defined in woocommerce/includes/class-wc-checkout.php:456 and contains 2-parameters.

add_action( 'woocommerce_checkout_update_order_meta', 'save_data' );

function save_data( $order_id ) {

	if ( ! isset( $_POST['custom_field_license'] ) ) {
		return;
	}

	$license = sanitize_text_field( $_POST['custom_field_license'] );
	update_post_meta( $order_id, '_order_custom_license', $license );
}
PHP
Display data inside order details
add_action( 
  'woocommerce_admin_order_data_after_billing_address', 
  'display_custom_data' 
);

function display_custom_data( $order ) {
	$license = $order->get_meta( '_order_custom_license', true );
	?>
	<p>
		<strong><?php _e( 'License', 'text-domain' ); ?>:</strong>
		<br>
		<span><?php echo esc_html( $license ); ?></span>
	</p>
	<?php
}
PHP

Here, i use woocommerce_admin_order_data_after_billing_address hook to display data inside Billing column. But you can use woocommerce_admin_order_data_after_shipping_address to display data inside Shipping column.

Thanks.

Istiaq Nirab

A highly skilled and proficient WordPress developer with over Three years of professional experience in all aspects of WordPress website creation, including design, plug-ins, and implementation. Results-driven individual contributor with a successful track record in exceeding expectations for web development initiatives

More Reading

Post navigation

2 Comments

  • Hey would you mind stating which blog platform you’re using?
    I’m going to start my own blog soon but I’m having a hard time making a
    decision between BlogEngine/Wordpress/B2evolution and Drupal.
    The reason I ask is because your layout seems different then most blogs and I’m looking for something
    unique. P.S Sorry for getting off-topic but I had to ask!

Leave a Reply

Your email address will not be published. Required fields are marked *