WooCommerce Checkout Upsell and Cross Sell. No Plugins Used
And I will tell you more, I faced with this implementation on different websites too. So, let’s try to do it with WooCommerce, I’m going to place this checkbox just before the "Place Order" button, but you can place it anywhere you want βΒ some of the checkout page hooks are described here.
In case you are looking for a plugin β there are a lot of plugins over there but I do not recommend most of them. If you are not a coder, maybe it will be a better solution to ask my help to create this functionality.
My example:

Step 1. Add a checkbox
Ok, you can use woocommerce_form_field() function here but because of the weird required
parameter it adds "(optional)" text after the checkbox label and I definitely do not want it.
Of course, you can str_replace()
the "(optional)" text with woocommerce_form_field_checkbox
hook for example, but let’s keep things simple.
add_action( 'woocommerce_review_order_before_submit', 'misha_checkbox_before_button' );
function misha_checkbox_before_button(){
echo '<p class="form-row">
<label class="woocommerce-form__label woocommerce-form__label-for-checkbox checkbox">
<input type="checkbox" class="woocommerce-form__input woocommerce-form__input-checkbox input-checkbox" name="misha_upsell">
<span>Only today! Get <a href="#" target="_blank" rel="noopener noreferrer">my WooCommerce course</a> with 90% discount – just $500!</span>
</label>
</p>';
}
I copied most of the classes from "Terms and Conditions" checkbox, definitely we do not need some of them. The main attribute is name="misha_upsell"
.
Step 2. Add a product to the Order before Payment
Now, once the above checkbox is checked, we have to add a certain product to the order but we have to do it after the order is submitted and before processing payment. I found the only hook woocommerce_checkout_order_processed
which fits our needs.
add_action( 'woocommerce_checkout_order_processed', 'misha_upsell_something', 9, 3 );
function misha_upsell_something( $order_id, $posted_data, $order ) {
if( isset( $_REQUEST['misha_upsell'] ) && $_REQUEST['misha_upsell'] == 'on' ) {
// get product object, we have to pass it to add_product() method
$product = wc_get_product( 41 );
$order->add_product( $product );
$order->calculate_totals();
}
}
This is an experimental feature and I haven’t tested it a lot, so if you have any questions or issues with it, let’s figure it out together in comments π

Misha Rudrastyh
Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me
What a great piece of code! Thank you very much.
To create the item discount, I duplicated the item (in my case, CBD Oil for Pets), renamed it to “CBD Oil for Pets – Checkout Discount”) and dropped the price to the special price for checkout. Then I set it to private and not searchable on the site. This way, when people check out, they see the name of the item updated with “Checkout Discount” added to it and I can still manage inventory.
Is there a better way to do this? That is, could I (should I) use code to discount the existing item instead of creating a new one?
Hey Matt,
Happy New Year! π
Hmmm… What do you think about using coupons? Did you try it?