Change the Billing Field Title in WooCommerce Checkout

You want to change the title of a billing field in WooCommerce checkout on your WordPress site. Maybe “Phone” should read “Mobile number”, or “ZIP Code” should read “Postal code”. Most answers tell you to use woocommerce_checkout_fields. That works for some fields. For others the old label comes back as soon as the customer picks a country, and the My Account → Addresses form never changes at all.

This snippet renames labels in the right places. Billing-only fields like name, phone and email change on checkout and on the edit-address page. Shared address parts like postcode and state keep their new label when WooCommerce’s JavaScript swaps labels for each country.

The snippet

Put it in a small plugin or in your theme’s functions.php. Edit the two label arrays at the top and leave the rest alone.

/**
 * Billing-only labels, keyed by the full checkout field ID.
 */
function dpc_billing_field_labels(): array {
	return [
		'billing_first_name' => __( 'Given name', 'dpc' ),
		'billing_last_name'  => __( 'Family name', 'dpc' ),
		'billing_company'    => __( 'Company or organisation', 'dpc' ),
		'billing_phone'      => __( 'Mobile number', 'dpc' ),
		'billing_email'      => __( 'Email for receipts', 'dpc' ),
	];
}

/**
 * Address-part labels shared by billing and shipping, keyed without prefix.
 */
function dpc_address_field_labels(): array {
	return [
		'postcode' => __( 'Postal code', 'dpc' ),
		'state'    => __( 'Region', 'dpc' ),
	];
}

add_filter( 'woocommerce_billing_fields', 'dpc_rename_billing_fields', 20 );
function dpc_rename_billing_fields( array $fields ): array {
	foreach ( dpc_billing_field_labels() as $key => $label ) {
		if ( isset( $fields[ $key ] ) ) {
			$fields[ $key ]['label'] = $label;
		}
	}
	return $fields;
}

add_filter( 'woocommerce_default_address_fields', 'dpc_rename_address_fields', 20 );
function dpc_rename_address_fields( array $fields ): array {
	foreach ( dpc_address_field_labels() as $key => $label ) {
		if ( isset( $fields[ $key ] ) ) {
			$fields[ $key ]['label'] = $label;
		}
	}
	return $fields;
}

// Country locales (US "ZIP Code", GB "County"…) override the defaults, on page load and in JS.
add_filter( 'woocommerce_get_country_locale', 'dpc_rename_locale_labels', 20 );
function dpc_rename_locale_labels( array $locales ): array {
	$labels = dpc_address_field_labels();
	foreach ( $locales as $country => $fields ) {
		foreach ( $labels as $key => $label ) {
			if ( isset( $fields[ $key ]['label'] ) ) {
				$locales[ $country ][ $key ]['label'] = $label;
			}
		}
	}
	return $locales;
}

How it works

  • woocommerce_billing_fields runs inside WC()->countries->get_address_fields(). The classic checkout and the My Account edit-address form both use that function, so one filter covers both pages. woocommerce_checkout_fields only reaches the checkout.
  • woocommerce_default_address_fields sets the base definition for address parts (postcode, state, city, address lines). Billing and shipping are both built from it, so a postcode renamed here changes in both forms.
  • woocommerce_get_country_locale is why renames often seem not to work. Many countries ship their own label (“ZIP Code” for the US, “County” for the UK). On checkout, address-i18n.js writes those labels back into the form whenever the country changes, which also happens on the first load. The filter replaces a country’s label only where that country defines one, and leaves rules like required and hidden alone.
  • Priority 20 runs after most plugins that hook at the default of 10. If another plugin still wins, list everything attached to the hook with this helper.

Customise it

  • To rename a shipping-only field, copy dpc_rename_billing_fields and hook it to woocommerce_shipping_fields, using keys like shipping_company.
  • Field IDs are the name attributes on the checkout form: billing_country, billing_address_1, billing_city, and so on. Shared parts go in dpc_address_field_labels() without the prefix.
  • To keep a country’s own wording (for example, US customers still see “ZIP Code”), skip that country inside the locale loop with if ( 'US' === $country ) { continue; }.
  • Placeholders work the same way. Set $fields[ $key ]['placeholder'] next to the label.
  • The order edit screen in wp-admin uses its own filter, woocommerce_admin_billing_fields, and its keys have no prefix (phone, company).

Gotchas

  • Checkout block: this snippet is for the classic checkout (the [woocommerce_checkout] shortcode) and My Account. The Checkout block renders its fields in React from its own definitions, so woocommerce_billing_fields does not reach it. To check which one you use, open your checkout page in the editor and see whether it contains a Checkout block. If it does, test there before relying on these filters.
  • WooCommerce prints labels through wp_kses_post(), so simple markup like <abbr> works. Labels are fixed strings here. Never build them from request data.
  • Keep the __() calls with your own text domain if the store is multilingual. The strings can then be translated like any other plugin string.
  • Changing a label does not change the meta key. Orders still store billing_phone, so exports and integrations keep working.

Snippet poll. Should this snippet be in the Scripts Organizer library for one-click import? 10 votes put it there.

0 of 10 votes

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You’ll also get DPlugins product updates. No spam, and you can unsubscribe anytime.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You'll also get DPlugins product updates. No spam, and you can unsubscribe anytime.