I want to create a CTA button/menu link that will only be visible to people that haven't bought a certain product on my site. The button shouldn't be visible to subscribers that already bought the product. I am using WooCommerce to create the products.

Thanks everyone

  • The idea of this forum is that you bring your ideas and code for discussion - and other provides feedback and help - please read more, take a first go and share your results and any errors or information.
    – Q Studio
    Jan 6 at 8:47
  • @QStudio This isn't a discussion forum, it's for questions that can be answered with a definitive answer, not back and forth discussion or code review. Jan 6 at 9:47
  • That might be the aim of the forum, but the reality is not quiet the same, regardless, my point was that the question needed more detail to be answerable.. please feel free to take this on from here.
    – Q Studio
    Jan 6 at 9:53

First define a function to check if user has bought product before.

// function to check product bought by user before

function has_bought_items( $user_var = 0,  $product_ids = 0 ) {
    global $wpdb;
    // Based on user ID (registered users)
    if ( is_numeric( $user_var) ) { 
        $meta_key     = '_customer_user';
        $meta_value   = $user_var == 0 ? (int) get_current_user_id() : (int) $user_var;
    // Based on billing email (Guest users)
    else { 
        $meta_key     = '_billing_email';
        $meta_value   = sanitize_email( $user_var );
    $paid_statuses    = array_map( 'esc_sql', wc_get_is_paid_statuses() );
    $product_ids      = is_array( $product_ids ) ? implode(',', $product_ids) : $product_ids;

    $line_meta_value  = $product_ids !=  ( 0 || '' ) ? 'AND woim.meta_value IN ('.$product_ids.')' : 'AND woim.meta_value != 0';

    // Count the number of products
    $count = $wpdb->get_var( "
        SELECT COUNT(p.ID) FROM {$wpdb->prefix}posts AS p
        INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON p.ID = woi.order_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
        WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $paid_statuses ) . "' )
        AND pm.meta_key = '$meta_key'
        AND pm.meta_value = '$meta_value'
        AND woim.meta_key IN ( '_product_id', '_variation_id' ) $line_meta_value 
    " );

    // Return true if count is higher than 0 (or false)
    return $count > 0 ? true : false;

After that Create a shortcode to display CTA if user has not bought product:

function cta_shortcode() { 
    $cta= '<a href="#">Buy This Product</a>'; 
    return has_bought_items() ? "" : $cta;

// register shortcode
add_shortcode('cta-shortcode', 'cta_shortcode'); 

Finally you can use this shortcode to conditionally show cta to users.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.