WooCommerce: Check if User Has Bought Product in the Last 365 Days

A few snippets ago we introduced the magic WooCommerce inbuilt function “wc_customer_bought_product” – automatically, with a single line of PHP, you can find out if the user has already purchased a product ID.

But when building my new #BloomerArmada section, I had to know if a user purchased a product ID in the last 365 days… so I rewrote the function, changed its name and added a little edit to it – easy peasy!

The original “wc_customer_bought_product” function in WooCommerce

PHP Snippet: Check if User Has Bought Product ID in the Last 365 Days

 * @snippet       New version of "wc_customer_bought_product" function (last 365 days)
 * @how-to        Watch tutorial @ https://businessbloomer.com/?p=19055
 * @sourcecode    https://businessbloomer.com/?p=21885
 * @author        Rodolfo Melogli
 * @compatible    WC 3.3.4

function wc_customer_bought_product_last_365( $customer_email, $user_id, $product_id ) {
   global $wpdb;

	$result = apply_filters( 'woocommerce_pre_customer_bought_product', null, $customer_email, $user_id, $product_id );

	if ( null !== $result ) {
		return $result;

	$transient_name = 'wc_cbp_' . md5( $customer_email . $user_id . WC_Cache_Helper::get_transient_version( 'orders' ) );

	if ( false === ( $result = get_transient( $transient_name ) ) ) {
		$customer_data = array( $user_id );

		if ( $user_id ) {
			$user = get_user_by( 'id', $user_id );

			if ( isset( $user->user_email ) ) {
				$customer_data[] = $user->user_email;

		if ( is_email( $customer_email ) ) {
			$customer_data[] = $customer_email;

		$customer_data = array_map( 'esc_sql', array_filter( array_unique( $customer_data ) ) );
		$statuses      = array_map( 'esc_sql', wc_get_is_paid_statuses() );

		if ( sizeof( $customer_data ) == 0 ) {
			return false;

		$result = $wpdb->get_col( "
			SELECT im.meta_value FROM {$wpdb->posts} AS p
			INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id
			INNER JOIN {$wpdb->prefix}woocommerce_order_items AS i ON p.ID = i.order_id
			INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS im ON i.order_item_id = im.order_item_id
			WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
            AND p.post_date > '" . date('Y-m-d', strtotime('-365 days')) . "'
			AND pm.meta_key IN ( '_billing_email', '_customer_user' )
			AND im.meta_key IN ( '_product_id', '_variation_id' )
			AND im.meta_value != 0
			AND pm.meta_value IN ( '" . implode( "','", $customer_data ) . "' )
		" );
		$result = array_map( 'absint', $result );

		set_transient( $transient_name, $result, DAY_IN_SECONDS * 30 );
	return in_array( absint( $product_id ), $result );

Now that the “wc_customer_bought_product_last_year” exists in your functions.php, you can use it in a snippet or shortcode! The only major difference with “wc_customer_bought_product” is this line:

AND p.post_date > '" . date('Y-m-d', strtotime('-365 days')) . "'

Where to add this snippet?

You can place PHP snippets at the bottom of your child theme functions.php file (before "?>" if you have it). CSS, on the other hand, goes in your child theme style.css file. Make sure you know what you are doing when editing such files - if you need more guidance, please take a look at my free video tutorial "Where to Place WooCommerce Customization?"

Does this snippet (still) work?

Please let me know in the comments if everything worked as expected. I would be happy to revise the snippet if you report otherwise (please provide screenshots). I have tested this code with Storefront theme, the WooCommerce version listed above and a WordPress-friendly hosting on PHP 7+.

If you think this code saved you time & money, please join other Business Bloomer supporters and avail of 365 days of WooCommerce benefits. Thank you in advance :)

Need Help with WooCommerce Customization?

Check out these free video tutorials!

  • how-to-edit-woocommerce-with-php-snippets
  • woocommerce-hooks-add_action-list-visual
  • woocommerce-customize-single-product-page-PHP

Rodolfo Melogli

Author, WooCommerce expert and WordCamp speaker, Rodolfo has worked as a WooCommerce freelancer since 2011. His goal is to help entrepreneurs and developers overcome their WooCommerce nightmares. Rodolfo loves travelling, chasing tennis & soccer balls and, of course, wood fired oven pizza.

6 thoughts on “WooCommerce: Check if User Has Bought Product in the Last 365 Days

  1. I do not get this to work.
    I got 3 products reflecting 365 days, 30 days and 7 days, 1 customer has bought both 365 days and 7 days, the 7 days are gone (more than 7 days since bought), yet both returns true.
    I added a parameter in the function to pass the days into the function.
    if any of the products are bought within the given days day should “give access” to certain content.
    i check first for 365 days then 30 days and then 7 days.
    shouldnt the 7 days return false?

    1. Hi there, thanks so much for your comment! Yes, this can be fixed, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  2. You is better!

    1. Thanks!

  3. Thanks a bunch !!!

    1. You’re welcome Nadia!

Questions? Feedback? Support? Leave your Comment Now!

If you are writing code, please wrap it between: [php]code_here[/php]. Failure to complying with this (as well as going off topic) will result in comment deletion. You should expect a reply in about a week - this is a popular blog but I need to get paid work done first. Please consider joining #BloomerArmada to ask me 1-to-1 WooCommerce questions. Thank you :)

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.