Hide checkout fields based on the products in the cart

You ask, i write! This post has been asked by sidharh in my other article about how to “Add a checkout field in WooCommerce only for specific roles“.

This time instead, we will hide checkout fields based on the products contained into your cart. you asked to add them instead to hide them, but it’s a lot quicker to add them all, and then hide them when they are not needed.

Let’s start!

First of all, install and activate Checkout Field Editor. This is not a required step, if you do not have the plugin and do not want to purchase it you can add the field by yourself following this tutorial.

Create all the new fields you need for the shipping for or the billing for or also additional fields. Also, be sure to have a list of all the products ID you need to use in your code to hide specific fields. If you don’t know how to get the product ID, read this tutorial.

Now you are ready to write some code. Open your functions.php file located in wp-content/themes/your-theme-name/ and add this code at the end of the file:

In this code, i hide the billing and shipping company field only if the product ID 70 is in the customer cart.

This is a very simple rule, obviously you can create very complex rules too, like hide fields only if there’s a product, but not another one, or hide a field if there are 2 or more products into the cart or anything else you can think about.


More Posts That You Might Like…


50 responses to “Hide checkout fields based on the products in the cart”

  1. […] Here’s a tutorial from WooNinja Nicola Mustone on hiding checkout fields based on products in the cart. […]

  2. Hi,

    I just use your snippets code, 1 month ago and it works.
    But now with somes updated i think… it doesn’t work, i just use more products :

    function conditional_checkout_fields_products( $fields ) {
        $cart = WC()->cart->get_cart();
    
        foreach ( $cart as $item_key => $values ) {
            $product = $values['data'];
    
            if ( $product->id ==  2624 || 2630 || 2634 || 2636 || 2637 || 2814 ) {
                  unset( $fields['billing']['aut1'] );
                  unset( $fields['billing']['aut2'] );
                  unset( $fields['billing']['aut3'] );
            }
        }
    
        return $fields;
    }
    add_filter( 'woocommerce_checkout_fields', 'conditional_checkout_fields_products' );
    

    it’s a good snippet ? or it’s the plugin updated that is wrong ?
    I put it in the functions.php.
    Thanks for your help.

    PS: Nice website 😉

    1. Hi! Thanks for reading!

      if ( $product->id == 2624 || 2630 || 2634 || 2636 || 2637 || 2814 ) {

      You can’t do this. You should do

      if ( $product->id == 2624 || $product->id == 2630 [etc.] ) {

  3. Yeah it works well !
    Thanks a lot

    Have a good day 🙂

  4. Great! 🙂

    Have a good day

  5. Thanks Nicola,

    I tried this code snippet on some products with some tweak and it worked well. This was really helpful.

    I having a bug/error on a site using woocommerce. On each product page there is a section to leave a review, but the user must be logged in to comment (which I want)

    So, when a user is not logged in, they get the message “You must be logged in to post a comment” and the log in link goes to https://www.mysite.com/wp-login….. and redirects back to the previous page. I do not want any of my users seeing the wordpress login. I want them to go to woocommerce login page https://www.mysite.com/my-account and then keep the redirect in place – redirected back to the page they were on once logged in.

    I know this is something to do with classes {must-login-in} & {logged-in-as}.

    .sprintf( __( 'You must be <a href="%s" rel="nofollow">logged in</a> to post a comment.' ), get_permalink(get_option('woocommerce_myaccount_page_id'))).'';

    If you can write an article on woocommerce redirect link and how to generate woocommerce my account URL by using the woocommerce_myaccount_page_id.

  6. Great article. I’m new at WooCommerce and would like to know how you would HIDE form fields if… all of the products in the cart contained the same TAG… If any product in the cart did not contain the TAG, then the form field should SHOW. Thanks for your help.

      1. Perfect. Thanks. Here’s my final code in case it can help someone else…

        function wordimpress_is_conditional_product_in_cart($product_tag) {
            //Check to see if user has product in cart
            global $woocommerce;
        
            //flag no product with tag in cart
            $in_cart = false;
        
            foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
                $_product = $values['data'];
        
                if ( has_term( $product_tag, 'product_tag', $_product->id ) ) {
                    $in_cart = true;
        
                }
            }
        
            return $in_cart;
        }
        
        1. Hi Dave, thanks for sharing!

          Instead of $woocommerce use WC(). The global variable $woocommerce is not used anymore in the plugin. Will be removed in a future version.

  7. Great tip, works great! Except… Trying to remove a field that was created using Checkout Field Editor under a tab “Additional Fields”…

    Your unset tip works for [billing] .. and [shipping] … not sure how to trigger it for fields created under ‘additional’ tab since it’s not a [billing] [shipping] [order] or [account]…

    Any insight? Thanks!

    1. Hi, the name of that tab in the code is additional!

      1. Have the same problem like many before, I cannot target the ‘additional’ fields?

        Im using the “WooCommerce Checkout Field Editor” plugin, and simply cannot “target those fields”
        Having the same problem with fields inserted by the ”
        WooCommerce Order Delivery” plugin (makes fields under #wc-od)

        Anyone has a soloution to this?

  8. Hi Nicola!
    Is there a way instead of listing each ID you could possibly list a category? It would make things much easier.

    1. I am looking for the ability to ‘hide’ the additional fields created and ‘show’ others. For instance, I wouldn’t ask the Exhibitors the same questions as the public…

    2. Hi Jenne,
      to do that you need to change the if on line 13 with this code:

      if ( has_term( 'category-slug', 'product_cat', $product->id ) ) {
      

      Replace category-slug with the category you want to check.

  9. Nicola,

    Thank you so much. This is basically what I’ve been looking for for the past couple of hours and I’m 90% there.

    I am able to exclude certain fields when a specific product is added. However if I add another product to the cart that requires those fields they are still hidden. Is there a way to turn this off in this instance?

    1. Hi Mike,
      to do that you i would check each product ID to be different than the one you don’t want to hide the fields for. Then before to check the ID again (the line where you check if it’s == to 70, check also if it’s in an array with the ones you don’t want to hide. If it’s there, then show the fields, otherwise not.

      If you require assistance with this and would like to explore this further you can seek help from an Affiliated Woo Worker or post a job on Codeable, I have provided links to these below.

      Affiliated Woo Workers
      Codeable

      Have a great week!

      1. Nicola,

        Thanks for the response. Certainly beyond my skill level.

        I will check out those two links and see if I can get some assistance from a pro. Thanks again.

  10. Hi Nicola,

    I add a field with wooCommerce add-on. It is a gift message with a text area for a given price. As I don’t sell only gift product, I want to hide the “gift message” field when it’s not a gift.

    I tried to replace billing by “additional” and after “gift_message” but it’s not working! Do you have any suggestion?

    P.S. thanks a lot for your amazing website! Very useful and easy to understand! If you’re not, you should become a professor 🙂

    1. Hi Florian,
      in the snippet above, add this code after line 8: var_dump( $fields ).

      This code will show all the checkout fields show on the page, so you can find which index to use to hide the gift message.

      P.S. Thanks! I’m glad you find it useful 🙂

  11. I have a scenario that I wondered if you could help with relating to this code.

    I have one product (a Fan Club Membership) that requires additional fields to be visible on Checkout. The rest of my products don’t require these fields.

    So I am using the above code to hide these fields for the rest of the products.

    However, it doesn’t take into account if a user adds BOTH the Fan Club Membership AND another product. It removes the fields in this instance, but it should not.

    Any idea how I can manipulate this code to work for this scenario?

    Many thanks,

    Richard

  12. If I want to hide some field in the “WooCommerce Checkout Add-Ons” Plugin how can I do that?

  13. Hi,

    I tried the code and it works for all default fields ( billing, shipping, order notes), but it does not work for additional fields that are added by me.

    I use this code:
    …. unset( $fields[‘additional’][‘additional_field_753’] ); …

    I have tried with code “var_dump( $fields );” to see the fields on my checkout page, but the additional fields that are created by me with the plugin just don’t show up there. So I guess it does not see my fields.

    How can I hide them?

    Thanks in advance!

    1. That is most probably caused by the priority of the filter.

      Make sure that it’s higher than 10, like this:

      add_filter( 'woocommerce_checkout_fields', 'conditional_checkout_fields_products', 20 );
      

      Or more than 20 if needed.

      1. Hey Guys,

        Strolling through the thread looking for a solution to this same problem. I’ve tried all of the recommendations in this thread, but can’t seem to hide the additional fields that I created using the “additional fields” section.

        Here’s the code that I’m using:

        /**
        * Hides checkout fields based on the products in the cart
        *
        * @param array $fields
        * @return array
        */
        function conditional_checkout_fields_products( $fields ) {
        $cart = WC()->cart->get_cart();

        foreach ( $cart as $item_key => $values ) {
        $product = $values['data'];

        if ( $product->id == 35 ) {
        unset( $fields['billing']['billing_phone'] );
        unset( $fields['additional']['additional_field_deliverydays'] );
        }
        }

        return $fields;

        }
        add_filter( ‘woocommerce_checkout_fields’, ‘conditional_checkout_fields_products’, 50 );

        Need to be able to hide a field that we created called “delivery days”, in addition to a few other fields that were created under the additional fields section.

        Thanks in advance for any assistance that you can provide!

        Regards

  14. Hi,
    this looks pretty interesting. I have another problem: I just want to hide/display a css class when a certain pro/cat is in the cart!!

    Reason: My client has klarna as paymethod and they have there own checkout page after the cart-page with a link to regular checkout from woocommerce. Now they have a new product-category and they want to deactivate/skip klarna for that. I just created a new button in the cart.php with a own class and the link directly to the regualar checkout.

    Its a pretty dirty solution, but any idea if that is possible with your script? Thanks for your help!!!

    1. remove_action(‘woocommerce_proceed_to_checkout’, ‘woocommerce_button_proceed_to_checkout’, 20);
      add_action(‘woocommerce_proceed_to_checkout’, ‘change_url_to_checkout’, 20);
      
      function change_url_to_checkout(){
          $extra_url = ‘put_your_extra_page_url_here’;
          ?>
          <a href="” class=”checkout-button button alt wc-forward”>
          <?php
      }
      

      This works and would be the perfect solution, ….just dont get it :/

      1. Hi,
        You should add an if right after the function declaration to check if the product is in the cart.

        To check if the product is in the cart you can use something like:

        $cart_iitems = WC()->cart->get_cart();
        

        And then check if the product is in the array $cart_items.

        1. Hi and thanks for your quick answer, but I just dont get it :/ …i tried different scripts, but it doesnt work for me. Could you help me again please?

        2. Try with this:

          https://gist.github.com/SiR-DanieL/7fd8ec2e4443abf792100ddf58b311c9

          On line 8 change the 70 with your product ID.

        3. oh thank you!!!

  15. I’m struggling with something this problem.

    When a coupon is applied I need to show the order comments as a required field.
    When no coupon is used I want to hide the order comments.

    I can hide it with:
    unset( $fields[‘order’][‘order_comments’] );
    but the order comments are still required.

    I just assumed that unsetting a field also made the requirement obsolete.

    Any pointers for this scenario?

    1. Hi Max,
      you can use $fields['order']['order_comments']['required'] = false; to make that field not required.

      By default, it is not required though, so this code I suggested may not work. It depends on how you make it required.

      1. Hi Nicola

        I need something like this:

        Coupon code applied
        – Show order comments
        – Order comments = required filed

        No coupon applied
        – Hide order comments
        – Order comments = NOT required (which I assumed followed the hiding/unsetting)

        The setup I have now is that I make the order comment required as a default. And when no coupon is present I have a snippet that hides it:
        unset( $fields[‘order’][‘order_comments’] );
        add_filter( ‘woocommerce_enable_order_notes_field’, ‘__return_false’ );

        I was assuming that unsetting and hiding a field would also ignore the requirement.

        1. Max can you paste the entire code in a snippet on https://gist.github.com and send me the link in a comment please?

  16. Thanks Nicola, here is the snippet:
    https://gist.github.com/Dudikowski/f53b4e7ed4251dd90400d1f1ea94c65c

    I dont know how much of this code is useful for a working solution though. I came to this setup after making a bad assumption. I thought that unsetting a field would make it completely out of the picture.

    The default settings for the checkout fields
    If no coupon code was used we hide the order comments, but the required setting from #1 is still valid

    1. I don’t think that is going to work.

      What I would do is:

      • Make notes NOT required by default
      • Add a JS that makes the notes required or not based on the coupon, when the page loads
      • Use the action woocommerce_before_checkout_process to make sure that the note is NOT empty when it is required
      • From that action, return true or false to eventually stop the checkout
  17. […] Hide checkout fields based on the products in the cart […]

  18. Hi,

    How to Disable checkout field using class name for particular product category?

    Thanks in advance

  19. Is there a way to hide checkout fields based on payment method?
    Thanks!

    1. Yes. Maybe a good option would be to do it via jQuery and hide fields when a specific payment method is selected.

  20. I want to add custom content in spesific product pages not all of them , I have added the following code but it didn’t work, please advice

    function iconic_output_engraving_field() {
    
    global $product;
    global $woocommerce;
    
    if ( $product->id !== 411 || $product->id !== 412 ){
        return;
    }
    
    ?>
    <div class="iconic-engraving-field">
        <label for="iconic-engraving"><?php _e( 'Gluten Free', 'iconic' ); ?></label>
        <input type="checkbox" id="iconic-engraving" name="iconic-engraving" value="Gluten Free">
    </div>
    <?php
    
    }
    
    add_action( 'woocommerce_before_add_to_cart_button', 'iconic_output_engraving_field', 10 );
    
    1. Hi Nermin,
      The code looks good to me. It looks like you want to add a label only for some products. In that case you could use an extension like Advanced Product Labels to do it without any code.

  21. How can i use this in reverse?

    I mean i want to hide all the fields and when a specific product is in checkout i want this field to be showed?

    1. Hi Tim,
      instead of using $product->id == 70 use $product->id != 70.

      In the first case it means that the product ID has to be equal to 70, in the second case it means that it must be different.

  22. Hi,
    please how can I hide only a Country in checkout billing or shipping adress is logged in user is not member of a Special Group? For example Bulgaria
    unset( $fields[‘billing’][‘billing_country][‘BG’] );
    does not work

  23. Hello,
    I am trying to make a directory with free and paid listings.
    Is it possible that:-
    Only for the zero rated (free) product IDs in woocommerce, the ‘Proceed to Checkout’ button becomes / behaves as ‘Place Order’ button on the checkout page. (In short, can I skip the checkout page and go directly from ‘Proceed to Checkout’ to ‘Order confirmation page’.
    Normally users find the checkout page irritating when there is no payment involved.
    Many thanks for your time. Any help will be deeply appreciated.

    Kind Regards,
    Manish

  24. Simply – it did not work for me 🙁
    I’ve tried it in an incognito window and 2 different browsers, and have cleared browser caches.

    1. Hi Sheila,
      I just tested the code with WooCommerce 3.3.4 and it works fine for me.

      Make sure you’re using the proper product ID.

Leave a Reply

Categories

Newsletter

Receive new articles from this blog directly in your inbox!

No spam guaranteed!

Blog at WordPress.com.

%d bloggers like this: