How to Add Custom Fields to Woocommerce Registration Form

Add custom fields to WooCommerce new account Page

The following will optimize and compact your code, adding field validation and allowing to save all fields values as user meta data:

// Custom function with all extra field data arrays
function extra_register_fields() {
$text_domain = 'woocommerce';
return array(
'first_name' => array('type' => 'text', 'class' => ['form-row-first'], 'required' => 1, 'label' => __('First name', $text_domain) ),
'last_name' => array('type' => 'text', 'class' => ['form-row-last'], 'required' => 1, 'label' => __('Last name', $text_domain) ),
'phone' => array('type' => 'tel', 'class' => ['form-row-wide'], 'required' => 1, 'label' => __( 'Phone', $text_domain ) ),
'facebook' => array('type' => 'text', 'class' => ['form-row-wide'], 'required' => 1, 'label' => __( 'Facebook ', $text_domain ) ),
'whatsapp' => array('type' => 'text', 'class' => ['form-row-wide'], 'required' => 1, 'label' => __( 'WhatsApp', $text_domain ) ),
'country' => array('type' => 'country', 'class' => ['address-field'], 'required' => 1, 'label' => __( 'Country', $text_domain ) ),
'state' => array('type' => 'state', 'class' => ['address-field'], 'required' => 1, 'label' => __( 'State', $text_domain ) ),
);
}

// Add extra register fields
add_action( 'woocommerce_register_form_start', 'wooc_extra_register_fields' );
function wooc_extra_register_fields() {
foreach ( extra_register_fields() as $fkey => $values ) {
if( $fkey === 'phone' ) $values['clear'] = 1;
if( $fkey === 'state' ) $values['validate'] = ['state'];

$value = isset($_POST['billing_'.$fkey]) ? esc_attr($_POST['billing_'.$fkey]) : '';

woocommerce_form_field( 'billing_'.$fkey, $values, $value );
}
wp_enqueue_script('wc-country-select', get_site_url().'/wp-content/plugins/woocommerce/assets/js/frontend/country-select.min.js', array('jquery'), true);
}

// Extra register fields validation
add_action( 'woocommerce_register_post', 'wc_validate_reg_form_fields', 10, 3 );
function wc_validate_reg_form_fields( $username, $email, $validation_errors ) {
foreach ( extra_register_fields() as $fkey => $values ) {
if (isset($_POST['billing_'.$fkey]) && empty($_POST['billing_'.$fkey]) && $values['required'] ) {
$validation_errors->add( 'extra_fields', sprintf('%s is a required field', $values['label']) );
}
}
return $validation_errors;
}

// Save extra register fields values
add_action( 'woocommerce_created_customer', 'wooc_save_extra_register_fields' );
function wooc_save_extra_register_fields( $customer_id ) {
foreach( extra_register_fields() as $fkey => $values ) {
if ( isset($_POST['billing_'.$fkey]) ) {
$value = in_array($fkey, ['country', 'state']) ? sanitize_text_field($_POST['billing_'.$fkey]) : esc_attr($_POST['billing_'.$fkey]);

update_user_meta( $customer_id, 'billing_'.$fkey, $value );

if ( in_array($fkey, ['first_name', 'last_name']) )
update_user_meta( $customer_id, $fkey, $value );
}
}
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.


To display "Facebook" and "WhatsApp" fields in My account edit billing address use the following:

// Display Facebook and WhatsApp fields in My account eddit billing address
add_filter( 'woocommerce_billing_fields', 'additional_billing_fields', 20, 1 );
function additional_billing_fields($billing_fields) {
if ( is_wc_endpoint_url( 'edit-address' ) ) {
foreach ( extra_register_fields() as $fkey => $values ) {
if ( in_array($fkey, ['facebook', 'whatsapp']) ) {
$billing_fields['billing_'.$fkey] = $values;
}
}
}
return $billing_fields;
}

To add "Facebook" and "WhatsApp" fields to Admin user billing section use the following:

// WordPress User: Add Facebook and WhatsApp fields to billing section
add_filter('woocommerce_customer_meta_fields', 'wordpress_user_account_billing_birthdate_field');
function wordpress_user_account_billing_birthdate_field( $fields ) {
foreach ( extra_register_fields() as $fkey => $values ) {
if ( in_array($fkey, ['facebook', 'whatsapp']) ) {
$fields['billing']['fields']['billing_'.$fkey] = array(
'label' => $values['label'],
'description' => ''
);
}
}
return $fields;
}

Add a field to Woocommerce registration form and in admin edit user

The following will add a "billing account number" field in customer registration as a required field (validation) and will also display it:

  • In My account > Edit account section
  • In Admin User edit pages on billing fields section

The code:

// Display a field in Registration / Edit account
add_action( 'woocommerce_register_form_start', 'display_account_registration_field' );
add_action( 'woocommerce_edit_account_form_start', 'display_account_registration_field' );
function display_account_registration_field() {
$user = wp_get_current_user();
$value = isset($_POST['billing_account_number']) ? esc_attr($_POST['billing_account_number']) : $user->billing_account_number;
?>
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="reg_billing_account_number"><?php _e( 'Ship to/ Account number', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" maxlength="6" class="input-text" name="billing_account_number" id="reg_billing_account_number" value="<?php echo $value ?>" />
</p>
<div class="clear"></div>
<?php
}

// registration Field validation
add_filter( 'woocommerce_registration_errors', 'account_registration_field_validation', 10, 3 );
function account_registration_field_validation( $errors, $username, $email ) {
if ( isset( $_POST['billing_account_number'] ) && empty( $_POST['billing_account_number'] ) ) {
$errors->add( 'billing_account_number_error', __( '<strong>Error</strong>: account number is required!', 'woocommerce' ) );
}
return $errors;
}

// Save registration Field value
add_action( 'woocommerce_created_customer', 'save_account_registration_field' );
function save_account_registration_field( $customer_id ) {
if ( isset( $_POST['billing_account_number'] ) ) {
update_user_meta( $customer_id, 'billing_account_number', sanitize_text_field( $_POST['billing_account_number'] ) );
}
}

// Save Field value in Edit account
add_action( 'woocommerce_save_account_details', 'save_my_account_billing_account_number', 10, 1 );
function save_my_account_billing_account_number( $user_id ) {
if( isset( $_POST['billing_account_number'] ) )
update_user_meta( $user_id, 'billing_account_number', sanitize_text_field( $_POST['billing_account_number'] ) );
}

// Display field in admin user billing fields section
add_filter( 'woocommerce_customer_meta_fields', 'admin_user_custom_billing_field', 10, 1 );
function admin_user_custom_billing_field( $args ) {
$args['billing']['fields']['billing_account_number'] = array(
'label' => __( 'Ship to/ Account number', 'woocommerce' ),
'description' => '',
'custom_attributes' => array('maxlength' => 6),
);
return $args;
}

Code goes in function.php file of your active child theme (active theme). Tested and works.

Sample Image

Add custom WooCommerce registration fields to admin WordPress user contact fields

To display the field between the contact information you can use the user_contactmethods filter hook opposite edit_user_profile

You just need to make sure the user meta key matches

/**
* Filters the user contact methods.
*
* @since 2.9.0
*
* @param string[] $methods Array of contact method labels keyed by contact method.
* @param WP_User $user WP_User object.
*/
function filter_user_contactmethods( $methods, $user ) {
// Add user contact methods
$methods['customer_dob'] = __( 'Date of Birth', 'your-theme-slug' );

return $methods;
}
add_filter( 'user_contactmethods', 'filter_user_contactmethods', 10, 2 );

Adding extra fields to the woocommerce form in wordpress

I cannot add comments yet so I'm adding a question here and making my best shot at answering at the same time.. Will edit if needed.

1st of all,
Just for debugging purposes to make sure I'm on the right track, I'm guessing these fields also do not auto populate on the My Account page either, right?

I see you're doing a text field for the country and state. You need the use the built in WooCommerce's Country and State field types so the values stored can be mapped to the selects options and thus auto select the proper option.

Try this:

  1. Add this at the top of your misha_add_register_form_field function, to get the countries list from WC.
$countries_obj = new WC_Countries();
$countries = $countries_obj->__get('countries');

  1. Then, to show these fields in the form replace the country and state fields in your misha_add_register_form_field() function with these:
woocommerce_form_field(
'billing_country',
array(
'type' => 'country',
'label' => 'Country',
'required' => 1,
'class' => ['address-field']
),
''
);

woocommerce_form_field(
'billing_state',
array(
'type' => 'state',
'label' => 'State',
'required' => 1,
'class' => ['address-field'],
'validate' => ['state']
),
''
);

You'll need to update the validations and sanitizers for those 2 fields, and maybe do a some extra work to make sure it's updated properly.
You can reference Using the WooCommerce API to get the country/state lists and Add Billing Address to Woocommerce Registration Page as they seem to address the same challenge.

WooCommerce - Custom User Registration Fields

1 You can use this plugin for display your custom fields in the admin view.

2 In your template HTML file, find the form, and use the default id & name tag : "Firstname" / "Lastname" ...ext

Add Custom registration fields in WooCommerce and phone field validation issue

Note: Your special registration form located in the footer is something different than WooCommerce checkout fields.

In your code the hook for your validating function text_domain_woo_validate_reg_form_fields() is just missing. There is also some small errors (corrected)

The best place to check the submitted data is your validation function and you should also need to add another one for checkout too (instead of using a custom pattern for checkout phone field, that is used to format data).

So all your related code should be:

## --- FOR CHECKOUT --- ##

// Checkout billing phone validation (Checking length)
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
if ( $_POST['billing_phone'] && strlen($_POST['billing_phone']) < 10 )
wc_add_notice( __('Please type a correct phone number…', 'woocommerce'), 'error' );
}

## --- FOR CUSTOM REGISTRATION FORM --- ##

// Add custom fields to registration form.
add_action('woocommerce_register_form_start', 'text_domain_woo_reg_form_fields');
function text_domain_woo_reg_form_fields() {
?>
<div class="formumuz" style="display:flex;">
<p class="form-row form-row-first">
<label style="display:none!important;" for="billing_first_name"><?php _e('First name', 'woocommerce'); ?><span class="required">*</span></label>
<input style="width: 130px; display: inline-block; margin-right:1px;" type="text" class="woocommerce-Input woocommerce-Input--text input-text placeholder" placeholder="İsim / Name *" type="text" class="input-text" name="billing_first_name" id="billing_first_name" value="<?php if (!empty($_POST['billing_first_name'])) esc_attr_e($_POST['billing_first_name']); ?>" />
</p>
<p class="form-row form-row-last">
<label style="display:none!important;" for="billing_last_name"><?php _e('Last name', 'woocommerce'); ?><span class="required">*</span></label>
<input style="width: 130px; display: inline-block; margin-left:1px;" type="text" class="woocommerce-Input woocommerce-Input--text input-text placeholder" placeholder="Soyisim / Surname *" type="text" class="input-text" name="billing_last_name" id="billing_last_name" value="<?php if (!empty($_POST['billing_last_name'])) esc_attr_e($_POST['billing_last_name']); ?>" />
</p>
</div>
<p style="margin-bottom: 0px; margin-top: 10px;" class="form-row form-row-wide">
<label style="display:none!important;" for="reg_billing_phone"><?php _e( 'Phone', 'woocommerce' ); ?></label>

<!-- "You can’t have 2 times the value attribute and you can use "tel" type … (to be removed)" -->
<input style="width:254px!important;" type="tel" class="woocommerce-Input woocommerce-Input--text input-text placeholder" placeholder="Cep Telefonu / Mobile *" name="billing_phone" id="reg_billing_phone" value="<?php esc_attr_e( $_POST['billing_phone'] ); ?>" /> *
</p><br>
<div class="clear"></div>
<?php
}

// Checking & validation of custom fields in registration form.
add_action('woocommerce_register_post', 'text_domain_woo_validate_reg_form_fields', 10, 3);
function text_domain_woo_validate_reg_form_fields( $username, $email, $validation_errors ) {
if (isset($_POST['billing_first_name']) && empty($_POST['billing_first_name'])) {
$validation_errors->add('billing_first_name_error', __('İsim alanı zorunludur! / Name field is required!', 'woocommerce'));
}
if (isset($_POST['billing_last_name']) && empty($_POST['billing_last_name'])) {
$validation_errors->add('billing_last_name_error', __('Soyisim alanı zorunludur! / Surname field is required!', 'woocommerce'));
}
if (isset($_POST['billing_phone']) && empty($_POST['billing_phone'])) {
$validation_errors->add('billing_phone_error', __('Telefon alanı zorunludur! / Phone field is required!', 'woocommerce'));
}

// ==> CHECKING PHONE LENGTH (10 character minimal) <==
if (isset($_POST['billing_phone']) && strlen($_POST['billing_phone']) < 10 ) {
$validation_errors->add('billing_phone_error', __('Please type a correct phone number…', 'woocommerce'));
}
return $validation_errors;
}

// Add custom fields to registration form.
add_action( 'woocommerce_created_customer', 'custom_save_extra_register_fields' ); // <==== Missing
function custom_save_extra_register_fields($customer_id) {
//First name field
if (isset($_POST['billing_first_name'])) {
update_user_meta($customer_id, 'first_name', sanitize_text_field($_POST['billing_first_name']));
update_user_meta($customer_id, 'billing_first_name', sanitize_text_field($_POST['billing_first_name']));
}
//Last name field
if (isset($_POST['billing_last_name'])) {
update_user_meta($customer_id, 'last_name', sanitize_text_field($_POST['billing_last_name']));
update_user_meta($customer_id, 'billing_last_name', sanitize_text_field($_POST['billing_last_name']));
}
//Phone field
if (isset($_POST['billing_phone'])) {
update_user_meta($customer_id, 'phone', sanitize_text_field($_POST['billing_phone']));
update_user_meta($customer_id, 'billing_phone', sanitize_text_field($_POST['billing_phone']));
}
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

Tested and works

Each time the phone number minimal length will be checked and display this alert (if needed):

Sample Image

Provide custom registration fields in Woocommerce edit profile My account page

You may try this example,

add_action( 'woocommerce_edit_account_form', 'my_woocommerce_edit_account_form' );
add_action( 'woocommerce_save_account_details', 'my_woocommerce_save_account_details' );

function my_woocommerce_edit_account_form() {

$user_id = get_current_user_id();
$user = get_userdata( $user_id );

if ( !$user )
return;

$twitter = get_user_meta( $user_id, 'twitter', true );
$url = $user->user_url;

?>

<fieldset>
<legend>Social information</legend>
<p>Fill in this information about your social media accounts.</p>
<p class="form-row form-row-thirds">
<label for="twitter">Twitter Username:</label>
<input type="text" name="twitter" value="<?php echo esc_attr( $twitter ); ?>" class="input-text" />
</p>
</fieldset>

<fieldset>
<legend>Additional Information</legend>
<p class="form-row form-row-thirds">
<label for="url">Website:</label>
<input type="text" name="url" value="<?php echo esc_attr( $url ); ?>" class="input-text" />
</p>
</fieldset>

<?php
}

function my_woocommerce_save_account_details( $user_id ) {

update_user_meta( $user_id, 'twitter', htmlentities( $_POST[ 'twitter' ] ) );

$user = wp_update_user( array( 'ID' => $user_id, 'user_url' => esc_url( $_POST[ 'url' ] ) ) );

}

For more information,

  • Custom User Fields on Woocommerce My Account Page
  • Custom WooCommerce User Account Fields
  • add user custom field in My Account page in Woocommerce?

Hope this will helps you.



Related Topics



Leave a reply



Submit