Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save damiencarbery/58532ac9c4e0b87012fca2f84f80b56f to your computer and use it in GitHub Desktop.
Save damiencarbery/58532ac9c4e0b87012fca2f84f80b56f to your computer and use it in GitHub Desktop.
Add fields to WooCommerce Checkout block - Experiments using WooCommerce API to add fields to the Checkout block. https://www.damiencarbery.com/2025/06/add-fields-to-woocommerce-checkout-block/
<?php
// This code is for a checkbox in the Order Information area.
add_action( 'woocommerce_init', 'cbt_add_newsletter_checkbox' );
function cbt_add_newsletter_checkbox() {
woocommerce_register_additional_checkout_field(
array(
'id' => 'namespace/marketing-opt-in',
'label' => 'Do you want to subscribe to our newsletter?',
'location' => 'order',
'type' => 'checkbox',
// If the checkbox is required the error_message will be displayed if it is not checked.
'required' => true,
'error_message' => 'Please subscribe, it will be great.'
)
);
}
<?php
// This code is for a dropdown in the Order Information area.
add_action( 'woocommerce_init', 'cbt_add_how_found_dropdown' );
function cbt_add_how_found_dropdown() {
woocommerce_register_additional_checkout_field(
array(
'id' => 'namespace/how-did-you-hear-about-us',
'label' => 'How did you hear about us?',
'location' => 'order',
'required' => true,
'placeholder' => 'Select a source',
'attributes' => array(
'title' => 'Please tell us how you heard about us.',
),
'type' => 'select',
'options' => [
[
'value' => 'google',
'label' => 'Google'
],
[
'value' => 'facebook',
'label' => 'Facebook'
],
[
'value' => 'friend',
'label' => 'From a friend'
],
[
'value' => 'other',
'label' => 'Other'
],
],
)
);
}
<?php
// This code is for a text field in the Address Information area.
// It is added to both the Billing and Shipping areas.
// In this example the 'pattern' attribute is checked when the field loses focus. This will prevent submitting the order.
// The validation callback is used after the Place Order button is clicked.
// Its check conflicts with the pattern one so it will return an error and you'll be stuck in an infinite loop.
// This is obviously a pointless example but it's just a demo of the validation options available.
add_action( 'woocommerce_init', 'cbt_add_personal_id_address_field' );
function cbt_add_personal_id_address_field() {
woocommerce_register_additional_checkout_field(
array(
// id, label and location are required.
'id' => 'namespace/personal-id',
'label' => 'Personal ID', // Label when field is required.
'location' => 'address', // order, address, contact. For address it will show in Shipping *and* Billing sections.
'type' => 'text', //'text', 'select', 'checkbox'; default is text.
'required' => false,
'optionalLabel' => 'Personal ID (totally optional)', // Can specify a different label when field is optional.
'attributes' => array(
'maxLength' => 5,
'readOnly' => false,
'pattern' => 'AA[A-Z0-9]{3}', // Value will be tested when field loses focus.
'title' => 'Enter an ID that begins with AA and has 5 characters.',
),
'validate_callback' => 'cbt_personal_id_validation_callback',
//'sanitize_callback' => 'cbt_personal_id_sanitization_callback', // Optional function to santize field value.
),
);
}
// Validate the Personal ID field and return a message on error.
// This will always return an error because the regex pattern is different from the one defined in the field settings.
function cbt_personal_id_validation_callback( $value, $field ) {
if ( ! preg_match( '/^BB[A-Z0-9]{3}$/', $value ) ) {
// Use different label if field is not required.
$field_name = $field['required'] ? $field['label'] : $field['optionalLabel'];
return new WP_Error( 'invalid_personal_id_value', sprintf( 'The format for &quot;%s&quot; field is BB[A-Z0-9]{3}.', $field_name ) );
}
}
<?php
// This code is for a text field in the Contact Information area.
add_action( 'woocommerce_init', 'cbt_add_second_email_contact_field' );
function cbt_add_second_email_contact_field() {
woocommerce_register_additional_checkout_field(
array(
// id, label and location are required.
'id' => 'namespace/second-email',
'label' => 'Second email', // Label when field is required.
'location' => 'contact', // order, address, contact. For address it will show in Shipping *and* Billing sections.
'required' => true,
'optionalLabel' => 'Second email (totally optional)', // Can specify a different label when field is optional.
'type' => 'text',
'attributes' => array(
'title' => 'Enter your second email address, just for fun.',
// To help users on mobile devices you can turn on autocomplete assistance and autocapitalisation.
//'autocomplete' => 'given-name', // email, given-name, family-name, country, organization, address-line1, address-line2, address-level1, address-level2, postal-code, tel. https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete#values
//'autocapitalize' => 'on', // off, on, none, sentences, words, characters. This only applies on mobile devices.
// The aria attributes can be used for accessibility.
//'aria-describedby' => 'some-element', // Accessibility setting.
//'aria-label' => 'custom aria label', // Accessibility setting.
// The custom data can be added for JavaScript use.
//'data-custom' => 'custom data', // Custom attribute for custom JS use.
),
'validate_callback' => 'cbt_second_email_validation_callback',
//'sanitize_callback' => 'cbt_second_email_sanitization_callback', // Optional function to santize field value.
),
);
}
// Validate the Second email field to ensure it is an email address and return a message on error.
function cbt_second_email_validation_callback( $value, $field ) {
if ( ! is_email( $value ) ) {
// Use different label if field is not required.
$field_name = $field['required'] ? $field['label'] : $field['optionalLabel'];
return new WP_Error( 'invalid_second_email', sprintf( 'The &quot;%s&quot; field must be an email address.', $field_name ) );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment