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!

1) PHP Snippet: Remove Billing Fields if Cart Contains Virtual Products @ WooCommerce Checkout
/**
* @snippet Hide Fields if Virtual @ WooCommerce Checkout
* @how-to businessbloomer.com/woocommerce-customization
* @author Rodolfo Melogli, Business Bloomer
* @compatible WooCommerce 8
* @community https://businessbloomer.com/club/
*/
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!
Hello Rodolfo,
I have used this snippet for some time on many websites.. it worked fine with the old woo checkout page. But now that woocommerce has the newer block checkout pages, looks so much nicer, it is not working on that new one.
I only need to collect First and Last name and email address as we’re not shipping out a physical product. But it still shows entire billing info, which I really don’t need if it’s just going to paypal or stripe. Please advise.
Hello Misty! The new checkout block is not customizable – at least for now. They’re working on making it happen again, but it will take a while. I recommend reverting to the classic Checkout, and only upgrade once you’re able to customize it
I recently switched to the ‘new stripe checkout experience’ in WooCommece with the Stripe extension and I’m getting an error when I attempt to use the WordPress customizer with the snippet activated. Do you know id this still works with the new Stripe integration? Thanks!
I got so many errors with the “new experience” that I disabled it right away
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
Yes it does
Tried your code and it seems to work, using latest version of WordPress, Woocommerce.
When I try to add a new page the page editor crashes. I disabled all plugins to find ou the problem has to do with Woo Payments plugin.
Tested on my development site dev2.soundshop.online
Problem is also on production site.
Best regards,
John
WooPayments has way too many bugs I’m afraid
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!
Did you talk to the plugin support? I suppose they should fix that
Hi
Yes I talk to them, but really there was a PHP error, once I noticed I was able to fix it, very simple:
I inserted the above the above line just before the for loop. Fixed!
Thanks
Alain
Cool
Many thanks, by adding this line of code at the beginning of the functions I fixed the issue with the new WooPayments 2024
The code works but then my payment method overrides it saying ‘There are no available payment methods per state’
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.
Ok cool!
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
Unset fields should not be visible… so you have some other sort of error
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.
Must be a WooCommerce bug, never seen that before honestly
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…
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!
Hi,
For information, the problem is solved with version 7.6.1 of woocommerce.
Excellent
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.
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
this is wrong.
Why you dont put break in this line:
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?
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!
Found the error, the tip suggest for the user DingoDaisy
Does not work on the PHP8 Version instead use this
Great, glad that helped
Hi. This snippet was working perfectly, I update my PHP version to 8.1 and now I get a critical error.
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.
Can you disable all other plugins except WooCommerce? Because on latest Woo + WP + Storefront theme works perfectly
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?
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’ );
Cool
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. 🙂
Great!
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
You’re welcome!
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?
Worked for me on latest WooCommerce, so it must be a conflict with your theme or another plugin
I love stuff that actually works! Used two of your snippets. No trouble at all. Awesome sauce! Thanks!!
Thank you!
It just works, brilliant
Cool
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.
Not sure, haven’t tested it yet. Let me know
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.
https://www.businessbloomer.com/woocommerce-check-product-category-cart/
Still working great in 2021!!
Great!
what happened if the user selected a physical product with a digital product.
is this gonna show the billing address field in that case?
Yes in case of a “mixed cart” the code won’t trigger so you get the default checkout
Thanks for publishing this, worked perfectly.
Great!
It works perfectly — you da best! 😉
Yeah!
Awesome, exactly what I was looking! Pretty stupid they don’t have this implemented on default.
Cool
how to remove billing address for the second time if the user logins with first time account created
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!
Thank You. It works for me
Nice!
Still works, thank you
Excellent!
Thanks very much, this worked with my GreenMart theme
Great!
Yes! Yes! yes yes yes yeses yes!
Thank you! Worked like a charm!!
Eheh glad it helped
The code works,
However, when I check-out, the transaction goes through but does not redirect the page.
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
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
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?
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!
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)
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!
Works like a charm!
Thanks!
No luck yet, let me try again
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.
True!
thanks a lot man .. its magic.
Great!
I love it! Thank you!
Yay!
This is brilliant, thank you!
How would you also remove the ‘ship to different address’ tick box?
Thanks
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
How would I change this if I wanted to remove billing fields on free products?
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!
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
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
thank you! You’re awesome for sharing the code.
Cheers!
This is Awesome function. Thank you! And yes it still works
Great!
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.
Thanks for your comment Nidhi. It works for me, so please test with a different theme / no plugins to see if it works
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
Hey Himanshu, thanks for your comment! Try using https://wordpress.org/plugins/code-snippets/ instead
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
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 🙂
Hi, found your code and tested it, still can be use. Thank you very much. Really appreciated it.
Awesome 🙂
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
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!
Sweet Code Rodolofo. Thank you, works a charm.
Great 🙂