Order Received (Thank you) page
Welcome to a complete guide about WooCommerce thank you page customization. If you think I forget to mention something in it, just leave a comment down below.
Thank you page URL
I suppose it is the first thing I would like to talk about in this tutorial. I would like to show you how to change the default thank you page URL and how to get it for a specific order.
How to change order received page URL?
Before I show you how to do that, I would like to remind you that by default this URL looks like /checkout/order-received/123/?key=wc_order_XYZ
, where 123 is an order ID and XYZ is an order key. And we only can change two things here:
checkout
slug which is the slug of the checkout page of your WooCommerce store, so you can just go to Pages and change it like you change it for any WordPress page.order-received
slug, which is a checkout endpoint, in order to change it, please go to WooCommerce settings, then Advanced tab.
Let’s change it to .../checkout/thank-you/...
for example.

! is_wc_endpoint_url( 'order-received' )
function.But about if you would like to change the thank you page URL to something like example.com/thank-you
? Is that even possible? Absolutely yes, but in that case you need to create a custom WordPress page with thank-you
slug and perform a redirect to it from the actual thank you page.
Get thank you page url
I already have a tutorial on my website where I show how to get WooCommerce page URLs programmatically, like shop, cart or checkout pages, but there is no mention of WooCommerce order received page URL. So, let’s dive into it now.
When we take a look at the default thank you page URL, which is /checkout/order-received/123/?key=wc_order_XYZ
, we have already figured it out, that it contains an order ID. For us it means that if we would like to generate an URL for a thank you page programmatically, we have to know the ID of the order.
$order = wc_get_order( $order_id );
echo $order->get_checkout_order_received_url();
Thank you page hooks
The next thing I want to talk about – WooCommerce action and filter hooks that are presented on the order received page. There are plenty of things you can do with hooks, let’s make a detailed look on some of them.
Redirect to a custom Thank you page
There are could be different reasons you may need a custom order received page on your WooCommerce store – maybe you just want the page URL to be like example.com/thank-you
or maybe even you would like different thank you pages for different payment methods.
No matter what reasons you have, the solution will be the same – to perform a redirect on template_redirect
action hook. Yes, I know that template_redirect
is not exactly a thank you page hook, it is presented on any WordPress website page, but think I should mention it here, because it is super-useful.
/**
* @snippet Custom Thank You Page Redirect
* @author Misha Rudrastyh
* @url https://rudrastyh.com/woocommerce/thank-you-page.html#custom-thank-you-page
*/
add_action( 'template_redirect', 'rudr_redirect_custom_thank_you' );
function rudr_redirect_custom_thank_you(){
// do nothing if we are not on the order received page
if( ! is_wc_endpoint_url( 'order-received' ) || empty( $_GET[ 'key' ] ) ) {
return;
}
wp_safe_redirect( site_url( 'thank-you' ) );
}
You can use some conditions here as well. I already mentioned my tutorial about creating a redirect to another page depending on a payment method used. The redirect is possible to condition to products purchased.
// first of all we need WC_Order object
$order_id = wc_get_order_id_by_order_key( $_GET[ 'key' ] );
$order = wc_get_order( $order_id );
// get order items
foreach( $order->get_items() as $item ) {
if( 123 === $item->get_product_id() ) { // if product 123 is in the order
wp_redirect( 'YOUR URL' );
exit;
}
}
- Please keep in mind that order items and products are different things,
- The difference between
wp_redirect()
andwp_safe_redirect()
, is that the first one allows to redirect to any external URL, and the second one – only to your website domain, though you can change that with the hook. - The code can be inserted to your current theme
functions.php
file.
Change Thank you page title
Now let’s make some changed to Thank you page content. And we are going to begin with the title. By the way you can definitely find a tutorial on the internet, where it is recommended to use WordPress the_title
hook. I am not sure that it is a good idea within our context. Isn’t it better to use a WooCommerce hook made specifically for this purpose? And this hook is woocommerce_endpoint_order-received_title
.
And also I am thinking why to not show you woocommerce_thankyou_order_received_text
filter hook that allows to change thank you page subtitle.

woocommerce_endpoint_order-received_title
allows to change “Order received” text, the second hook woocommerce_thankyou_order_received_text
– “Thank you. Your order has been received.”Let’s do it 💪 All the code from this tutorial you can insert to you current theme functions.php
but I recommend to use a child theme or a custom plugin.
/**
* @snippet Change Thank You Page Title
* @author Misha Rudrastyh
* @url https://rudrastyh.com/woocommerce/thank-you-page.html#change_title
*/
add_filter( 'woocommerce_endpoint_order-received_title', 'misha_thank_you_title' );
function misha_thank_you_title( $old_title ){
return 'You\'re awesome!';
}
Do you see (Line 3) that this hook has the only one argument – $old_title
, but what about order details? Well, you can easily get the order id from $_GET[ 'key' ]
variable $order_id = wc_get_order_id_by_order_key( $_GET[ 'key' ] )
and after that to get the order object $order = wc_get_order( $order_id )
from the order ID.
The second hook woocommerce_thankyou_order_received_text
makes it easier because WC_Order
object is available as a function argument.
add_filter( 'woocommerce_thankyou_order_received_text', 'misha_thank_you_subtitle', 20, 2 );
function misha_thank_you_subtitle( $thank_you_title, $order ){
return 'Oh ' . $order->get_billing_first_name() . ', thank you so much for your order!';
}
And here is the result:

Add content or a shortcode to Thank you page
There are three hooks that can help you with that:
woocommerce_thankyou_order_received_text
– we’ve already made a quick look above,woocommerce_thankyou
– runs just after the order details,woocommerce_thankyou_METHOD
– the same as the previous one, but can be connected to a payment method slug.
I am going to use woocommerce_thankyou
hook to display several latest products just below the order details.
add_action( 'woocommerce_thankyou', 'misha_shortcode_or_content' );
function misha_shortcode_or_content( $order_id ) {
echo do_shortcode( '[products limit="3"]' );
}
Thank You Page Templates
In all the examples you’ve seen in this tutorial I used hooks. A hook can be applied very easily – just insert it to the functions.php
/ child theme’s functions.php
/ custom plugin.
But not always hooks allow us to make the customization we need. If you open your WooCommerce plugin folder, you will find the templates
directory there. But in terms of this tutorial we’re interested in the following files:
templates/checkout/thankyou.php
templates/checkout/order-details.php
templates/checkout/order-details-item.php
templates/checkout/order-details-customer.php
Of course you do not have to change the content of these files directly inside WooCommerce plugin folder. All you need to do is to choose the file you would like to change and duplicate it in your current theme’s woocommerce
folder.
From | To |
---|---|
templates/checkout/thankyou.php | your-theme/woocommerce/checkout/thankyou.php |
After that you can make changes in this file! But be careful – hooks are a more safe way to make changes of course. Just imagine you changed so many of WooCommerce template files and… the new WooCommerce version arrived. You won’t lose your changes but maybe your code won’t work with that new WooCommerce version as expected, so you will have to check every changed template.
Collect additional customer details on your Thank You page
1. Add a HTML form
So, we need a form, right? Where would we add it? If just after the title, we can use woocommerce_thankyou_order_received_text
, if below it, woocommerce_thankyou
is a perfect fit.
Ok, so my form is going to be super-simple.
<?php
add_action( 'woocommerce_thankyou', 'misha_poll_form', 4 );
function misha_poll_form( $order_id ) {
?>
<h2>What do you think about my shop?</h2>
<form id="thankyou_form">
<label><input type="radio" name="like" value="superb"> Superb</label>
<label><input type="radio" name="like" value="good enough"> Good enough</label>
<label><input type="radio" name="like" value="could be better"> Could be better</label>
<input type="hidden" name="action" value="collect_feedback" />
<input type="hidden" name="order_id" value="<?php echo $order_id ?>" />
<?php wp_nonce_field( 'thankyou'.$order_id, 'thankyou_nonce' ) ?>
</form>
<?php
}
Some notes:
- Line 1 – If you set the hook priority to
9
and lower, the form will be displayed before the Order details section, if10
and higher – after the addresses section. - You do not see a submit button – I didn’t forget it, we are going to send this form with AJAX!
- Line 11 – Do not forget about a nonce, we need it for security reasons.
2. Send AJAX request
You can add the code to a .js file of course, but in that case do not forget to pass the url parameter correctly.
jQuery( function( $ ) {
$( 'input[type=radio][name=like]' ).change( function() {
$.ajax({
url: woocommerce_params.ajax_url,
type: 'POST',
data: $( '#thankyou_form' ).serialize(),
beforeSend: function( xhr ){
$( '#thankyou_form' ).html( 'Thank you! You feedback has been send!' );
},
success: function( data ){
console.log( data );
}
});
});
});
So, if you’ve done everything correctly, here is what you should got:

3. Process the AJAX request
Now the only thing left is to process the form. By the way, you can read more about AJAX requests in this category.
add_action( 'wp_ajax_collect_feedback', 'misha_thankyou_ajax' ); // wp_ajax_{ACTION}
add_action( 'wp_ajax_nopriv_collect_feedback', 'misha_thankyou_ajax' );
function misha_thankyou_ajax(){
// security check
check_ajax_referer( 'thankyou'. $_POST[ 'order_id' ], 'thankyou_nonce' );
$order = wc_get_order( $_POST[ 'order_id' ] );
$order->add_order_note( $order->get_formatted_billing_full_name() . ' thinks that the shop is ' . sanitize_text_field( $_POST[ 'like' ] ), 0, true );
die;
}
Go to the order edit page and find the Order notes metabox. Of course you can also change the order details with that form.


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
As you are an expert i want to ask you if any of your clients asked for woocommerce backend modifications. Why i ask is because i am trying to find a solution for woocommerce backend variants.
Here is the problem and it is not resolves yet by Woo.
Lets say we have just two variants on a product : Blue and Red
Blue is on stock, Red is out of stock
When you are editing your product in backend you have to expand every variantion just to see which one is in stock and which isnt.
When you have just two variants it is no problem, but with more!? When you have to check 20 varianta it is very time consuming.
I was wondering if you were asked in the past by a client to resolve this problem.
I was thinking that in backend when you edit a product and you go to variants, you can see which variants are in stock without expanding.
So, let s say the Blue variation is in stock therefor the background of this variant listing is green. This way when you check 20 variants you are not needed to expand every variant and you can see very clear which is on stock and which is not.
Thanks again Misha
I’ve looked through WooCommerce files and didn’t find a hook for that :(
Hey, Misha! Thanks for this post! However, I can’t seem to make the gateway redirect work :/ It’s exactly what I was desperatly in need, but it doesn’t work. Is the code up to date?
Thank you so much!
Hey Bianca,
It should work 🙃
Love the details lol! :)
Hello, I wanted to know how to show the field below Shipping address in metabox
Hey Paul,
Sure, this tutorial is for you.
Hi, thanks for your answer, I need to put the survey in thankyou page and show the result in admin page, not in private notes
Good,
I gave you the link to the appropriate tutorial then 👍
Thank you so much man. You are the best.
I know this is different, but how can I change the add to cart button (both on the shop page and on the single product page) when a customer has already ordered for that product.
In essence, I want 1 product to be sold to a customer for the lifetime of that product, and thus show it on the product (by changing the button and putting a sold-out kind of label) to only that customer.
See a pseduo-code that explains what I want to do:
1. Customer selects 1 product and add to cart,
2. Customer makes payment and purchases product. Order completed.
3. Customer comes to shop or single product page
4. Check if customer has purchased such product before
5. If yes, product’s add to cart button changes to “Any_text” & Product image is white washed with the sign “Already Purchased”
6. Else allow customer make purchase.
I know you might think I should be able to do this, but sincerely I don’t know how.
Thanks for your awesomeness once again.
Hi Rexy,
Thank you for the good question.
Try this in your
functions.php
Hi Misha,
How did AJAX work without
wp_localize_script()
?I tried with your code wihout extra JS file , but I got 404 error for ajax url.
Thank you for your help!
Cheers,
Chris
Hi Chris,
Hi, misha.
Thanks for this amazing tutorial. I learn so much from this, thanks again!
HI Misha,
Thank you for this tutorial, it is exactly what I need!
(I am creating a timed question on the thank you page)
I have implemented your code, straight up, and I get the following error in my console:
POST https://mydomain.com/wp-admin/admin-ajax.php 400 jquery.js?ver=1.12.4:4
I get the same error when I implement my timed question as well.
Any ideas why this is happening?
Cheers!
James
Hey James,
Hmmm… It looks like I forgot about
action
paremeter. Please update the code from this step, especially lines 10,11.Hi Misha,
Thank you for replying so quickly – it works now. Not sure if I was looking at an older version of the article or something.
Either way – keep up the good work mate!
James
You’re welcome! 🙃
There is no action specified in the ajax call.
How does ajax request gets processed in here?
Hey,
Here, step 1, line 10.
Got it!
Thanks
Hi Misha,
This is very helpful indeed.
Is it possible to show the order confirmation details but log the user out at the same time? As I need to force the customer to log back in before being able to view anything in the My Account section
I’ve tried using the hook ‘woocommerce_thankyou’ to log the user out, however, you then don’t see the default order confirmation details/thank you page. It also means I can’t use code to auto set orders to complete should I need to.
One thought is a custom thank you page. So I use the above hook to log them out, then redirect and perhaps use a GET variable in the redirect URL via something like this:
Then on the new thank you page, grab the variable (order ID?) from the URL and display the order details
However, I wonder if I’ve massively over looked the obvious?
Thanks
Hey Ian,
You’re doing everything right, a custom thank you page is the only way here, I think.
Thanks Misha,
My only thought is how to pass the order Id through to the custom page? Any ideas would be appreciated
Thanks again
In a short way the code will look like this:
But I recommend to pass order key instead and on your custom page use
wc_get_order_id_by_order_key()
function.Thanks Misha,
That’s fantastic!
Welcome! 🙃 🎉
Hi Misha
Maybe you can help me, i would like call a url after order payment.
As example :
http://url/delay?event={EVENT}&t={DELAY IN MINUTES}&key={YOUR KEY}
{EVENT} as product meta
{DELAY IN MINUTES} as product meta
{YOUR KEY} as product meta
What you think is possible or not?
Thank you for your answer :)
Hey Robert,
Do you want to redirect to that URL or to parse it? :)
:)
Redirect, (HTTP request POST or GET) iam complete newbie :).
{EVENT} sould be take from product meta or attributes
{DELAY IN MINUTES} sould be take from product meta or attributes
{YOUR KEY} sould be take from product meta or attributes
As example : i have one product with three different variable:
– 1 hour
– 2 hour
– 3 hour
{EVENT} and {YOUR KEY} for now its same
After the orders was placed, this script call this url.
Well,
There would be a lot of code but I can help you with a step by step instruction.
First step – you have to get your order ID and order object, you can do it with this line of code:
Second step, we have to get all the products from the order and get their meta, you can get product IDs from order items:
I assume there is just one product in each order?
And the last step, create a URL from the variables and perform a redirect:
Thanks for this tutorial, Misha. Any idea on how I could (pre)view the changes without having to simulate a purchase? For example, to see how it actually looks (CSS, images, etc.).
Thanks!
Hey Javier,
Sure, let me show you an example. On my test server order received URL looks like this
order-received/225/?key=wc_order_...
.Instead of 225 just pass an order ID.
To get
key
parameter value you can use this code:Hello Misha,
could you help mewith removin all customer and order details/tables from the Thank You page? So that is just displays the thank you message at the top? I know this is possible by commenting out code from the template, but can I remove them with a hook instaed?
Thank you!
Nina
Hey Nina,
Unfortunately there is no such hook available, unless you remove it with CSS in
wp_head
of course…Too bad! Would you then rather recommend editing the template in my child theme or just hiding it with CSS?
I would do it with template
Hi, I am having trouble making my thank you page endpoint having the product ID or SKU so that I can track my campaigns and what my clients purchase.
I see your post on gateway but what about product id??
Thanks in advance!
Hi Jaime,
Did you try
wc_get_order_id_by_order_key()
and then just get order items?Dear Misha!
Great tutorial, congratulations!
I would need to display some customer loyalty program information on the ‘thank you’ page, but by using a shortcode another plug-in supports.
Is there a way to insert a shortcode into the template so that it is replaced by actual content by the other plugin?
Best regards,
Attila
I managed to do it in the meantime, this way:
Hey,
For some reason you code has been cut out, I think you have implemented it with the help of
the_content
filter hook 🙃Hi
Very cool article very helpfull !!
Thank you!
But How to modify this code below in order to set up custom Thank You Page for every single product in the WC store?
Hi,
It all depends. How the thank you pages for products should be generated?
Great tutorial. I had a client site where YITH Custom Thank You plugin wasn’t working, so your post was a huge help.
Awesome!
Awesome. Alot of great things. Would like to add html code for reviews (pricerunner/other services) instead of the radiobutton one you created
Another awesome post Misha!
Anytime I search for something here you are with a solution.
I have a question. It is connected to a membership plugin for woocommerce. I would like to change the text of; “Thanks for purchasing a membership! You can view more details about your membership from your account.” on Order received page. Where could I find that info?
Any ideas?
Many thanks for sharing your knowledge!
Mario
Hey Mario,
I am so happy to hear that! 🙃
Please sorry for the late reply, currently I am orginizing WordCamp Saint Petersburg and also have some unexpected work related to my plugins…
I found a hook in the WooCommerce Memberships code:
So you could try to remove it. Another option is to use
gettext
filter to replace the texts.just passing through here and must say this is incredible. such a well written and clear article. why couldn’t all tutorials be this good.
Victor
For this code you shared…
…I have some questions (my apologies if it’s too many – feel free to answer only the simple ones):
1. Will doing this redirect break the flow in my Google Analytics tracking?
2. When multiple products are purchased and I have different thank you pages for different products, do I just put the most “important” thank you page first in the list in order to make sure it gets shown?
3. Would it be better to use wp_safe_redirect rather than wp_redirect?
4. Can I use the product SKU instead of the product ID? How about the product’s category?
1. I think yes, if it is connected to the default Thank you page.
2. Yes, but unfortunately the most simple way is to duplicate the whole
foreach
loop for both products.3. Nope, if the redirect URLs hardcoded in your code.
4. It is possible, but you have to use at least
get_post_meta()
to retrieve a product SKU.You save the world! Thank You.
Hello Misha, I used your code for the Poll, nice and simple.
Unfortunately it stopped working with the WordPress update.
I get an error on admin-ajax 400. Any idea how to fix this. I already tried
var ajaxurl = '<?php echo admin_url('admin-ajax.php') ?>';
but did do nothing.When I go to the
admin_url('admin-ajax.php')
in the browsers I get a 0 as response so it seems to be working.Any ideas?
Thank you
Jean Paul
Hi! thank you so much, its very useful!
I have a question for yo :D
how can show vendor information after purchase in the “Thank you page”?
For example, cellphone number, address…?
I want to say great thank you! You save my time and money!
Thank you for the great tutorial!! So helpful!! Is there a way to make this work for a category? For one or two items I want them to each have their own thank you page, but for the other two categories, I want one thank you page for each category. Can you please let me know if there is a way to specify a specific thank you page for a certain category of products? Thank you!
Thank you man. It was really useful!
It is an amazing post and you explained it in a detailed way. Nice to see this here.
I will bookmark your blog for more details. Keep sharing new things like this.
Hi, I have been using your code for a while and it works great!
I now want to have several products redirect to the same url. How can I add multiple product ids?
Hi Jessica,
Nice!
You can use a condition like this:
if( in_array( $item['product_id'], array( 1, 2, 5 ) ) {
(Line 14)
Yeaassss thank you! I’ve searched for a long time to find your post. This is finally the solution I needed 😍
Hi Misha, can you help me? How to show my customer username on Thank You page?
Nice work Misha, thanks !