WooCommerce Product User Wishlist Favorite Like System, Logged Users Only

If you need a very very simple wishlist button for woocommerce here you go enjoy.

This code adds 2 shortcode one for product page and one for wishlist page itself.

The current user can add products to its own wishlist. Wishlist is just a simple array in the user profile custom field.

I didn’t add any CSS styling do that yourself 😉

For Product Single Page: [add_to_wishlist_button]

For Wishlist Page: [user_wishlist]

For the count: [wishlist_count]

it is possible to loop the user_wishlist easily as well instead of using shortcode here;

$user_id = get_current_user_id();
$wishlist = get_user_meta($user_id, 'wishlist_products', true);

return [
    'post_type'      => 'product',
    'post_status'    => 'publish',
    'posts_per_page' => -1,
    'post__in'       => $wishlist,
];

this is the code to run this system add somewhere in fucntions.php

<?php
// [add_to_wishlist_button] 
// [user_wishlist] 
// [wishlist_count]

function wishlist_inline_scripts() {
	?>
	<script>
		document.addEventListener('DOMContentLoaded', function() {
			var wishlistButtons = document.querySelectorAll('.add-to-wishlist');
			wishlistButtons.forEach(function(button) {
				button.addEventListener('click', function() {
					var productId = this.getAttribute('data-product-id');
					var messageDiv = this.nextElementSibling;
					var button = this;

					var xhr = new XMLHttpRequest();
					xhr.open('POST', '<?php echo esc_url(admin_url("admin-ajax.php")); ?>', true);
					xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

					xhr.onreadystatechange = function() {
						if (xhr.readyState === 4 && xhr.status === 200) {
							messageDiv.textContent = xhr.responseText;

							// Toggle button emoji based on response
							if (xhr.responseText.includes('added')) {
								button.innerHTML = '<img src="/wp-content/uploads/2025/01/liked.png" >'; 
							} else if (xhr.responseText.includes('removed')) {
								button.innerHTML = '<img src="/wp-content/uploads/2025/01/like.png" >'; 
							}
						} else if (xhr.readyState === 4) {
							messageDiv.textContent = 'An error occurred. Please try again.';
						}
					};

					xhr.send('action=toggle_wishlist&product_id=' + encodeURIComponent(productId) + '&nonce=<?php echo wp_create_nonce("wishlist_nonce"); ?>');
				});
			});
		});
	</script>
	<?php
}
add_action('wp_footer', 'wishlist_inline_scripts');

// Shortcode to add "Add to/Delete from Wishlist" button
function add_to_wishlist_button() {
	if (is_user_logged_in()) {
		$product_id = get_the_ID();
		$user_id    = get_current_user_id();
		$wishlist   = get_user_meta($user_id, 'wishlist_products', true);
		$in_wishlist = in_array($product_id, (array) $wishlist);
		$button_emoji = $in_wishlist ? '<img src="/wp-content/uploads/2025/01/liked.png" >' : '<img src="/wp-content/uploads/2025/01/like.png" >'; 

		return '<button 
		class="add-to-wishlist" 
		data-balloon="Wishlist" 
		data-balloon-pos="top" 
		data-product-id="' . esc_attr($product_id) . '">' . $button_emoji . '</button>
		<div class="wishlist-message"></div>';
	} else {
		return '<p><a href="' . esc_url(wp_login_url(get_permalink())) . '" class="wishlist-shortcode-link">Log in</a> to wishlist.</p>';
	}
}
add_shortcode('add_to_wishlist_button', 'add_to_wishlist_button');

// AJAX handler to toggle wishlist items
function handle_toggle_wishlist() {
	if (is_user_logged_in() && isset($_POST['product_id']) && wp_verify_nonce($_POST['nonce'], 'wishlist_nonce')) {
		$user_id = get_current_user_id();
		$product_id = intval($_POST['product_id']);

		if (get_post_type($product_id) === 'product') {
			$wishlist = get_user_meta($user_id, 'wishlist_products', true);
			if (empty($wishlist)) {
				$wishlist = [];
			}

			if (!in_array($product_id, $wishlist)) {
				$wishlist[] = $product_id;
				update_user_meta($user_id, 'wishlist_products', $wishlist);
				echo 'Product added to wishlist!';
			} else {
				$wishlist = array_diff($wishlist, [$product_id]);
				update_user_meta($user_id, 'wishlist_products', $wishlist);
				echo 'Product removed from wishlist!';
			}
		} else {
			echo 'Invalid product.';
		}
	} else {
		echo 'Error: Invalid request or you need to log in to modify wishlist.';
	}
	wp_die();
}
add_action('wp_ajax_toggle_wishlist', 'handle_toggle_wishlist');

// Shortcode to display the user's wishlist
function display_user_wishlist() {
	if (is_user_logged_in()) {
		$user_id  = get_current_user_id();
		$wishlist = get_user_meta($user_id, 'wishlist_products', true);

		if (!empty($wishlist)) {
			$output = '<ul class="user-wishlist">';
			foreach ($wishlist as $product_id) {
				$product = wc_get_product($product_id);
				if ($product) {
					$output .= '<li>
                                    <a href="' . esc_url(get_permalink($product_id)) . '">' 
						. get_the_post_thumbnail($product_id) . '<br>' . esc_html($product->get_name()) . 
						'</a>
                                </li>';
				}
			}
			$output .= '</ul>';
		} else {
			$output = '<p>You have no wishlist products.</p>';
		}
		return $output;
	} else {
		return '<p>You need to <a href="' . esc_url(wp_login_url(get_permalink())) . '" class="wishlist-list-shortcode-link">log in</a> to see your wishlist.</p>';
	}
}
add_shortcode('user_wishlist', 'display_user_wishlist');

// New shortcode to display the wishlist count
function wishlist_count_shortcode() {
	if (is_user_logged_in()) {
		$user_id  = get_current_user_id();
		$wishlist = get_user_meta($user_id, 'wishlist_products', true);
		$count    = is_array($wishlist) ? count($wishlist) : 0;
		return $count;
	} else {
		return '<p>Please <a href="' . esc_url(wp_login_url(get_permalink())) . '">log in</a> to see your wishlist count.</p>';
	}
}
add_shortcode('wishlist_count', 'wishlist_count_shortcode');