Wishlist / Save-for-Later Button
Adds a cookie-based wishlist heart button to product pages and archive cards, with an [scseed_wishlist] shortcode to display saved items.
Module3 parts · by SnipCraft
PHPPHP
php
<?php
if ( ! class_exists( 'WooCommerce' ) ) { return; }
/* Output AJAX vars once per page */
add_action( 'wp_footer', 'scseed_wl_footer_vars', 1 );
function scseed_wl_footer_vars() {
echo '<script>window.scWL=' . wp_json_encode( array(
'ajax' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'scseed_wl' ),
) ) . ';</script>';
}
/* Heart button — single product and archive */
add_action( 'woocommerce_after_add_to_cart_button', 'scseed_wl_button', 10 );
add_action( 'woocommerce_after_shop_loop_item', 'scseed_wl_button', 12 );
function scseed_wl_button() {
global $product;
if ( ! $product ) { return; }
$id = $product->get_id();
echo '<button type="button" class="scseed-wl-btn" data-pid="' . esc_attr( $id ) . '" '
. 'aria-label="' . esc_attr__( 'Add to wishlist', 'scseed' ) . '">'
. '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false">'
. '<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>'
. '</svg></button>';
}
/* AJAX: return HTML for wishlist product grid */
add_action( 'wp_ajax_scseed_wl_items', 'scseed_ajax_wl_items' );
add_action( 'wp_ajax_nopriv_scseed_wl_items', 'scseed_ajax_wl_items' );
function scseed_ajax_wl_items() {
check_ajax_referer( 'scseed_wl', 'nonce' );
$raw = sanitize_text_field( wp_unslash( $_POST['ids'] ?? '' ) );
$ids = array_filter( array_map( 'absint', explode( ',', $raw ) ) );
if ( empty( $ids ) ) {
wp_send_json_success( '' );
}
ob_start();
echo '<ul class="products scseed-wl__grid">';
foreach ( $ids as $id ) {
$p = wc_get_product( $id );
if ( ! $p || 'publish' !== $p->get_status() ) { continue; }
echo '<li class="product">';
echo '<a href="' . esc_url( $p->get_permalink() ) . '">';
echo $p->get_image( 'woocommerce_thumbnail' );
echo '<h2 class="woocommerce-loop-product__title">' . esc_html( $p->get_name() ) . '</h2>';
echo '</a>';
echo '<span class="price">' . $p->get_price_html() . '</span>';
echo '<a href="' . esc_url( $p->add_to_cart_url() ) . '" class="button add_to_cart_button">'
. esc_html( $p->add_to_cart_text() ) . '</a>';
echo '</li>';
}
echo '</ul>';
wp_send_json_success( ob_get_clean() );
}
/* Shortcode: [scseed_wishlist] */
add_shortcode( 'scseed_wishlist', 'scseed_wl_shortcode' );
function scseed_wl_shortcode() {
return '<div id="scseed-wl-page" class="scseed-wl__page">'
. '<p class="scseed-wl__empty">'
. esc_html__( 'Your wishlist is empty.', 'scseed' )
. '</p></div>';
}CSSStyles
css
/* ── Wishlist Button ── */
.scseed-wl-btn {
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
background: none;
border: none;
padding: .4rem;
color: #bbb;
transition: color .2s, transform .15s;
vertical-align: middle;
}
.scseed-wl-btn svg { fill: currentColor; display: block; pointer-events: none; }
.scseed-wl-btn:hover { color: #e91e63; transform: scale(1.18); }
.scseed-wl-btn.scseed-wl--active { color: #e91e63; }
.scseed-wl-btn:focus-visible { outline: 2px solid #e91e63; outline-offset: 2px; border-radius: 50%; }
/* ── Wishlist Page ── */
.scseed-wl__page { min-height: 4rem; }
.scseed-wl__empty { color: #777; font-style: italic; }JavaScriptScript
js
(function () {
var COOKIE = 'scseed_wl';
var DAYS = 365;
function readIds() {
var m = document.cookie.match('(?:^|;)\s*scseed_wl=([^;]*)');
if (!m) { return []; }
try { return JSON.parse(decodeURIComponent(m[1])); } catch (e) { return []; }
}
function writeIds(ids) {
var d = new Date();
d.setDate(d.getDate() + DAYS);
document.cookie = COOKIE + '=' + encodeURIComponent(JSON.stringify(ids))
+ '; path=/; expires=' + d.toUTCString() + '; SameSite=Lax';
}
function toggleId(id) {
var ids = readIds();
var idx = ids.indexOf(id);
if (idx === -1) { ids.push(id); } else { ids.splice(idx, 1); }
writeIds(ids);
return ids.indexOf(id) !== -1;
}
/* Initialise buttons */
var saved = readIds();
document.querySelectorAll('.scseed-wl-btn').forEach(function (btn) {
var pid = parseInt(btn.getAttribute('data-pid'), 10);
if (saved.indexOf(pid) !== -1) { btn.classList.add('scseed-wl--active'); }
btn.addEventListener('click', function () {
var active = toggleId(pid);
btn.classList.toggle('scseed-wl--active', active);
btn.setAttribute('aria-label', active ? 'Remove from wishlist' : 'Add to wishlist');
});
});
/* Populate wishlist page */
var page = document.getElementById('scseed-wl-page');
if (page && typeof scWL !== 'undefined') {
var ids = readIds();
if (!ids.length) { return; }
var body = new URLSearchParams({
action: 'scseed_wl_items',
nonce: scWL.nonce,
ids: ids.join(',')
});
fetch(scWL.ajax, { method: 'POST', body: body })
.then(function (r) { return r.json(); })
.then(function (res) { if (res.success && res.data) { page.innerHTML = res.data; } });
}
})();#ux#woocommerce#product#cookie#wishlist