Customize the WooCommerce order received thank you page

The WooCommerce order received page — commonly called the “thank you” page — is shown immediately after a customer completes checkout. It displays the order number, order details, and a payment confirmation message. This page is one of the highest-intent pages on your store: the customer is in a positive, satisfied state and highly receptive to cross-sell offers, newsletter sign-ups, or social sharing prompts. Customising it is therefore one of the highest-return improvements you can make to a WooCommerce store. WooCommerce provides several action hooks that fire specifically on this page: woocommerce_thankyou (fires after the order details table, passing the order ID), woocommerce_before_thankyou, and the template-level hooks inside the order-received.php template. You can also check is_wc_endpoint_url( ‘order-received’ ) to target this page in your PHP or CSS without creating a custom page template. The example below adds a personalised message, a related products section, and a newsletter opt-in checkbox to the order received page using hooks only. For more WooCommerce customisation patterns, see the guides on custom checkout fields and displaying product prices. All output uses proper WordPress escaping functions to prevent XSS.

Problem: You want to add custom content to the WooCommerce thank you page — a personalised message, a cross-sell offer, or a newsletter prompt — without overriding WooCommerce template files.

Solution: Add the following code to your functions.php file:

/**
 * Add a personalised thank-you message above the order details.
 */
add_action( 'woocommerce_before_thankyou', 'helloadmin_custom_thankyou_message' );
function helloadmin_custom_thankyou_message( $order_id ) {
    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return;
    }
    printf(
        '<div class="helloadmin-thankyou-banner" style="background:#f0fdf4;border:1px solid #86efac;padding:1rem;margin-bottom:1.5rem;border-radius:0.5rem;">
            <h3>%s</h3>
            <p>%s</p>
        </div>',
        esc_html( '🎉 Thank you, ' . $order->get_billing_first_name() . '!' ),
        esc_html( 'Your order #' . $order->get_id() . ' has been received and is being processed.' )
    );
}

/**
 * Show related products below the order details on the thank you page.
 */
add_action( 'woocommerce_thankyou', 'helloadmin_thankyou_related_products', 20 );
function helloadmin_thankyou_related_products( $order_id ) {
    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return;
    }
    // Get the first product from the order to find related products
    $items      = $order->get_items();
    $first_item = reset( $items );
    if ( ! $first_item ) {
        return;
    }
    $product_id = $first_item->get_product_id();
    $related    = wc_get_related_products( $product_id, 3 );
    if ( empty( $related ) ) {
        return;
    }
    echo '<h3>' . esc_html__( 'You might also like', 'woocommerce' ) . '</h3><ul class="products">';
    foreach ( $related as $related_id ) {
        $product = wc_get_product( $related_id );
        if ( $product ) {
            printf(
                '<li><a href="%s">%s <strong>%s</strong></a></li>',
                esc_url( get_permalink( $related_id ) ),
                esc_html( $product->get_name() ),
                wp_kses_post( $product->get_price_html() )
            );
        }
    }
    echo '</ul>';
}

/**
 * Add a custom CSS class to the body on the thank you page for styling.
 */
add_filter( 'body_class', 'helloadmin_thankyou_body_class' );
function helloadmin_thankyou_body_class( $classes ) {
    if ( is_wc_endpoint_url( 'order-received' ) ) {
        $classes[] = 'woocommerce-thankyou';
    }
    return $classes;
}

NOTE: The woocommerce_thankyou hook fires only when the customer first lands on the order received page. If the customer refreshes the page or navigates back to the URL, the order has already been processed but the hook still fires — so avoid running actions here that should only happen once (like sending a notification). For one-time actions use the woocommerce_payment_complete hook instead, which fires exactly once when payment is confirmed.