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.

Configure cross-selling in WooCommerce
Please note, that you can add to cross-sells not only simple and variable products but also certain product variations.

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:

Here is the result:

Display cross-sell products on WooCommerce thank you page

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:

Cross-sell with discount from the Thank you page

Step 3. Create a unique coupon

Now a little experimental part begins. We need a coupon and here are the requirements:

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

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

Follow me on X