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 to check if there are only “virtual” products in the Cart and if yes, all the billing fields and order notes are hidden (but name and email address). Go test this on your development environment and let me know if this works!

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

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 7
 * @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;
}

Where to add this snippet?

You can place PHP snippets at the bottom of your child theme functions.php file (delete "?>" if you have it there). CSS, on the other hand, goes in your child theme 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 free video tutorial "Where to Place WooCommerce Customization?"

Does this snippet (still) work?

Please let me know in the comments if everything worked 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 on PHP 7.3.

If you think this code saved you time & money, feel free to join 14,000+ WooCommerce Weekly subscribers for blog post updates or 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.

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

  1. 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

  2. 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

  3. 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!

  4. 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

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

  6. 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

  7. 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’ );

  8. 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' );
  9. 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

  10. 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

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

  12. It just works, brilliant

  13. 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

  14. 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.

  15. Still working great in 2021!!

    1. Great!

  16. 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

  17. Thanks for publishing this, worked perfectly.

    1. Great!

  18. 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.

  19. 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!

  20. Thank You. It works for me

    1. Nice!

  21. Still works, thank you

    1. Excellent!

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

    1. Great!

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

    1. Eheh glad it helped

  24. 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

  25. 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!

  26. 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!

  27. Works like a charm!

    1. Thanks!

  28. No luck yet, let me try again

  29. 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!

  30. thanks a lot man .. its magic.

    1. Great!

  31. I love it! Thank you!

    1. Yay!

  32. 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

  33. 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!

  34. 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

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

    1. Cheers!

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

    1. Great!

  37. 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

  38. 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

  39. 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

    1. Thanks Andy ๐Ÿ™‚ I suggest you take a look at “conditional logic”: https://businessbloomer.com/conditional-logic-woocommerce-tutorial/ and https://businessbloomer.com/woocommerce-conditional-logic-ultimate-php-guide/. Let me know ๐Ÿ™‚

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

    1. Awesome ๐Ÿ™‚

  41. 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!

  42. 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 *