Connect with us


WooCommerce Function Of The Week: wc_get_customer_total_spent



WooCommerce Function Of The Week: wc_get_customer_total_spent

Quickly identify your top-paying customers and get the total amount spent for each in WooCommerce. Perfect for a VIP rewards program.

WooCommerce is full of unknown gems for developers. For example, there are some core functions that calculate pretty complex data, and these functions are mainly “public” so that WooCommerce developers can reuse them for their own purposes.

Today, let’s take a look at the wc_get_customer_total_spent( $user_id ) WooCommerce PHP function.

As you can guess by its name, this function returns the total amount spent by a given customer identified by their user ID. There is no need to loop through user orders to add up totals and return a final sum — WooCommerce already has you covered.

So, let’s take a deeper look at the syntax, meaning, and usage of wc_get_customer_total_spent.

Function source code and description

You can find the wc_get_customer_total_spent function under woocommerce\includes\wc-user-functions.php. Clearly, it’s a function that gets a user ID and returns the total spent by that user as a string:

 * Get total spent by customer.
 * @param  int $user_id User ID.
 * @return string
function wc_get_customer_total_spent( $user_id ) {
	$customer = new WC_Customer( $user_id );
	return $customer->get_total_spent();

The first question that comes to mind is which order statuses are counted toward the total amount spent?

The answer might be inside the get_total_spent function in woocommerce\includes\class-wc-customer.php:

 * Return how much money this customer has spent.
 * @return float
public function get_total_spent() {
	return $this->data_store->get_total_spent( $this );

Actually, we also need to look at WC_Customer_Data_Store::get_total_spent() in woocommerce/includes/data-stores/class-wc-customer-data-store.php:

 * Return how much money this customer has spent.
 * @since 3.0.0
 * @param WC_Customer $customer Customer object.
 * @return float
public function get_total_spent( &$customer ) {
	$spent = apply_filters(
		get_user_meta( $customer->get_id(), '_money_spent', true ),
	if ( '' === $spent ) {
		global $wpdb;
		$statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );
		$spent    = $wpdb->get_var(
			// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
				"SELECT SUM(meta2.meta_value)
				FROM $wpdb->posts as posts
				LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
				LEFT JOIN {$wpdb->postmeta} AS meta2 ON posts.ID = meta2.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 ( 'wc-" . implode( "','wc-", $statuses ) . "' )
				AND     meta2.meta_key      = '_order_total'",
			// phpcs:enable
		if ( ! $spent ) {
			$spent = 0;
		update_user_meta( $customer->get_id(), '_money_spent', $spent );
	return wc_format_decimal( $spent, 2 );

Finally, we have the full picture of how the wc_get_customer_total_spent function works:

  1. First it checks if the customer/user has _money_spent metadata. If not, there’s no need to query the database.
  2. If _money_spent is null, the function queries the database for all orders placed by the customer ID. The only order statuses to be counted are wc_get_is_paid_statuses ones. If you do a file search for that function, you’ll see that by default it only includes completed and processing order statuses, unless you’ve added custom order statuses to the paid statuses array
  3. After the database call, the total sum is calculated and stored it in the _money_spent customer meta, so that next time the function can run faster by avoiding yet another query.

An interesting observation: get_total_spent returns a floating-point number with two decimals by default (unless you specify otherwise via the WooCommerce settings or a PHP filter hook), while wc_get_customer_total_spent declares that the total is returned as a string. That’s a mystery! Probably a mistake, too, as it should definitely be a float.

Function usage

Clearly, wc_get_customer_total_spent can be really useful for a store with an active and established customer base.

A good use case for wc_get_customer_total_spent that immediately comes to mind is a VIP section dedicated to customers who have spent more than a given amount. You could display thank you messages, special offers, unlock benefits, and create targeted VIP marketing messages.

A good place to display a VIP status or message is the WooCommerce “My Account dashboard page” and header notification bar for logged-in customers. Then your VIP customers will see a special notice just for them when they log in.

Here’s an example:

 * @snippet       Show Notice If Customer Spent > $500 @ My Account
 * @how-to        Get FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 6
 * @donate $9
add_action( 'woocommerce_account_dashboard', 'bbloomer_my_account_notice_if_customer_spent' );
function bbloomer_my_account_notice_if_customer_spent() {
   $user_id = get_current_user_id();
   if ( wc_get_customer_total_spent( $user_id ) > 500 ) {
      echo '<div class="woocommerce-message"><a class="button" href="">Browse VIP-only products</a> Congratulations, you are a VIP member!</div>';

Here’s how I use it on Business Bloomer:

If the customer has spent more than $500, this message will show in the My Account > Dashboard page

WooCommerce by default has a single currency, so wc_get_customer_total_spent may not be usable with multi-currency stores without a special workaround. Have you encountered this situation and come up with a solution? Let us know in the comments.

Do the Woo

Do the Woo! Get the Podcast. Subscribe to the Newsletter.

Learn from others. Grow your business. Connect with a community of like-minded developers and builders who freelance, run agencies and build really cool products and sites in the WooCommerce ecosystem.

Source link

Continue Reading
Click to comment

Leave a Reply

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