WooCommerce: Hide Checkout Fields if Virtual Product @ Cart

If you sell downloadable/virtual products and need to simplify your WooCommerce checkout when such product type is in the Cart, you’ve come to the right place!

Here’s a simple snippet, as well as a handy mini-plugin, that checks if there are only “virtual” products in the Cart and hides all the billing fields and order notes (except name and email).

The mini-plugin also allows you to enable this for free virtual orders only, and to move the relevant billing fields under a toggle instead of removing them all together.

Enjoy!

Simplify the WooCommerce checkout by removing billing fields if cart contains virtual products

1) PHP Snippet: Remove Billing Fields if Cart Contains Virtual Products @ WooCommerce Checkout

/**
 * @snippet       Hide Fields if Virtual @ WooCommerce Checkout
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 8
 * @donate $9     https://businessbloomer.com/bloomer-armada/
 */

add_filter( 'woocommerce_checkout_fields', 'bbloomer_simplify_checkout_virtual' );
 
function bbloomer_simplify_checkout_virtual( $fields ) {
   $only_virtual = true;
   foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
      // Check if there are non-virtual products
      if ( ! $cart_item['data']->is_virtual() ) $only_virtual = false;
   }
   if ( $only_virtual ) {
      unset($fields['billing']['billing_company']);
      unset($fields['billing']['billing_address_1']);
      unset($fields['billing']['billing_address_2']);
      unset($fields['billing']['billing_city']);
      unset($fields['billing']['billing_postcode']);
      unset($fields['billing']['billing_country']);
      unset($fields['billing']['billing_state']);
      unset($fields['billing']['billing_phone']);
      add_filter( 'woocommerce_enable_order_notes_field', '__return_false' );
   }
   return $fields;
}

2) Mini-Plugin: Business Bloomer WooCommerce Hide Checkout Fields For Virtual Products

You don’t feel confident with coding? You don’t want to purchase yet another bloated, expensive plugin? Great!

Business Bloomer WooCommerce Hide Checkout Fields For Virtual Products Mini-Plugin comes without the usual WordPress plugin hassles. One feature. Lifetime license. No annoying subscriptions. 1 plugin file. A few lines of code. No banners. No up-sells. No WordPress notifications. Use it on as many websites as you like. Lifetime support. 1-page documentation. Super simple settings.

Speaking of which, here’s a screenshot of the settings:

Quick demo:

As you can see the plugin is straight forward. Install it, decide when to enable the functionality, hide or move the relevant billing fields and save. Simple!

Where to add custom code?

You should place PHP snippets at the bottom of your child theme functions.php file and CSS at the bottom of its style.css file. Make sure you know what you are doing when editing such files - if you need more guidance, please take a look at my guide "Should I Add Custom Code Via WP Editor, FTP or Code Snippets?" and my video tutorial "Where to Place WooCommerce Customization?"

Does this snippet (still) work?

Please let me know in the comments if everything went as expected. I would be happy to revise the snippet if you report otherwise (please provide screenshots). I have tested this code with Storefront theme, the WooCommerce version listed above and a WordPress-friendly hosting.

If you think this code saved you time & money, feel free to join 17,000+ WooCommerce Weekly subscribers for blog post updates and 250+ Business Bloomer supporters for 365 days of WooCommerce benefits. Thank you in advance!

Need Help with WooCommerce?

Check out these free video tutorials. You can learn how to customize WooCommerce without unnecessary plugins, how to properly configure the WooCommerce plugin settings and even how to master WooCommerce troubleshooting in case of a bug!

Rodolfo Melogli

Business Bloomer Founder

Author, WooCommerce expert and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. His goal is to help entrepreneurs and developers overcome their WooCommerce nightmares. Rodolfo loves travelling, chasing tennis & soccer balls and, of course, wood fired oven pizza.

101 thoughts on “WooCommerce: Hide Checkout Fields if Virtual Product @ Cart

  1. I’ve used this many times but for some reason on a new website I’m working on it’s not working. Can you confirm it’s working on the latest Woo version (7.6.1)?

    Thank you

  2. Hi

    Very nice snippet, but it does not work together with “WC – APG SMS Notifications” https://wordpress.org/plugins/woocommerce-apg-sms-notifications/.

    They use “apply_filters( ‘woocommerce_checkout_fields’, …” and It does not like we use “add_filter( ‘woocommerce_checkout_fields’, …”.

    I need to use that plugin it is a very nice solution for sending SMS’s. I don’t know enough to compatabilize the two expressions.

    Thanks. Anyway I have to say your site is my reference!

    1. Did you talk to the plugin support? I suppose they should fix that

      1. Hi

        Yes I talk to them, but really there was a PHP error, once I noticed I was able to fix it, very simple:

         if ( is_null( WC()->cart ) ) wc_load_cart(); 

        I inserted the above the above line just before the for loop. Fixed!

        Thanks
        Alain

  3. The code works but then my payment method overrides it saying ‘There are no available payment methods per state’

    1. Oeh! Removed the Country line. So left it in for the checkout page and now payments go through again. So I now have the following on checkout:
      – First Name
      – Last Name
      – Country
      – E-mailadres

      So happy person again. Even if it needs to chow the country.

  4. Great!
    Just one thing – now when I have a non-virtual product in the cart the unset fields get a text of “undefined” as default:

    https://snipboard.io/eWmQSA.jpg

    1. Unset fields should not be visible… so you have some other sort of error

      1. Hi,
        I have the same problem.
        To see the error:
        I first add a virtual product to the basket, then I click on the validation button to land on the checkout page;
        I come back to the shop (for exemple by first clicking on the site logo…)
        I then add a physical product (for which the address fields are of course required for shipping) to the cart;
        On the basket and on checkout page, the text “undefined” appears in the address fields (in any case with the plugin Colissimo shipping methods for WooCommerce; otherwise it appears on the checkout page).
        This error occurs since woocommerce version 7.5.0. Downgrading to 7.4.1 everything works fine.
        I specify that I have also tested different plugins for editing order fields, and the problem is exactlty the same.
        So I think there is a compatibility issue with woocommerce version 7.5.

        1. Must be a WooCommerce bug, never seen that before honestly

          1. Hi,
            Thank you for your reply.
            I reported it to woocommerce… who tell me that it’s a code problem, and therefore to see this with the developers concerned ( https://wordpress.org/support/topic/undefined-text-on/#post-16602971).
            The same problem occurs with different checkout field editor plugins that I tested…
            To date, no one is able to provide a solution.
            Anyway, I’m stuck with this issue…

            1. They actually changed their mind 3 days ago and created a GitHub bug report, so they will fix it (sooner or later). Keep us posted!

              1. Hi,
                For information, the problem is solved with version 7.6.1 of woocommerce.

  5. Works perfectly and I really like it, but it crashes the system when I go to ‘customise’ in Appearance. At this stage I have to delete it from php in order to make other changes on the site, then reinstall the code. Can’t figure out the clash issue.

    1. Dan, thanks so much for your comment! I just retested this on the latest version of WooCommerce and it still works. Unfortunately this looks like custom troubleshooting work and I cannot help here via the blog comments. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding! ~R

  6. this is wrong.

    Why you dont put break in this line:

    if ( ! $cart_item['data']->is_virtual() ) $only_virtual = false;

    So if the current item is not virtual, it will be marked as false. Then if the last item is virtual, it will be marked as true again

    Everyone use the wrong code until now? why nobody notice it for 4years?

    1. Code is not wrong and works perfectly 🙂 Anyone is free to improve it, so if you have a faster/better snippet feel free to share it!

  7. Found the error, the tip suggest for the user DingoDaisy

    add_filter( ‘woocommerce_enable_order_comments_field’, ‘__return_false’ );

    Does not work on the PHP8 Version instead use this

     add_filter( 'woocommerce_enable_order_notes_field', '__return_true' );
    1. Great, glad that helped

  8. Hi. This snippet was working perfectly, I update my PHP version to 8.1 and now I get a critical error.

  9. Now is Oct 2022, my Woo is 6.9.4, WP is 6.0.2, Theme is Twenty Twenty-Two, the billing fields are hided but checkout still validate them, I got “Error processing checkout. Please try again.” when I enable this snippet.

    1. Can you disable all other plugins except WooCommerce? Because on latest Woo + WP + Storefront theme works perfectly

  10. It works! Although I wanna keep the comment field in the check out. What do I need to change in the code, to keep that field?

    1. Found the solution myself. Just changes this line:

      add_filter( ‘woocommerce_enable_order_notes_field’, ‘__return_false’ );

      to this:

      add_filter( ‘woocommerce_enable_order_comments_field’, ‘__return_false’ );

  11. Hey Rodolfo,

    This still works with WooCommerce 5.9.0 and Divi 4.14.1. I used a modified version of it to check whether only a product with a specific ID – in this use case, a café reservation – is in the cart. Sharing it below in case it’s useful to anyone. 🙂

    // Remove billing fields from checkout when café product is in the cart 
    function cln_simplify_checkout_cafe( $fields ) {
    
    	// Set variable to true
    	$only_cafe = true;
    	
    	// Loop through the cart
    	foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
    
    		// Check for products that do NOT match the ID of the café reservations product
    		// If a product like that is found, set the variable to false
    		if ( $cart_item['product_id'] !== 31 ) $only_cafe = false; 
    	
    	}
    	
    	// Check if variable is set to true
    	if( $only_cafe ) {
    		
    		// Unset billing fields
    		unset($fields['billing']['billing_company']);
    		unset($fields['billing']['billing_address_1']);
    		unset($fields['billing']['billing_address_2']);
    		unset($fields['billing']['billing_city']);
    		unset($fields['billing']['billing_postcode']);
    		unset($fields['billing']['billing_country']);
    		unset($fields['billing']['billing_state']);
    		unset($fields['billing']['billing_phone']);
    		add_filter( 'woocommerce_enable_order_notes_field', '__return_false' ); 
    	
    	}
    	
    	// Return the checkout fields
    	return $fields; 
    
    }
    
    add_filter( 'woocommerce_checkout_fields' , 'cln_simplify_checkout_cafe' );
  12. Thank you so much, Rodolfo Melogli.

    You are a genius and businessbloomer.com is now my go-to website for all WooCommerce related snippets. They all work like a charm.

    Keep doing the good work.

    Regards,
    Manju

  13. I added the above snippet but doesn’t work, it always prompts “Something went wrong. Please try again or choose another payment source.” but there is no error find from error_log

    My Woo is Version 5.7.1, is my Woo version not compatible with this snippet?

    1. Worked for me on latest WooCommerce, so it must be a conflict with your theme or another plugin

  14. I love stuff that actually works! Used two of your snippets. No trouble at all. Awesome sauce! Thanks!!

  15. It just works, brilliant

  16. Hi,
    Will this work with WooCommerce Blocks (a plugin by Automattic, makers of WC, that gives more options for the checkout format)?
    I have not gotten it to work yet, and wondering if that is the reason.

    1. Not sure, haven’t tested it yet. Let me know

  17. Hi, how about base on product category? My woocommerce is integrated with Learndash. And I want to hide the billing details if course product data is selected.

  18. Still working great in 2021!!

    1. Great!

  19. what happened if the user selected a physical product with a digital product.
    is this gonna show the billing address field in that case?

    1. Yes in case of a “mixed cart” the code won’t trigger so you get the default checkout

  20. Thanks for publishing this, worked perfectly.

    1. Great!

  21. It works perfectly — you da best! 😉

    1. Yeah!

      1. Awesome, exactly what I was looking! Pretty stupid they don’t have this implemented on default.

  22. how to remove billing address for the second time if the user logins with first time account created

    1. Anand, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  23. Thank You. It works for me

    1. Nice!

  24. Still works, thank you

    1. Excellent!

  25. Thanks very much, this worked with my GreenMart theme

    1. Great!

  26. Yes! Yes! yes yes yes yeses yes!
    Thank you! Worked like a charm!!

    1. Eheh glad it helped

  27. The code works,
    However, when I check-out, the transaction goes through but does not redirect the page.

    1. Code works,
      However it hangs on the checkout page. Transaction still goes through and order shows up in the account, but there is no redirect nor does the cart get emptied after the order

      1. Andreas, thanks for your comment! I just tested this again with Storefront theme and it works perfectly. Maybe your theme (or another plugin) is messing/conflicting with my snippet.

        To troubleshoot, disable all plugins but WooCommerce and also switch temporarily to “Twentytwenty” theme (load the snippet there in functions.php) – does it work? If yes, you have a problem with your current theme or one of the plugins.

        Hope this helps!

        R

  28. Hi,
    In Peru we need Departamento, Provincia and Distrito to bill our customers.
    We sell a virtual product (gift card) and have a special field created for District: ‘billing_gowoo_place’. This field disappears when buying a virtual product.
    How can I force it to appear?

    1. Hi Samir, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  29. Hello

    I’m selling virtual product, is it possible if a customer choose pay by bitcoin gateway, hide all Billing Fields only show email field. On the other hand if choose pay by credit card or Paypal, show all billing fields? (Default show all)

    1. Hello, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  30. Works like a charm!

    1. Thanks!

  31. No luck yet, let me try again

  32. Beautiful, thank you – and unbelievable that Woo displays shipping address fields for virtual products. I can’t think of a use case for that, unless someone wants to harvest addresses.

    1. True!

  33. thanks a lot man .. its magic.

    1. Great!

  34. I love it! Thank you!

    1. Yay!

  35. This is brilliant, thank you!

    How would you also remove the ‘ship to different address’ tick box?

    Thanks

    1. Hi Adam – I guess you’re talking about “mixed” carts, where you have virtual and non-virtual products at the same time? Because if you only have virtual ones the shipping form won’t display at all. Let me know

  36. How would I change this if I wanted to remove billing fields on free products?

    1. Hi Pat, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  37. This code works perfectly.

    We are only selling downloadable virtual products and I think hiding the billing fields is a good idea. However, the question arises whether these fields are needed for credit/debit card payment methods. We plan to use Stripe and PayPal, but have only tested in test mode and not in live or production mode. Since this is our first time using WooCommerce, we would like to know, before we go live, whether we can use this snippet.

    Thanks

    1. Technically if it works on test mode it should work on live mode. However, I recommend you enable this snippet on your live site and immediately do a real test purchase. After that, based on your results, you can leave the snippet there or you can remove it. Hope this helps

  38. thank you! You’re awesome for sharing the code.

    1. Cheers!

  39. This is Awesome function. Thank you! And yes it still works

    1. Great!

  40. Thanks the code work only if I am logged in doesn’t work if not logged in then it ask to login to the account first to checkout.

    1. Thanks for your comment Nidhi. It works for me, so please test with a different theme / no plugins to see if it works

  41. I don’t have a child theme. I put my code in the parent’s theme’s “functions.php”. I put the code at the end of the file. But after saving and refreshing, my site doesn’t display anything. It just keeps on loading

    1. Hey Himanshu, thanks for your comment! Try using https://wordpress.org/plugins/code-snippets/ instead

  42. Hi Rodolfo
    Nice piece of code, simple and easy 😉
    How would I change your snippet, if there was a physical product in the cart as well, to exclude the cost of the virtual product from the subtotal, to allow free shipping, but still take the total through to checkout?
    I’m hoping this is something really simple to do but cannot figure it out.
    Cheers

  43. Hi, found your code and tested it, still can be use. Thank you very much. Really appreciated it.

    1. Awesome 🙂

  44. Hey,

    i am new to your page and I am very thankful for your content. I looked through your checkout page tips and I cant find how you put the “My Order” table on the right side? My order and payment options are under the billing details, how can I make them so beautiful like yours? thank you

    1. Hello Serhat! I get that checkout layout thanks to my theme, Storefront. Otherwise you can use simple CSS to make a 2-columns checkout layout. Hope this helps!

  45. Sweet Code Rodolofo. Thank you, works a charm.

    1. Great 🙂

Questions? Feedback? Support? Leave your Comment Now!
_____

If you are writing code, please wrap it between shortcodes: [php]code_here[/php]. Failure to complying with this (as well as going off topic, not writing in English, etc.) will result in comment deletion. You should expect a reply in about 2 weeks - this is a popular blog but I need to get paid work done first. Please consider joining BloomerArmada to get blog comment reply priority, ask me 1-to-1 WooCommerce questions and enjoy many more perks. Thank you :)

Your email address will not be published. Required fields are marked *