This is a great WooCommerce snippet (or plugin, if you wish to call it like that) for those who want to provide conditional checkout fees. For example, you might need to display custom checkout radio buttons to pick premium packaging types, gift wrapping options, specific services or whatever can increase your AOV (Average Order Value).
Radio button selection must work with “Ajax” – which means as soon as the radio button is chosen, checkout must refresh in order to display the updated fees and totals.
Something similar (and also more complex, such as offering additional products) is achieved by the WooCommerce Checkout Add-Ons Plugin sold on the official WooCommerce.com marketplace. But in this case, we want to take a look at custom coding so you’ve got something to play with! Enjoy.
PHP Snippet: Add Dynamic Fee Based on Custom Radio Buttons @ WooCommerce Checkout
/**
* @snippet Dynamic Fee @ WooCommerce Checkout
* @how-to businessbloomer.com/woocommerce-customization
* @author Rodolfo Melogli, Business Bloomer
* @testedwith WooCommerce 3.9
* @community https://businessbloomer.com/club/
*/
// Part 1
// Display Radio Buttons
add_action( 'woocommerce_review_order_before_payment', 'bbloomer_checkout_radio_choice' );
function bbloomer_checkout_radio_choice() {
$chosen = WC()->session->get( 'radio_chosen' );
$chosen = empty( $chosen ) ? WC()->checkout->get_value( 'radio_choice' ) : $chosen;
$chosen = empty( $chosen ) ? '0' : $chosen;
$args = array(
'type' => 'radio',
'class' => array( 'form-row-wide', 'update_totals_on_change' ),
'options' => array(
'0' => 'No Option',
'10' => 'Option 1 ($10)',
'30' => 'Option 2 ($30)',
),
'default' => $chosen
);
echo '<div id="checkout-radio">';
echo '<h3>Customize Your Order!</h3>';
woocommerce_form_field( 'radio_choice', $args, $chosen );
echo '</div>';
}
// Part 2
// Add Fee and Calculate Total
add_action( 'woocommerce_cart_calculate_fees', 'bbloomer_checkout_radio_choice_fee', 20, 1 );
function bbloomer_checkout_radio_choice_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$radio = WC()->session->get( 'radio_chosen' );
if ( $radio ) {
$cart->add_fee( 'Option Fee', $radio );
}
}
// Part 3
// Add Radio Choice to Session
add_action( 'woocommerce_checkout_update_order_review', 'bbloomer_checkout_radio_choice_set_session' );
function bbloomer_checkout_radio_choice_set_session( $posted_data ) {
parse_str( $posted_data, $output );
if ( isset( $output['radio_choice'] ) ){
WC()->session->set( 'radio_chosen', $output['radio_choice'] );
}
}
Hi Thank for the code. it really helps.
I have a question, can we implement the same code on cart page, means I want to implement warranty of $15 to every order based on radion button choice on cart page. If user select Yes, it will add $15 to his/her order and if select No, then add $0.
Can you please help me implement the same on Cart page?
Hi Muzafar, 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!
the code works. But somehow I want to have the radio button and the text to be in the same line. see screenshot here: https://prnt.sc/11q2e61
You’ll need a bit of CSS for that
Hello, everything does work, but I have two pts.
1 – how to add css so that the radio and label are on one line (the solutions described in the comments do not work for me)
2 – the “label” of the selected option is not transferred to the order. How can this be added. Now there is only a default name and amount. If the two options have the same amount, it is not known what the client chose.
Hi Grzegrz, 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!
Hi Rudolfo,
Thank you for all the knowledge you are sharing with.
I’ve noticed that recently (approx two weeks ago) the code you provided stopped working.
Nothing was changed on the website or updated before/after that.
Could you please have a test if the code is still working as usual?
thanks a lot
Sorry I’m on paternity leave!
To troubleshoot, disable all plugins but WooCommerce and also switch temporarily to “Twentytwenty” theme (load the snippet there in functions.php) as explained here: https://www.businessbloomer.com/lesson/trwm4l01/
Once you do that, does it work? If yes, you have a problem with your current theme or one of the plugins.
Hope this helps!
It is not working. I just tried it. How can I make it work?
Hi Reman! What’s not working exaclty?
I tried to copy and paste the code into functions.php.
It displays correctly however if I click on a radio option, nothing refreshes.
Please help.
Weird. You might have a jQuery conflict or a cache problem. Try deactivating all plugins but Woo and see if that does the trick
hello , thank you at first , i would like to ask how make the choice mandatory (the customer must be select option from radio button to proceed the order)
thank you
Hi Hany, 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!
Is this possible to make it work only with a specific country?
I mean, make this only show when the country selected in the checkout is Portugal.
Thanks in advance.
Hi Miguel, 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 is not working in cart page i needed to work it on cart page
Hi Farhan, 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!
Can we placed this radio option before billing first name or after the billing email? If yes then how? i tried with this in part 1
add_action( ‘woocommerce_before_billing_first_name’, ‘bbloomer_checkout_radio_choice’ ); but it seems not working..
You can but it needs further customization, because it won’t trigger a checkout update on change if placed there
how to add same code to cart page?
Hi Aleks, 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!
Good morning.
I can’t understand why when the selected fee is with decimals (for example 5,14€) with this code in the cart the fee become 5€ instead of the selected 5,14€.
may you help me? i need the decimals.
Another way for help me is find a way to save the NAME of the fee selected by customers. any place is good, but in the address order review, after the ZIP code, or the City, it will be perfect.
Hi Gian Mario thanks for your comment! You can give the radio buttons a value that is text-only e.g. “fee1”. Then, in the second part of the snippet, you can do this:
is it possible to add the function as a product instead of a fee?
Hi Dave, 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!
hey I used this code and its working fine but there are a lot of changes on our side and we want to exclude some products from this option is this possible?
Hi Kenthreig, 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!
Another solution for the issue with the same line.
Add this to $args.
CSS:
.labelafter:after {
content: ‘ ‘;
clear: both;
width: 100%;
display: block;
}
Cool!
I managed to get the radio buttons and their labels to appear on the same line. I don’t know if it’s the best way to do it, but it worked.
Step one:
Add a line break after the first option:
’10’ => ‘Option 1 ($10)’
Step two:
Add the following to CSS;
#checkout-radio label.radio {
display: inline!important;
margin-left: 5px;
}
#checkout-radio input[type=radio] {
margin-left: 15px;
}
That did it for me.
Well done!
In your example above, the radio buttons and their labels are on the same line.
Radio Button – Option 1
Radio button – Option 2
I’m testing the code as written, but it displays with the radio button and the label on different lines:
Radio Button
Option 1 text
Radio Button
Option 2 text
Any idea why this is happening or what I can do to fix it? I don’t see anything in the code that would add a line break in between the button and the label for it.
I’m trying to add fee in checkout page via ajax by a button click. But the ‘woocommerce_cart_calculate_fees’ hook is not working with ajax request. Please help me solve the issue, take a look at the code:
Amirul, 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!
Great Code! I have implemented it successfully.
My only challenge is that when the data gets written to the database, it puts the data in the wp_woocommerce_order_itemmeta table, and every time any of my plugins try to access this field it more challenging.
Is there any easy way to also put a duplicate of this value and field name _fee_amount to the wp_postmeta? Most of my plugins are pulling the from that table.
Is there some way to have it write this data to both tables?
Thanks!
Hi Jacob, 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!
Hey Mike,
The payment system for paypal and stripe, 10% deposit allowed only. So I want to change the payment to be a deposit of 10% of the amount, which clearly says “Please pay your 10% deposit now to start your order and production” also must clearly say “This deposit is a non refundable deposit”
Now the deposit in cart should be calculated like this. 10% of the total amount of the bill, PLUS add 5.9%, for the payment of the deposit using Paypal or Stripe.
I also Want to write point “The balance payment you will receive an invoice from Torque Jet Boards within 7 days for the balance to be paid through bank transfer, which will include the product remaining cost and the shipping fees.”
How can i do this with PHP or any Free Plugin. Please Help
Hi Muhammad, 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,
Do you have checkbox version? If not could you please update new version for checkbox version? Thank you so much!
Hello Stephen, 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!
Firstly thank you for sharing this code! I am adapting it so that it also appears on the cart page and it works, however, it only works once. It’s like the jquery function just isn’t working after the cart update. Can you suggest anything?
The moment I posted this comment I foundthe solution it out. For it to trigger the cart update you need to recall the on change jquery again with the using the cart update on the body element…
stackoverflow.com/a/39321178/2509587
Nice!
Hey! Love this code snippet, thanks for sharing it! Altough I have a question. I use it as a discount radio button on a page, where only one product can be in the cart in the same time. Can I modify the code, so it would only change the price if the product in the cart has a certain product category?
Harkai, 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 Rodolfo,
i have this API code thats generate an arrays of fees and wanted to put this array in ‘option’ at $arg array, it manage to show the radio button and name next to it but all of the radio selector gone after i click on it. why?
Hello Ree, 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!
Thanks for the great post !
Is it possible to have the customisation option on the product page?
Hello Yama, 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!
Hi, how could i modify this. I need only one options, by default it should not be checked and than you could check it or uncheck it again if you want it.
Thanks
Hi Rok, 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!
Hi, very good job. How can I put the amount in percentage?
Sorry, only put this lines for 20% of total:
…
$radio = WC()->session->get( ‘radio_chosen’ );
$percentage = 0.25;
$percentage_fee = ( $cart->cart_contents_total + $cart->shipping_total ) * $percentage;
if ( “option_1” == $radio ) {
$fee = $percentage_fee;
…
sorry is the 25% of total…
Hi Ocano, 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 for this. it helped me alot
Nice!
(Sorry to post again. I couln´t subscribe to the post with the other email.)
I have copied and adapted your code to my reality. It works on the functions.php, but not on a class inside my plugin.
To be more accurate, the ajax is not working. Everything else does. Researching, I found out you have to do something special when working with ajax in plugins, but I could not integrate with your code. What would you have done differently if writing this code in a plugin class?
Rafa, 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!
Hey Rodolpho! Great work!
So, I´ve written your code and adapted it to my reality. It works great
Although, it´s not working when I put it inside of a class. To be more specific, the ajax part is not working. Everything else is. Is there a special something to do when working with ajax in classes?
Hi Rodolfo, really useful. Only one problem …every option that I insert is on a new line.
So I have the in
line1- choose point
line2- option 1 text
line3- choose point
line4- option 2 text
line5- choose point
line6- option 3 text
Hello Edoardo, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom CSS work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!
Hello I’m trying to implement this on my site and it does the update via Ajax when I select an option, but the fee value is not being added.
Does this happen to anyone else?
Hi Luis, did you use the exact same code?
Thank you! It works very well, BUT does not include VAT to the fee?
I can’t seem to find a place in the code that defines if the fee is with or without VAT..
Hope that you maybe can, Rodolfo 🙂
/Tobias
Hello Tobias, 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!
Tobias in $cart->add_fee( $name, $amount, $taxable, $tax_class );
$taxable is false by default, add true and your tax-class
Nice!
Hello Rodolfo,
you are Very informative and easy to follow , is it possible to insert the radio buttons within the newly added “optional fee” slot of the checkout order review not below?also could you elaborate on why, when option_1 is set as the default the fee is not added i noticed another option must be selected and then option1 again in order to add the fee?
Hi there! I’m sure you can move it wherever you like 🙂 In regard to the rest, 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!
Hi, I have a question how can i change the code if instead of having fix fee to be %. like 3% of a total amount before the fee.
Hello Valenitnos, 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!
I can help you with this if you still need
Hello! Do you know a solution for ‘discount if checkbox is selected’? meaning activating a checkbox which says: “I want a monthly Auto-Delivery”. This is pre-selected and the client gets directly 10% discount on his cart. If he ticks off the box, the discount gets removed and he pays full price. thanks 🙂
Hello Riccardo, thanks so much for your comment! Yes, this is possible – unfortunately this is custom work and I cannot provide a complementary solution 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
Hi, the snippet works but it does not add any of my fees.
Works for me, sorry – you’ll need to troubleshoot it.
Hi Rodolfo thanks very much for this snippet. one question, after I checkout and select an amount said $30. after I complete checkout. next time when I visit the website and add something to cart. the $30 fee is already in cart by default. it’s not the default no option. how can I reset to default no option on next time I visit the website with previous checkout with an option? Thank you.
Hey Choutin, I guess the choice stays inside the session and you will need to clear it. However, I believe WooCommerce empties the session when an order is placed. Can you try with another theme and no plugins but WooCommerce?
No, it still remain even after order placed. I use twenty nineteen theme and only woo commerce is enable. Please advise. Thank you
Weird, it works for me and I use it on a client’s site. There must be something else, sorry
Hi guys.
I’m primarily a Laravel backend dev. But i got involved in a woocommerce project and your articles have been life savers.
Just want to thankyou for the amount of invaluable content you put out.
Much love from Kenya!
Thank you so much!
Hello Rodolfo, thank you very much for this fragment of php, but the question is how can I do this with a select?
Hello Joshua, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution 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
Hi Rodolfo, this is great! I’ve amended it to show the choice made in the order confirmation page int he woocommerce > orders section, but how can I add it to the confirmation email that is sent out?
Thanks!
Hello! If you have two options with the same price how do you know what the person has chosen?. In the woocommerce order information it only tells you the price, not what the person has selected. Thanks!
Hello Patricia, thanks for your comment! In the “$cart->add_fee” part, you could possibly print the name of the option as well, so that you can know it for later. Hope this helps!
Hello Rodolfo,
Thank you for the great code snippet.
I’m wasn;t able to print the chosen option in the order confirmation email or in the order details in the WordPress dashboard.
would it be possible to tell me how to do it please?
Thanks.
Hi Mandy, this should help you a little: https://www.businessbloomer.com/woocommerce-save-display-order-total-weight/
Thats great! I did that thanks!
Excellent 🙂
This code works really great ! thank you.
Awesome 🙂
Thank you for your great work. The snippet has option 1 set as default. How can I change the default selection so that no option is selected
Hello Jurgen, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution 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
Once we choose the radio with $30. It should be updated in thank you page, isn’t it so?
Hi there, thanks for your comment! Yes of course 🙂
Hi Rodolfo thanks a lot for this php snippet ,but the question is if i had integrate an e-commerce theme in my woocommerce website where can i add this snippet and should i create a child theme ?
Hello Sabrine, yes, I recommend to place this in your child theme’s functions.php file – if you need more guidance, please take a look at this video tutorial: https://businessbloomer.com/woocommerce-customization-hangout/. Hope this helps!