To add a custom field to WordPress registration, render an input in the form your site actually uses, validate it on the server before the account is created, and save the cleaned value as user metadata after successful registration. A registration field does not automatically appear on a later profile screen; profile display and editing are separate integrations.
Understand the WordPress user-data model
Do not add a column to WordPress’s core users table for an extra registration value. Core account fields remain there, while arbitrary additional values belong in the usermeta table. WordPress describes this model in Working with User Metadata.
Choose a stable metadata key, such as company_department, and define its contract before writing code:
- Whether the field is required or optional.
- The accepted format and value type.
- Whether one value or multiple values are stored.
- Who may view or change it.
- Whether it should be exposed through the REST API.
Collect only information that the site needs, particularly when the value could identify or profile a person.
#1 Best Overall
Identify the registration form first
WordPress sites commonly use the core login-page registration, a custom theme template, a membership plugin, WooCommerce, or a custom endpoint. The register_new_user() reference documents the core login-page path. Its hooks should not be assumed to process every third-party form.
| Registration surface | What to verify | Where the field must be handled |
|---|---|---|
| Core WordPress registration | That the site uses the standard login-page registration flow | The form’s rendering extension point, registration_errors for validation, and user_register for post-creation persistence |
| Theme or custom form | Which template or endpoint receives the POST request | That form’s rendering, request validation, and user-creation code |
| Membership, commerce, or profile plugin | The plugin’s documented field and validation hooks | The plugin’s integration API; core hooks may not run |
| REST or other custom endpoint | How the endpoint authenticates and creates users | The endpoint’s schema, authorization, validation, and metadata update logic |
Core registration implementation
The following pattern applies when the site uses WordPress’s core registration flow. Replace the example key and field rules with the contract for your site.
Rank #2
1. Render the input in the actual registration form
Add a labeled input to the form that users submit. The markup must be present in the same request that creates the account; adding a field to an unrelated page will not capture it.
<p>
<label for="company_department">Department<br>
<input
type="text"
name="company_department"
id="company_department"
value="<?php echo esc_attr( wp_unslash( $_POST['company_department'] ?? '' ) ); ?>"
autocomplete="organization-title"
>
</label>
</p>
For the standard login-page form, attach this output through the form extension point provided by the active WordPress version and theme. For a plugin or custom form, use that product’s documented rendering mechanism instead.
Rank #3
2. Validate before account creation
registration_errors filters the WP_Error object before WordPress saves user information. WordPress’s reference says, “This filter can be used to create custom validation rules on user registration.” Return the error object on every path; an error added to it aborts account creation.
add_filter( 'registration_errors', function ( $errors, $sanitized_user_login, $user_email ) {
$value = isset( $_POST['company_department'] )
? sanitize_text_field( wp_unslash( $_POST['company_department'] ) )
: '';
if ( '' === $value ) {
$errors->add(
'company_department_required',
__( '<strong>Error:</strong> Please enter your department.' )
);
} elseif ( mb_strlen( $value ) > 100 ) {
$errors->add(
'company_department_too_long',
__( '<strong>Error:</strong> Your department must be 100 characters or fewer.' )
);
}
return $errors;
}, 10, 3 );
Server-side validation is mandatory even if JavaScript checks the field in the browser. Match the sanitizer to the data: plain text should not be treated as HTML, and an email, URL, number, date, or controlled choice needs rules appropriate to that type.
Rank #4
3. Save the value after successful registration
Use the new user ID to store the cleaned value as metadata only after WordPress has created the account. The user_register action fires immediately after registration and is commonly used for additional metadata passed by custom forms, as documented at the hook reference.
add_action( 'user_register', function ( $user_id ) {
if ( ! isset( $_POST['company_department'] ) ) {
return;
}
$value = sanitize_text_field( wp_unslash( $_POST['company_department'] ) );
if ( '' !== $value ) {
update_user_meta( $user_id, 'company_department', $value );
}
} );
The hook documentation cautions that not all user metadata has necessarily been stored when this action fires. Treat your own field as an explicit update and do not assume every other profile property is already populated.
Free tools Windows power users keep installed
One-click scans. No signup required.
Best Value
Make the field editable on profile screens
Saving a signup value does not create a profile editor. If users or administrators must change it later in wp-admin, output the control and save it on the profile-update workflow. WordPress provides show_user_profile when a user edits their own profile and edit_user_profile when an administrator edits another user.
function itech_department_profile_field( $user ) {
?>
<table class="form-table" role="presentation">
<tr>
<th><label for="company_department">Department</label></th>
<td>
<input type="text" class="regular-text" name="company_department"
id="company_department"
value="<?php echo esc_attr( get_user_meta( $user->ID, 'company_department', true ) ); ?>">
</td>
</tr>
</table>
<?php
}
add_action( 'show_user_profile', 'itech_department_profile_field' );
add_action( 'edit_user_profile', 'itech_department_profile_field' );
function itech_save_department_profile_field( $user_id ) {
if ( ! current_user_can( 'edit_user', $user_id ) ) {
return;
}
if ( ! isset( $_POST['company_department'] ) ) {
return;
}
update_user_meta(
$user_id,
'company_department',
sanitize_text_field( wp_unslash( $_POST['company_department'] ) )
);
}
add_action( 'personal_options_update', 'itech_save_department_profile_field' );
add_action( 'edit_user_profile_update', 'itech_save_department_profile_field' );
For a front-end account page, implement the same authorization, validation, sanitization, and update_user_meta() flow in that page’s handler. Do not require wp-admin access when the site’s users are not meant to have it.
Register metadata and control REST exposure
register_meta( 'user', ... ) documents a metadata value’s type, whether it is single or multiple, sanitization callback, authorization callback, and REST behavior. Registering a value with show_in_rest => true makes it available through the REST API, so enable that only when the exposure is intentional.
register_meta( 'user', 'company_department', array(
'type' => 'string',
'single' => true,
'sanitize_callback' => 'sanitize_text_field',
'auth_callback' => function ( $allowed, $meta_key, $object_id ) {
return current_user_can( 'edit_user', $object_id );
},
'show_in_rest' => false,
) );
If a REST response needs a computed field, custom callbacks, or a bespoke schema rather than a value under a user resource’s meta, use register_rest_field. Keep both read and update authorization deliberately narrow; profile data should not become public or writable merely because an API client requests it.
Recommended Free Tools
Test the complete lifecycle
- Open the exact registration surface used by the site and confirm the field renders with a label and sensible autocomplete/type.
- Submit the form with the field empty, malformed, and over its permitted length. Confirm that the account is not created and a useful error is shown.
- Submit a valid value and confirm that the account is created.
- Inspect the new user’s metadata and verify the stored value is cleaned, not raw request data.
- Open the relevant self-edit and administrator-edit profile screens and confirm the value appears only where intended.
- Edit the value, save the profile, and verify authorization prevents an unauthorized update.
- If REST exposure is enabled, test authenticated and unauthenticated responses and update attempts separately.
- Repeat after switching themes or disabling the registration plugin to ensure you are testing the form that production users actually submit.
Common failure modes
- The field displays but is always blank in metadata: the input name, submitted form, and save handler do not match, or the handler is attached to a different registration flow.
- Invalid values still create accounts: validation is running after creation or its
WP_Errorobject is not returned. Move the rule to the pre-creation integration point. - The value appears at signup but not in wp-admin: persistence and profile rendering are separate features; add the profile hooks.
- A plugin form ignores the code: that form may use its own endpoint and extension API rather than the core registration path.
- Sensitive data appears in REST: disable unintended
show_in_restexposure and review the metadata authorization callback. - The field disappears after a theme change: rendering was placed in a theme template instead of a stable plugin or site-specific integration.
Choosing the right implementation
| Requirement | Recommended approach |
|---|---|
| Capture one value during core signup | Render the core form field, validate with registration_errors, and save on user_register. |
| Let administrators edit it in wp-admin | Add both profile display hooks and both profile-update save hooks. |
| Let users edit it in a front-end account area | Build a protected front-end metadata form with capability checks and server-side validation. |
| Use a membership or commerce registration form | Follow that product’s documented field, validation, and account-profile extension points. |
| Expose the value to an API | Register user meta with an explicit schema and authorization policy, or use register_rest_field for custom callbacks. |
The durable design is the lifecycle, not a particular form: collect the value where signup occurs, reject bad data before user creation, store it as user metadata after creation, and implement later editing or API exposure as separate, permission-checked features.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

