WooCommerce – removing country field from my-account page prevents from saving address

Tags: , , ,

I sell and ship products only to one country so I don’t want to display billing_country and shipping_country field to the customers. I removed the fields from both checkout and my-account addresses page using unset($fields['billing_country']).

Checkout works fine, but after I removed those fields from my-account page, I can’t save or edit any addresses on my-account addresses page. The page will simply refresh itself not changing anything.

This is my functions.php inside my theme.

add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );

function custom_override_checkout_fields( $fields ) {
   return $fields;

add_filter( 'woocommerce_billing_fields' , 'custom_override_billing_fields' );

function custom_override_billing_fields( $fields ) {
  return $fields;

add_filter( 'woocommerce_shipping_fields' , 'custom_override_shipping_fields' );
function custom_override_shipping_fields( $fields ) {
  return $fields;

If I comment out unset($fields['billing_country']); or unset($fields['shipping_country']); everything works fine and it saves any addresses. Unsetting other fields also works. Am I doing something wrong, is there any other way to remove those fields? Thanks.



The weirdest thing happened. I made those fields hidden using css and left them set in functions.php. But then, my billing and shipping address classes got messed up!

I had those lines in my woocommerce_billing_fields filter hook:

      $fields['billing_city']['class'] = array('form-row-last');
      $fields['billing_postcode']['class'] = array('form-row-first');
      $fields['billing_email']['class'] = array('form-row-last');
      $fields['billing_phone']['class'] = array('form-row-first');

This is supposed to make those 4 fields to take 50% width of the row in the billing address form. It worked with email and phone, but city and postcode remained 100% width. It should replace form-row-wide class into form-row-first/last and it did so, but only for two.

So I looked into the browser and found out that somehow those two elements had data-o_class attribute.

This is what I found:

<p class="form-row validate-required validate-postcode form-row-wide address-field" 
id="billing_postcode_field" data-priority="65" 
data-o_class="form-row form-row-first validate-required validate-postcode"></p>

Element above is bugged and has this data-o_class attribute which contains all the classes, however, element below is fine and has his classes replaced:

<p class="form-row form-row-first validate-required validate-phone" 

When I removed the country field with unset($fields['billing_country']), the problem disappeared, but again, I couldn’t save the address.

In order to fix it I had to use another filter – woocommerce_default_address_fields – This is what i did in functions.php:

  add_filter( 'woocommerce_default_address_fields','custom_override_default_address_fields' );
  function custom_override_default_address_fields( $fields ){
    return $fields;

What it did is even better!

It made the country fields appear again both in checkout and on my account page, even though it was still unset with other filters there. But it didn’t appear in the right order, it was unstyled and at the end of the form. So once again, I had to remove it using css.

But…. It fixed the classes in my billing and shipping address on my account page! I still don’t know how this got my forms so messed up.


You can get the same result without writing a line of code.

  1. In the WordPress admin panel go to WooCommerce > Settings > General.
  2. In the field Selling location(s) select Sell to specific countries.
  3. In the Sell to specific countries field, enter only the country in which you want to sell.
  4. In the Shipping location(s) field select the option Ship to all countries you sell to.

enter image description here

In this way, on the checkout page and on the address page in your account you will see the Billing country and Shipping country fields as plain text (instead of the list of options).

Customers will not be able to modify them.

If you want to hide it, however, you can intervene with the css code.

Source: stackoverflow