WooCommerce New vs Returning Customers

Alpha Insights

Boost Your ROAS.

Connecting WooCommerce Orders To Your Ad Campaigns Is Just The Beginning...

WooCommerce Cost Of Goods Order Profit Reports

How to Determine If A WooCommerce Order Is A Customer's First

In this article we will provide you with a PHP snippet to determine if an order is a customer’s first order.

We will also show you how to display this in the order admin column in the WooCommerce orders page if you would like to.

Below is a screenshot example of the WooCommerce Orders page which has been extended by our Profit Reporting Plugin Alpha Insights which includes a custom column for new vs returning customers.

With the provided function, you’ll be able to use the logic in many areas of your website, based on the order.

Drop us a comment if you want to know how to add this information anywhere else.

PHP Snippet -> The Function Which Determines If An Order Is A Customer's First

If you add this to your functions.php file it will allow you to use this function anywhere you need, this function will need the order object or order_id passed into it.

How does this function work?

This function will search for any orders older than the one being looked at, which have the same billing address.

Billing address has been assumed as the best unique identifier to account for guest orders vs registered user orders.

This function will simply return a true or false depending on the results. It will return true if this is the first order found by this email address, or false if it is not their first order or if there was an error in the function.

Paste the following code into your functions.php

				
					/**
 * 
 * 	Calculates whether this order is the first order for a particular customer
 * 	Will check the order's date created and search backward to see if any other orders have been placed by this email address (so that we are checking guests too)
 * 
 * 	@author Christopher Davies -> WP Davies
 * 	@link https://wpdavies.dev/woocommerce-new-vs-returning-customers/
 *  @param WC_Order|int $order Order object or order_id
 *  @return bool $bool True if this is this customer's first order, false if they've ordered prior to this order date
 * 
 **/
function wpd_customers_first_order( $order ) {
	
	// Check if we've passed an Order ID
	if ( is_int($order) && $order > 0 ) {
		$order = wc_get_order( $order );
	}

	// Safety check
	if ( ! is_a( $order, 'WC_Order' ) ) return false;

	// Date created
	$date_created =  $order->get_date_created();
	if ( is_a($date_created, 'WC_DateTime') ) {
		$date_created = $date_created->getTimestamp(); // Must use gettimestamp not getoffsettimestamp
	} else {
		return false; // Can't check a date?
	}

	// Unique Identifier
	$billing_email = $order->get_billing_email();

	// New customer if they haven't got a billing email?
	if ( empty($billing_email) ) {
		return true;
	}

	// Search for orders with the same billing address that are older than this order
	$args = array(
		'limit' 		=> 1,
		'billing_email' => $billing_email,
		'date_created' 	=> '<' . $date_created, // This must be in UTC -> causing issues when we compare against offset timestamp
		'return' 		=> 'ids',
	);

	// Search for orders
	$orders = wc_get_orders( $args );

	if ( empty($orders) ) {

		return true; // No orders found, this must be the first

	} else {

		return false; // If we've found orders, then this isn't the first

	}

}
				
			

How Do I Use The New vs Returning Customer Function?

You can pass either the Order ID or Order Object into the function, storing it as a boolean value which you can then use with your logic.

				
					// If you have the Order ID
$customers_first_order = wpd_customers_first_order( $order_id );

// If you have the order object
$customers_first_order = wpd_customers_first_order( $order );

if ( $customers_first_order ) {

	// Customer's first order, proceed with logic..

} else {

	// Not the customer's first order, proceed with logic..

}
				
			

How To Setup A New vs Returning Customer Column For WooCommerce Orders?

The below is the final result, if you’ve copy pasted the earlier function in make sure you remove it, you only want one occurrence of the same functions otherwise it will trigger a fatal error.

To setup the custom column, you will need to register the column and then setup the data to be output into the column.

You can also copy paste the below snippet into your functions.php which should do both of these for you.

The display settings latch onto WooCommerce’s native order styles, but you can adjust to suit.

If you are just looking for a way to register the column in the first image, you can copy paste the entire snippet below. It will do everything you need it to.

				
					/**
 *
 * 	Calculates whether this order is the first order for a particular customer
 * 	Will check the order's date created and search backward to see if any other orders have been placed by this email address (so that we are checking guests too)
 *
 * 	@author Christopher Davies -> WP Davies
 * 	@link https://wpdavies.dev/woocommerce-new-vs-returning-customers/
 *  @param WC_Order|int $order Order object or order_id
 *  @return bool $bool True if this is this customer's first order, false if they've ordered prior to this order date
 *
 **/
function wpd_customers_first_order( $order ) {

	// Check if we've passed an Order ID
	if ( is_int($order) && $order > 0 ) {
		$order = wc_get_order( $order );
	}

	// Safety check
	if ( ! is_a( $order, 'WC_Order' ) ) return false;

	// Date created
	$date_created =  $order->get_date_created();
	if ( is_a($date_created, 'WC_DateTime') ) {
		$date_created = $date_created->getTimestamp(); // Must use gettimestamp not getoffsettimestamp
	} else {
		return false; // Can't check a date?
	}

	// Unique Identifier
	$billing_email = $order->get_billing_email();

	// New customer if they haven't got a billing email?
	if ( empty($billing_email) ) {
		return true;
	}

	// Search for orders with the same billing address that are older than this order
	$args = array(
		'limit' 		=> 1,
		'billing_email' => $billing_email,
		'date_created' 	=> '<' . $date_created, // This must be in UTC -> causing issues when we compare against offset timestamp
		'return' 		=> 'ids',
	);

	// Search for orders
	$orders = wc_get_orders( $args );

	if ( empty($orders) ) {

		return true; // No orders found, this must be the first

	} else {

		return false; // If we've found orders, then this isn't the first

	}

}

/**
 * 
 * 	Registers the new custom column
 * 
 * 	@author Christopher Davies -> WP Davies
 * 	@link https://wpdavies.dev/woocommerce-new-vs-returning-customers/
 *  @param array $columns The array of columns to display in the WooCommerce Orders page
 * 
 **/
add_filter( 'manage_edit-shop_order_columns', 'wpd_register_admin_order_columns', 10, 1 );
add_filter( 'manage_woocommerce_page_wc-orders_columns', 'wpd_register_admin_order_columns', 10, 1 ); // HPOS
function wpd_register_admin_order_columns( $columns ) {

	$columns['wpd_new_vs_returning_customers'] 	= __( 'New vs Returning', 'wpd-alpha-insights' );

	return $columns;

}

/**
 * 
 * 	Fills out the New vs Returning Customer column in HPOS and Standard WooCommerce Mode
 * 
 * 	@author Christopher Davies -> WP Davies
 * 	@link https://wpdavies.dev/woocommerce-new-vs-returning-customers/
 *  @param string $column The Column Name
 * 	@param int|WC_Order $post_id_or_order_object The post ID or order object depending on if you're using HPOS or not
 * 
 **/
add_action( 'manage_shop_order_posts_custom_column', 'wpd_display_admin_order_column_data', 10, 2 );
add_action( 'woocommerce_shop_order_list_table_custom_column', 'wpd_display_admin_order_column_data', 10, 2 ); // HPOS
function wpd_display_admin_order_column_data( $column, $post_id_or_order_object ) {

	// Add contents into column
	if ( 'wpd_new_vs_returning_customers' == $column ) {

		// Get order ID (HPOS compatible)
		if ( is_a($post_id_or_order_object, 'WC_Order') ) {

			$order_id = $post_id_or_order_object->get_id();

		} else {

			if ( is_numeric($post_id_or_order_object) && $post_id_or_order_object > 0 ) {

				$order_id = $post_id_or_order_object;

			} else {

				global $post;
				$order_id = $post->ID;

			}

		}

		// Is this their first order?
		$customers_first_order = wpd_customers_first_order( $order_id );

		// Define labels
		$new_returning = ( $customers_first_order ) ? 'New Customer' : 'Returning Customer';
		
		// Setup a Data Tip (On Hover info)
		$data_tip = ( $customers_first_order ) ? 'This is the first order placed by this email address' : 'This email address has placed an order prior to this date';
		
		// Output Info
		echo '<mark class="wpd-new-vs-returning-customer order-status tips customer-'.strtolower( $new_returning ).'" data-tip="'.$data_tip.'"><span>'.ucfirst( $new_returning ) .' Customer</span></mark>';

	}

}
				
			

That’s it! As always, happy coding and feel free to leave a comment below if you have any questions or requests.

Thanks, Chris

Subscribe
Notify of
guest
0 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments

Alpha Insights

The World's Most Advanced WooCommerce Reporting Plugin.

WooCommerce Cost Of Goods Order Profit Reports

Want To Grow Your Store?

Join our newsletter for 25% off on all of our plugins & services, exclusive access to eCommerce content & personalized WooCommerce development support.

Alpha Insights

Alpha Insights

The World's Most Advanced WooCommerce Reporting Plugin.

WooCommerce Cost Of Goods Order Profit Reports