Creating a personalized My Account experience is a powerful way to increase customer engagement and drive repeat purchases. In this post, we’ll walk you through a custom plugin that adds three exciting features to your WooCommerce My Account page:
- Buy Again: Displays a grid of products your customer has previously purchased, allowing them to repurchase with a single click.
- Wishlist: Lets customers add products to their wishlist via AJAX, with a dedicated grid view for easy management.
- Special Offers: Showcases on-sale products and dynamically generates a unique, one‑time 5% discount coupon for logged‑in users.
Below, we’ll share the PHP code for the plugin and also include the JavaScript and CSS code that powers the interactive and visual elements of the My Account page.
WordPress Plugin Development
Transform your business website with our expert WordPress development services. Our team of specialists will unlock your site’s full potential, driving better performance, engagement, and conversions. Let us help you create a seamless, high-performing website that delivers results.
Plugin PHP Code
This is the main plugin code that registers our custom My Account enhancements. It uses best practices for escaping, localization, and WordPress coding standards.
<?php
/**
* Plugin Name: Custom My Account Enhancements
* Description: Adds custom sections to WooCommerce My Account page, including Buy Again, Offers, and Wishlists.
* Version: 1.0
* Author: Kishores
* Text Domain: custom-my-account-enhancements
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Custom_My_Account_Enhancements {
/**
* Constructor.
*/
public function __construct() {
// Enqueue scripts and styles.
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
// Add custom sections to My Account page.
add_action( 'woocommerce_account_dashboard', [ $this, 'add_custom_sections' ] );
// AJAX handlers for wishlist.
add_action( 'wp_ajax_add_to_wishlist', [ $this, 'add_to_wishlist' ] );
add_action( 'wp_ajax_remove_from_wishlist', [ $this, 'remove_from_wishlist' ] );
// Add wishlist button on product pages.
add_action( 'woocommerce_after_add_to_cart_button', [ $this, 'add_wishlist_button' ] );
}
/**
* Enqueue scripts and styles.
*/
public function enqueue_scripts() {
wp_enqueue_script( 'custom-my-account-js', plugin_dir_url( __FILE__ ) . 'assets/js/custom-my-account.js', [ 'jquery' ], '1.0', true );
wp_localize_script( 'custom-my-account-js', 'custom_my_account_ajax', [ 'ajax_url' => admin_url( 'admin-ajax.php' ) ] );
wp_enqueue_style( 'custom-my-account-css', plugin_dir_url( __FILE__ ) . 'assets/css/custom-my-account.css' );
}
/**
* Output custom sections.
*/
public function add_custom_sections() {
echo '<div class="custom-my-account-sections">';
$this->special_offers_section();
echo '</div>';
echo '<div class="custom-my-account-sections">';
$this->wishlist_section();
echo '</div>';
echo '<div class="custom-my-account-sections">';
$this->buy_again_section();
echo '</div>';
}
/**
* Buy Again Section.
*/
private function buy_again_section() {
echo '<h2>' . esc_html__( 'Buy Again', 'custom-my-account-enhancements' ) . '</h2>';
echo '<div class="buy-again-grid">';
// Set the maximum number of unique products to display here:
$max_products = 3; // Change this value as needed.
// Fetch orders with a limit high enough to likely retrieve enough unique products.
$customer_orders = wc_get_orders( [
'customer_id' => get_current_user_id(),
'limit' => 20,
'status' => 'completed',
] );
$products_displayed = [];
if ( $customer_orders ) {
foreach ( $customer_orders as $order ) {
foreach ( $order->get_items() as $item ) {
$product = $item->get_product();
if ( $product && ! in_array( $product->get_id(), $products_displayed, true ) ) {
echo '<div class="buy-again-item">';
echo '<a href="' . esc_url( get_permalink( $product->get_id() ) ) . '">' . $product->get_image( 'woocommerce_thumbnail' ) . '</a>';
echo '<div class="product-details">';
echo '<a href="' . esc_url( get_permalink( $product->get_id() ) ) . '"><h3>' . esc_html( $product->get_name() ) . '</h3></a>';
echo '<p class="price">' . $product->get_price_html() . '</p>';
$buy_again_url = esc_url( apply_filters( 'woocommerce_product_add_to_cart_url', $product->add_to_cart_url(), $product ) );
echo '<a href="' . $buy_again_url . '" data-product_id="' . esc_attr( $product->get_id() ) . '" class="button buy-again-button">' . esc_html__( 'Buy Again', 'custom-my-account-enhancements' ) . '</a>';
echo '</div>';
echo '</div>';
$products_displayed[] = $product->get_id();
if ( count( $products_displayed ) >= $max_products ) {
break 2;
}
}
}
}
} else {
echo '<p>' . esc_html__( 'You haven\'t purchased anything yet.', 'custom-my-account-enhancements' ) . '</p>';
}
echo '</div>';
}
/**
* Wishlist Section.
*/
private function wishlist_section() {
echo '<h2>' . esc_html__( 'Your Wishlist', 'custom-my-account-enhancements' ) . '</h2>';
echo '<div class="wishlist-grid">';
$user_id = get_current_user_id();
$wishlist = get_user_meta( $user_id, '_custom_wishlist', true );
if ( $wishlist && is_array( $wishlist ) ) {
foreach ( $wishlist as $product_id ) {
$product = wc_get_product( $product_id );
if ( $product ) {
echo '<div class="wishlist-item">';
echo '<a href="' . esc_url( get_permalink( $product_id ) ) . '">' . $product->get_image( 'woocommerce_thumbnail' ) . '</a>';
echo '<div class="product-details">';
echo '<a href="' . esc_url( get_permalink( $product_id ) ) . '"><h3>' . esc_html( $product->get_name() ) . '</h3></a>';
echo '<p class="price">' . $product->get_price_html() . '</p>';
echo '<button class="remove-wishlist-button" data-product-id="' . esc_attr( $product_id ) . '">' . esc_html__( 'Remove', 'custom-my-account-enhancements' ) . '</button>';
echo '</div>';
echo '</div>';
}
}
} else {
echo '<p>' . esc_html__( 'Your wishlist is empty.', 'custom-my-account-enhancements' ) . '</p>';
}
echo '</div>';
}
/**
* Special Offers Section.
*/
private function special_offers_section() {
echo '<h2>' . esc_html__( 'Special Offers', 'custom-my-account-enhancements' ) . '</h2>';
// Display on-sale products in a grid layout with 3 columns.
echo do_shortcode( '[products on_sale="true" limit="4" columns="3"]' );
// Only proceed if the user is logged in.
if ( is_user_logged_in() ) {
$user_id = get_current_user_id();
$coupon_code = get_user_meta( $user_id, '_dynamic_discount_coupon', true );
if ( ! empty( $coupon_code ) ) {
$coupon = new WC_Coupon( $coupon_code );
$usage_limit = intval( $coupon->get_usage_limit() );
$usage_count = intval( $coupon->get_usage_count() );
if ( $usage_count >= $usage_limit ) {
delete_user_meta( $user_id, '_dynamic_discount_coupon' );
$coupon_code = '';
}
}
if ( empty( $coupon_code ) ) {
$coupon_code = strtoupper( 'OFF5' . wp_generate_password( 4, false, false ) );
$coupon_data = array(
'post_title' => $coupon_code,
'post_content' => '',
'post_status' => 'publish',
'post_author' => $user_id,
'post_type' => 'shop_coupon',
);
$new_coupon_id = wp_insert_post( $coupon_data );
if ( $new_coupon_id ) {
update_post_meta( $new_coupon_id, 'discount_type', 'percent' );
update_post_meta( $new_coupon_id, 'coupon_amount', '5' );
update_post_meta( $new_coupon_id, 'individual_use', 'yes' );
update_post_meta( $new_coupon_id, 'usage_limit', '1' );
update_post_meta( $new_coupon_id, 'usage_limit_per_user', '1' );
update_post_meta( $new_coupon_id, 'expiry_date', date( 'Y-m-d', strtotime( '+7 days' ) ) );
update_user_meta( $user_id, '_dynamic_discount_coupon', $coupon_code );
}
}
if ( ! empty( $coupon_code ) ) {
echo '<div class="coupon-banner">';
echo '<h3>' . esc_html__( 'Exclusive Offer!', 'custom-my-account-enhancements' ) . '</h3>';
echo '<p>' . sprintf(
esc_html__( 'Use coupon %s for 5%% off your next order. (One time use)', 'custom-my-account-enhancements' ),
'<strong>' . esc_html( $coupon_code ) . '</strong>'
) . '</p>';
echo '</div>';
}
} else {
echo '<p>' . esc_html__( 'Login to get your exclusive discount coupon!', 'custom-my-account-enhancements' ) . '</p>';
}
}
/**
* Output Wishlist Button on Product Page.
*/
public function add_wishlist_button() {
if ( is_user_logged_in() ) {
global $product;
$user_id = get_current_user_id();
$wishlist = get_user_meta( $user_id, '_custom_wishlist', true );
$is_in_wishlist = $wishlist && in_array( $product->get_id(), $wishlist, true );
echo '<button class="wishlist-button ' . ( $is_in_wishlist ? 'added' : '' ) . '" data-product-id="' . esc_attr( $product->get_id() ) . '">';
echo $is_in_wishlist ? esc_html__( 'Remove from Wishlist', 'custom-my-account-enhancements' ) : esc_html__( 'Add to Wishlist', 'custom-my-account-enhancements' );
echo '</button>';
} else {
echo '<a href="' . esc_url( wp_login_url( get_permalink() ) ) . '" class="wishlist-button">' . esc_html__( 'Login to Add to Wishlist', 'custom-my-account-enhancements' ) . '</a>';
}
}
/**
* AJAX: Add to Wishlist.
*/
public function add_to_wishlist() {
if ( ! is_user_logged_in() ) {
wp_send_json_error( esc_html__( 'You must be logged in to add items to your wishlist.', 'custom-my-account-enhancements' ) );
}
$product_id = intval( $_POST['product_id'] );
$user_id = get_current_user_id();
$wishlist = get_user_meta( $user_id, '_custom_wishlist', true );
if ( ! $wishlist ) {
$wishlist = [];
}
if ( ! in_array( $product_id, $wishlist, true ) ) {
$wishlist[] = $product_id;
update_user_meta( $user_id, '_custom_wishlist', $wishlist );
wp_send_json_success( esc_html__( 'Product added to your wishlist!', 'custom-my-account-enhancements' ) );
} else {
wp_send_json_error( esc_html__( 'This product is already in your wishlist.', 'custom-my-account-enhancements' ) );
}
}
/**
* AJAX: Remove from Wishlist.
*/
public function remove_from_wishlist() {
if ( ! is_user_logged_in() ) {
wp_send_json_error( esc_html__( 'You must be logged in to remove items from your wishlist.', 'custom-my-account-enhancements' ) );
}
$product_id = intval( $_POST['product_id'] );
$user_id = get_current_user_id();
$wishlist = get_user_meta( $user_id, '_custom_wishlist', true );
if ( is_array( $wishlist ) && ( $key = array_search( $product_id, $wishlist, true ) ) !== false ) {
unset( $wishlist[ $key ] );
$wishlist = array_values( $wishlist );
update_user_meta( $user_id, '_custom_wishlist', $wishlist );
wp_send_json_success( esc_html__( 'Product removed from your wishlist.', 'custom-my-account-enhancements' ) );
} else {
wp_send_json_error( esc_html__( 'Product not found in your wishlist.', 'custom-my-account-enhancements' ) );
}
}
}
new Custom_My_Account_Enhancements();
JavaScript Code
The JavaScript (located in assets/js/custom-my-account.js
) handles the AJAX requests for adding and removing products from the wishlist. Here’s an example:
jQuery(document).ready(function($) {
// Wishlist toggle for product detail and wishlist grid.
$(document).on('click', '.wishlist-button', function(e) {
e.preventDefault();
const productId = $(this).data('product-id');
var $btn = $(this);
if ($btn.hasClass('added')) {
// Remove from wishlist.
$.ajax({
url: custom_my_account_ajax.ajax_url,
type: 'POST',
data: {
action: 'remove_from_wishlist',
product_id: productId
},
success: function(response) {
if (response.success) {
$btn.removeClass('added').text('Add to Wishlist');
// If in wishlist grid, remove the container.
if ($btn.closest('.wishlist-item').length > 0) {
$btn.closest('.wishlist-item').fadeOut(300, function() {
$(this).remove();
});
}
alert(response.data);
} else {
alert(response.data);
}
}
});
} else {
// Add to wishlist.
$.ajax({
url: custom_my_account_ajax.ajax_url,
type: 'POST',
data: {
action: 'add_to_wishlist',
product_id: productId
},
success: function(response) {
if (response.success) {
$btn.addClass('added').text('Remove from Wishlist');
alert(response.data);
} else {
alert(response.data);
}
}
});
}
});
});
CSS Code
The CSS (located in assets/css/custom-my-account.css
) styles the grid layouts, buttons, and sections for a polished look. For example:
/* General Container */
.custom-my-account-sections {
margin-bottom: 2rem;
padding: 1.5rem;
background: #f9f9f9;
border-radius: 12px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
/* Grid Layout for Buy Again & Wishlist */
.buy-again-grid, .wishlist-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
}
/* Item Styling */
.buy-again-item, .wishlist-item {
background: #fff;
border: 1px solid #dcdcde;
border-radius: 10px;
padding: 1rem;
text-align: center;
transition: box-shadow 0.3s ease;
}
.buy-again-item:hover, .wishlist-item:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
/* Image Styling */
.buy-again-item img, .wishlist-item img {
display: block;
margin: 0 auto;
border-radius: 8px;
width: 70%;
height: auto;
}
/* Product Details */
.product-details h3 {
font-size: 1.2rem;
margin: 0.5rem 0;
}
.price {
color: #007cba;
font-weight: bold;
}
/* Buy Again Button */
.buy-again-button {
padding: 0.4rem 0.8rem;
font-size: 0.9rem;
background: #007cba;
color: #fff;
border: none;
border-radius: 5px;
text-decoration: none;
margin-top: 0.5rem;
transition: background 0.3s ease;
}
.buy-again-button:hover {
background: #005a87;
}
/* Wishlist Button */
.wishlist-button {
display: inline-block;
background: #007cba;
color: #fff;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 8px;
margin-top: 1rem;
cursor: pointer;
transition: background 0.3s ease;
}
.wishlist-button:hover {
background: #005a87;
}
/* Coupon Banner */
.coupon-banner {
background: #f1f1f1;
border: 1px solid #dcdcde;
border-radius: 10px;
padding: 1rem;
margin-top: 1rem;
text-align: center;
}
.coupon-banner h3 {
margin: 0;
color: #d63638;
font-size: 1.4rem;
}
.coupon-banner p {
margin-top: 0.5rem;
font-size: 1rem;
color: #23282d;
}
Conclusion
By integrating the PHP, JavaScript, and CSS code provided above, you can transform your WooCommerce My Account page into an engaging space where customers can easily repurchase, manage their wishlist, and take advantage of exclusive discount offers. This plugin not only enhances the user experience but also encourages repeat business with minimal effort.
Feel free to modify and extend the code to best suit your store’s branding and promotional strategies. Happy coding and may your sales soar!
Leave a Reply