Cross-sell products from the Thank You page with a Coupon applied
Step 1. Display Cross-sells
Just in a case you’re green 🌱 here, let me show you where in product settings you can configure cross-sell products.

We already had a chance to work with woocommerce_thankyou
hook here. So you can check the link for more examples and explanations.
add_action( 'woocommerce_thankyou', 'misha_cross', 3 );
function misha_cross( $order_id ){
/* this array will contain all the product/variation IDs for cross-sell */
$crosssel_ids = array();
$order = wc_get_order( $order_id );
/* get cross-sell for each purchased items and write them to the array */
$items = $order->get_items();
foreach ( $items as $item ) {
if( $item_crosssel_ids = get_post_meta( $item['product_id'], '_crosssell_ids', true ) ) {
$crosssel_ids = array_unique( array_merge( $item_crosssel_ids, $crosssel_ids ));
}
}
/* product query */
if( !empty( $crosssel_ids ) ) :
$crosssel = new WP_Query( array(
'post_type' => array( 'product', 'product_variation' ),
'post_status' => 'publish',
'post__in' => $crosssel_ids,
'orderby' => 'post__in'
) );
if( $crosssel->have_posts() ) :
echo '<section class="woocommerce-misha-cross-sell"><h2>Present for you!</h2><div class="woocommerce columns-3">';
woocommerce_product_loop_start();
while ( $crosssel->have_posts() ) : $crosssel->the_post();
$product = wc_get_product( $crosssel->post->ID );
/* we can not add the variable product to cart just from Thank you page, so skip them */
if( $product->is_type( 'variable' ) ) {
continue;
}
if( !$product->is_in_stock() ) {
continue;
}
wc_get_template_part( 'content', 'product' );
endwhile;
woocommerce_product_loop_end();
woocommerce_reset_loop();
wp_reset_postdata();
echo '</div></section>';
endif;
endif;
}
As usual, here is some notes for this code:
- With the help of
$order->get_items()
we get the items from the order. You can read about the difference between products and order items here. - This line allows us to get the array of unique IDs of products we would like to display. If you want to get Upsells, you can use
_upsell_ids
key instead:$crosssel_ids = array_unique( array_merge( get_post_meta( $item['product_id'], '_crosssell_ids', true ), $crosssel_ids ));
- I do not want to display variable products because if you want to add them to cart, you have to visit a product page, but I want to display product variations, so I added
product_variation
to thepost_type
parameter of WP_Query and a condition to the loop to skip the variable productsif( $product->is_type( 'variable' ) ) {
.
Here is the result:

If you just want to display cross-sell products, without discounts, you’re done here and do not have to read the rest part of the tutorial.
Step 2. Apply discounts to prices
This code works only for simple products and product variations:
add_filter('woocommerce_get_price_html', 'misha_discount', 10, 2);
function misha_discount( $price_html, $product ){
/* if it is the thank you page*/
if( !is_wc_endpoint_url( 'order-received' ) ) {
return $price_html;
}
/* if already has discount, do nothing */
if( $product->is_on_sale() ) {
return $price_html;
}
/* discount percentage */
$discount = 10;
return wc_format_sale_price(
wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) ),
wc_get_price_to_display( $product, array( 'price' => ($product->get_regular_price() * ( 1 - $discount / 100 ) ) ) )
) . $product->get_price_suffix();
}
Actually the above code just changes the way the prices are displayed on the Thank You page and nothing more. Result:

Step 3. Create a unique coupon
Now a little experimental part begins. We need a coupon and here are the requirements:
- Coupons can be used just once,
- Only one customer can use a certain coupon,
- Coupons must be applied only to certain products,
- When a customer makes another order, the old coupon shouldn’t be added to the cart anymore,
- (Optional) Coupon must expire by a certain period of time.
I came up with an idea to generate unique coupons for each order. Yes, I know it could be not the best way, but if you have a better idea, please suggest in comments.
/* when an order is placed */
add_action( 'woocommerce_order_status_processing', 'misha_create_a_unique_coupon', 10, 2 );
function misha_create_a_unique_coupon( $order_id, $order ){
/* let's do nothing for administrators and shop managers */
if( current_user_can('administrator') || current_user_can('shop_manager') ) {
return;
}
/* creating a coupon, you can add some random numbers there with rand() */
$coupon_name = 'crosssell'.$order_id;
/* creating a coupon like a custom post type */
$coupon_id = wp_insert_post( array(
'post_title' => $coupon_name,
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
) );
/* we have to allow the coupon only for cross-sel products */
$crosssel_ids = array();
/* get cross-sell for each purchased items and write them to the array */
$items = $order->get_items();
foreach ( $items as $item ) {
$crosssel_ids = array_unique( array_merge( get_post_meta( $item['product_id'], '_crosssell_ids', true ), $crosssel_ids )) ;
}
update_post_meta( $coupon_id, 'product_ids', join(',', $crosssel_ids ) );
/* 10% discount */
update_post_meta( $coupon_id, 'discount_type', 'percent' );
update_post_meta( $coupon_id, 'coupon_amount', 10 );
/* only 1 usage is allowed */
update_post_meta( $coupon_id, 'usage_limit', 1 );
/* do not apply to sale items */
update_post_meta( $coupon_id, 'exclude_sale_items', 'yes' );
/* store IDs of cross-sell products and coupon code in session */
WC()->session->set( 'cross_sell_coupon', $coupon_name );
WC()->session->set( 'cross_sell_products', $crosssel_ids );
}
If you want the coupons to expire by a certain period of time, just add another post meta expiry_date
in a format like this YYYY-MM-DD
.
By the way, would you like me to publish a tutorial about coupons? If yes, what questions do you have? Let me know in in comments.
Step 4. Apply the coupon
This code will be fired each time the cart page is open but coupons will be added only in case there are specific products in the cart and if a coupon code is stored in user sessions.
add_action( 'woocommerce_before_cart', 'misha_apply_coupon' );
function misha_apply_coupon() {
global $woocommerce;
if( ($coupon_code = WC()->session->get('cross_sell_coupon'))
&& !$woocommerce->cart->has_discount( $coupon_code )
&& WC()->session->get('cross_sell_products') ) {
/* do not try to apply a coupon for inappropriate products */
foreach ( $woocommerce->cart->cart_contents as $key => $values ) :
if( in_array( $values['product_id'], WC()->session->get('cross_sell_products') ) ) {
$woocommerce->cart->add_discount( $coupon_code );
return;
}
endforeach;
}
}
I want to repeat that again – for me this tutorial seems a little tricky and experimental, so if you have any suggestions how to improve the code, welcome to 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
The products that is added to cart, it will be added to the same order or there will be a new order?
It will be a new order
that is not a good approach since products without a cross-sell with generate an error. please re-visit this code.
Updated, thank you!