This week we’ll take a look at WooCommerce orders and a neat WooCommerce core function called wc_get_customer_last_order
.
Nothing mysterious here — pass a customer ID, and with a PHP one-liner, you get immediately the customer’s latest order!
This can be used in several scenarios. Think for example of an email campaign that triggers six months after the customer’s last order to entice them to reorder. (In marketing, you’d call it a “Win-Back” campaign.)
But before looking at some case studies, let’s analyze the function syntax and source code.
Function Syntax
wc_get_customer_last_order()
function is under woocommerce\includes\wc-user-functions.php
:
/**
* Get info about customer's last order.
*
* @since 2.6.0
* @param int $customer_id Customer ID.
* @return WC_Order|bool Order object if successful or false.
*/
function wc_get_customer_last_order( $customer_id ) {
$customer = new WC_Customer( $customer_id );
return $customer->get_last_order();
}
I personally go mad when I see blank lines for no apparent reason within WooCommerce core functions, but that’s just me. 😃
The wc_get_custmer_last_order()
function returns the output of another function called get_last_order()
that you can find under woocommerce\includes\data-stores\class-wc-customer-data-store.php
:
/**
* Gets the customers last order.
*
* @since 3.0.0
* @param WC_Customer $customer Customer object.
* @return WC_Order|false
*/
public function get_last_order( &$customer ) {
$last_order = apply_filters(
'woocommerce_customer_get_last_order',
get_user_meta( $customer->get_id(), '_last_order', true ),
$customer
);
if ( '' === $last_order ) {
global $wpdb;
$last_order = $wpdb->get_var(
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
"SELECT posts.ID
FROM $wpdb->posts AS posts
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
WHERE meta.meta_key = '_customer_user'
AND meta.meta_value = '" . esc_sql( $customer->get_id() ) . "'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array_map( 'esc_sql', array_keys( wc_get_order_statuses() ) ) ) . "' )
ORDER BY posts.ID DESC"
// phpcs:enable
);
update_user_meta( $customer->get_id(), '_last_order', $last_order );
}
if ( ! $last_order ) {
return false;
}
return wc_get_order( absint( $last_order ) );
}
Well, that’s an easy one to understand: get_last_order
calls the WordPress database, selects the posts and postmeta tables, sets the customer ID, and looks for the shop order with the greatest ID — which means it’s the most recent order.
In return, we get the $order
object.
Brilliant!
Simply declare a customer ID, call wc_get_customer_last_order( $customer_id )
, and get whatever data you need.
Take a look at my WooCommerce: Get Order Info (total, items, etc) From $order
Object tutorial to learn how to get any kind of data from that last order, such as the paid-on date, its product IDs, or even the total amount transacted.
Case Studies
Earlier we mentioned a Win-Back campaign as a scenario where your customers’ last orders might be a way to re-engage them. It could be as simple as defining a time period (based on your business and customer patterns), and then sending a “come back!” email. Or display a message to customers who didn’t place an order within that timeframe.
Let’s consider the second option — displaying a notification message to logged-in customers if they haven’t placed an order in the last 6 months. Here’s how I do it:
/**
* @snippet Win-Back notice | WooCommerce My Account
* @how-to Get CustomizeWoo.com FREE
* @author Rodolfo Melogli
* @compatible WooCommerce 6
* @donate $9 https://businessbloomer.com/bloomer-armada/
*/
add_action( 'woocommerce_account_content', 'bbloomer_notice_if_ordered_7_months_ago' );
function bbloomer_notice_if_ordered_7_months_ago() {
$customer_id = get_current_user_id();
$last_order = wc_get_customer_last_order( $customer_id );
if ( ! $last_order ) return; // BAIL IF NO PREVIOUS ORDERS
if ( time() > strtotime( $last_order->get_date_created() . ' +6 months' ) ) {
wc_add_notice( 'Been a while! Use coupon code XXXYYYZZZ for 10% off today!', 'notice' ); // WP_PRINT_NOTICE MAY WORK BETTER? PLEASE TEST
}
}
Screenshot:
Other case studies could see the use of wc_get_customer_last_order
function to determine a specific product offer. (For example, “Buy product XYZ again ad get 15% off today!”)
To do this, you’d simply loop through the order items, and then use my WooCommerce: Set / Override Product Price Programmatically guide to set the price for the logged-in customer.
Also, you could use wc_get_customer_last_order
for special offers, such as giving away a freebie in case the last order total is > $200.
What would you use the wc_get_customer_last_order
for? I’m curious — let me know in the comments!
Nice snippet. Thanks. However if someone gets holds of the coupon code and shares it with the friends, they would be able to use the code as well. We also need to prevent it at coupon level, so when user applies the coupon, we only allow it if the customer hasn’t placed any order for last 6 months. Not sure which filter for coupon can be used in combination with this here. Any ideas?
There’s a technical answer to that question I’m sure Rodolfo can answer, but it seems like a generally bad move to worry about blocking coupon abuse when you can simply limit the coupon settings to one per person and set a cap on how many will be accepted. Then keep an eye on what happens. If additional people (existing or new customers) place orders they wouldn’t have made without a coupon, is that a problem? In what actual business case would it be bad for a coupon to be used beyond its intended recipients? Those are leads and sales!
Hey Sachin, thanks for your comment!
I think Smart Coupons extension allows your logged in customers to generate a coupon on click: https://woocommerce.com/document/smart-coupons/how-to-auto-generate-coupons-using-shortcode/ – in that case I guess you can pick the parameters you want and hide the coupon code unless clicked/used
Hope this helps!