Do something after WooCommerce order completed with woocommerce_order_status_completed

If you want to do something after WooCommerce order completed you can hook into woocommerce_order_status_completed.

Here is a Gist with sample code:

Thanks to @mikejolley for the pointer 🙂

Reader Interactions


  1. Hello, maby you can help,

    The email notifications from woocommerce are not working. I see many topics on the internet with the same problems.

    Thanks anyway, regards Wout from The Netherlands

  2. Is $order_id automatically passed to myFunction() when ‘woocommerce_order_status_completed’ is triggered?
    Also, where should I put the add_action() line? In my functions.php file of the woocommerce folder?

    • Yes, $order_id is passed. You would put the add_action in a plugin file or functions.php.

      • Hi Daan,
        if I put the the code into the file function.php rise the follow ERROR:
        Fatal error: Call to undefined function add_action() in …WWW.DOAMIN.COM\wp-includes\functions.php on line nnn !!

        • Hard to tell but I suspect you pasted the code in the wrong functions.php file. You need to add it to functions.php in your theme. And rename my_function() to something usefull.

  3. Hello,
    Thanks for this post. I have a question : is there a specific hook to use is we want to make an action after paypal paiement is OK (in order to be sure that paiement is effective)?

    • Sure, happy to help. If you really need to go in depth you can try asking Mike Jolley for help. If he doesn’t know, nobody knows 😉

  4. This doesn’t appear to do anything. Could it not be working in the latest versions?

    I place a line with `echo “hello”` inside of that function but nothing seems to happen after coming back from placing the order.

    I’m interested in custom thank-you pages based upon the product purchased.

    • This hook is for internal processing. It won’t do anything to display to buyers by itself. When a buyer comes back from a payment it does not mean the payment is complete. Only after payment has been cleared this hook will run or if you manually click “complete” on the order (in wp-admin).

      Best to read the documentation:
      As far as documentation goes, the WooThemes does a really good job. There aren’t many companies that do.

      • So if this won’t run until “payment is complete” then I guess it’s not what I need. Like I said, just looking to redirect users to different pages based on which product is purchased. So for my needs, I need this to happen immediately after they come back from making the payment. Ideas? Thanks!

  5. You’re putting yourself out there as an expert taking questions, so IMHO, “RTFM” is always rude unless you want to discourage people from participating on your blog.

    DId I read the manual cover to cover? Of course not. Did I search, browse, and use it as reference material? YES, and still could not figure out how to start. I only politely asked for ideas, to be pointed in the right direction… I never expected anyone write the solution for me.

    Anyway, thank-you for showing the two hooks… that’s enough to get started.

    • Sorry you feel that way, you’re welcome all the same and I hope you can solve the problem you had.

  6. Hello,

    I am wanting to put the first product tag (only) in a variable. I was hoping something like $item[‘product_tags’] would work. Tried various things without any luck. Any idea how I can get the tags?

    Many thanks

  7. Hi thank you for this articl,

    Is there a hook before woocommerce_order_status_completed is fired?

    I have installed a fedex labelling plugin that creates fedex label of a particular order and produces fedex tracking number. What i want to do is to create a condition that checks if the fedex tracking number is already generated when the user marks a particular order as COMPLETE or PAYMENT COMPLETED.


  8. Hello, I added an action to woocommerce_thankyou that has a 45 second delay in it and it causes the page to hang while it executes. I was wondering if there was some way hook this to an action that could fire after the woocommerce thankyou.php page has been built. I’ve already tried adding my own do_action at the end of the script but that didn’t work. The page still hangs for 45 seconds.

    This is the action and its function…

    add_action(‘woocommerce_thankyou’, ‘call_restaurant’);

    function call_restaurant() {

    require_once ‘/home/mywebsite/public_html/voice/Services/call.php’;

    $sid = “bla bla bla”;
    $token = “bla bla bla”;

    $from_number = “3055478873”; // Calls must be made from a registered Twilio number.
    $to_number = “3058345058”;
    $message = “Hello. You have received a new order from eat three sixty five miami dot com”;

    $client = new Services_Twilio($sid, $token, “2010-04-01”);
    $call = $client->account->calls->create(
    echo ‘phone call has been made’;


    The reason that I’m doing this is because I am trying to place an automated phone call 45 seconds after the order is made.

    Any help is greatly appreciated.

  9. Hi Daan,

    I’m trying to create an order in other website when an order is created in my woocommerce site. I’m creating the orders through APIs and the code to create an order in the other site is working when I put the code with the data to send in a php file. The problem I have is that I can’t send automatically when an order is created in Woocommerce. I have the following code in mytheme/functions.php

    add_action( ‘woocommerce_order_status_completed’, ‘bringg_order’);
    function bringg_order($order_id){
    $order = new WC_order($order_id);
    $order_data = array(
    ‘customer_id’ => $order->id,
    ‘created_at’ => $this->server->format_datetime( $order_post->post_date_gmt ),
    ‘completed_at’ => $this->server->format_datetime( $order->completed_date, true ),
    ‘status’ => $order->get_status(),
    ‘company_id’ => ‘3494’,
    ‘total_price’ => wc_format_decimal( $order->get_total(), 2 ),
    ‘access_token’ => “XXXXX(its private)”,
    ‘note’ => $order->payment_method_title,
    ‘address’ => $order->billing_address_1,
    ’email’ =>$order->billing_email,
    ‘phone’ =>$order->billing_phone
    ) ;

    // Send order to my website through API

    $url = ‘http://developer-a’;
    $secret_key = “XXXXXX”;
    $signature = hash_hmac(“sha1”, http_build_query($order_data), $secret_key);
    $order_data[“signature”] = $signature;
    Class RestCurl {
    public static function exec($method, $url, $obj = array()) {

    $curl = curl_init();

    switch($method) {
    case ‘GET’:
    if(strrpos($url, “?”) === FALSE) {
    $url .= ‘?’ . http_build_query($obj);
    case ‘POST’:
    curl_setopt($curl, CURLOPT_POST, TRUE);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($obj));
    case ‘PUT’:
    case ‘DELETE’:
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, strtoupper($method)); // method
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($obj)); // body
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array(‘Accept: application/json’, ‘Content-Type: application/json’));
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_HEADER, TRUE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, TRUE);

    // Exec
    $response = curl_exec($curl);
    $info = curl_getinfo($curl);

    // Data
    $header = trim(substr($response, 0, $info[‘header_size’]));
    $body = substr($response, $info[‘header_size’]);

    return array(‘status’ => $info[‘http_code’], ‘header’ => $header, ‘data’ => json_decode($body));
    public static function get($url, $obj = array()) {
    return RestCurl::exec(“GET”, $url, $obj);
    public static function post($url, $obj = array()) {
    return RestCurl::exec(“POST”, $url, $obj);
    public static function put($url, $obj = array()) {
    return RestCurl::exec(“PUT”, $url, $obj);
    public static function delete($url, $obj = array()) {
    return RestCurl::exec(“DELETE”, $url, $obj);

    $result1 = RestCurl::post($url, $order_data);


    The part of the “Send order to my website through API” is working when I put it in a php file and I open it. But when I include the part of automatically generate the order when a new order is created in woocommerce is not working, when I create an order nothing happens.

    Which could be the problem?

    Thanks !

  10. Hi Daan, i added this action but when its executed i try to read wp_pmpro_memberships_users but in this moment have no updated. Its there any action allow me to read this table updated whith the new member registry?

    Thanks in advance!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.