Wishlist

Let shoppers save products for later and come back to buy them.

A heart on every product card and product page. Saved products appear on a Wishlist page, in a My Account tab and in the Moduly Wishlist Divi module, where shoppers change quantities, add them to the cart or share the list with a private link. A variable product keeps the variation the shopper chose. Guests can save too: their list is kept in the browser and moves into their account when they log in. Saved hearts stay correct on cached pages.

Extension · needs WooCommerce

Requirements

  • WordPress 6.2 or newer
  • PHP 7.4 or newer
  • WooCommerce 7.0 or newer

Configure it

  1. Switch it on in Moduly → Installed Widgets.
  2. Hearts appear at once on shop and category pages, on Moduly product grids and carousels, in quick view and on product pages.
  3. A Wishlist page is created for you the next time you open the admin, and a Wishlist tab is added to My Account.
  4. Click Manage on Wishlist to change where the buttons go, their text and colour, the table's columns and what happens after saving.

Where the heart shows

PlaceHow it looks
Shop, category and tag pagesA round icon on the image (top right or top left), or a text link under the card's button
Moduly Product Grid, Product Carousel and Woo ProductsThe same icon, at the top of the card's own hover icons
Product pageA button after (or before) Add to cart, or below the summary
Quick view windows and other add-to-cart formsA button after Add to cart
Out of stock and external productsA button after the product meta

Settings

Buttons

SettingWhat you can set
On product cardsOn / off · shop, categories, Moduly product grids and carousels
On the cardIcon on the image, top right · Icon on the image, top left · Text link below the card's button
On the product pageOn / off
Place on the product pageAfter the Add to cart button · Before the Add to cart button · Below the summary
IconHeart, Star or Bookmark
Button text / once savedDefaults: "Add to wishlist" and "Saved to wishlist"
Saved colourThe filled icon's colour

Wishlist page

SettingWhat you can set
Page titleThe title of the page created for the list (and of the My Account tab)
Wishlist tab in My AccountOn / off
Take a product off the list once it is added to the cart from thereOn / off
Private share linksLogged-in shoppers create an unguessable link, copy it or send it by email, WhatsApp, X or Facebook, make a new one or stop sharing. Anyone with the link sees the list read-only. Guests are asked to log in to share
ColumnsPrice, Stock, Date added, Add to cart button
Empty list textShown when nothing is saved

Behaviour

SettingWhat you can set
Guests can save productsOn: kept in a cookie and moved into their account at login. Off: guests are sent to log in
Keep a guest's list for (days)1–365
After savingA short message with a link to the list · just fill the icon · go to the wishlist page
Message positionAny corner

Shortcodes and code

The wishlist table (put it on any page):

[mdly_wishlist]

A heart with the count, for a header:

[mdly_wishlist_count]
[mdly_wishlist_count text="Wishlist"]

A button for one product (look is button, icon or link; without id, the current product):

[mdly_wishlist_button id="42"]

In a theme template:

<?php if ( mdly_wishlist_has( get_the_ID() ) ) : ?> … <?php endif; ?>

The script fires mdly:wishlist on document after each change, with { id, saved, ids } in event.detail (API calls add op and the call's answer).

Developer API (since 1.1)

The Divi Wishlist module is built on this API, and themes and plugins can use it too.

PHP — Moduly\Extensions\Wishlist\Api

MethodDoes
Api::items( [ 'search' => '', 'sort' => 'newest', 'stock' => 'all' ] )The visitor's list with product data: id, variation_id, attributes, variation (label / value pairs), variation_text, qty, max_qty, added, name, sku, url, image, price_html, price, in_stock, stock_text, can_add, needs_options, button_text. Sorts: newest, oldest, price_asc, price_desc, name. Stock: all, in, out. 'user' => 42 reads another account's list (a share link's owner)
Api::add( $id, [ 'variation' => 51, 'attrs' => [], 'qty' => 2 ] )Save a product, or change a saved one. A variation's own ID is saved under its parent
Api::update( $id, [ 'qty' => 3 ] )Change the quantity and/or variation of a saved product
Api::remove( $id_or_ids )Remove one or several; returns the IDs removed
Api::to_cart( $ids, [ 'remove' => true, 'qty' => [ $id => 2 ] ] )Add to the cart with each item's variation and quantity. Returns added, failed (with a reason and the product link) and removed. Out-of-stock items and variable products without a complete variation are reported, never added. remove defaults to the "take off once added" setting
Api::share_state() / Api::share( 'enable' | 'regenerate' | 'revoke' )The visitor's private link: enabled, can (logged in), active, url
Api::shared_owner( $token )The account a share token belongs to, or 0

Helpers: mdly_wishlist_has( $id ), mdly_wishlist_items( $args ), mdly_wishlist_share_url().

JavaScript — window.mdlyWishlist.api

Every method returns a promise of the server's answer, which always carries ids and count. Saved hearts and counters on the page update by themselves, and mini carts refresh after an add to cart.

const wl = window.mdlyWishlist.api;
wl.list( { search: 'tee', sort: 'price_asc', stock: 'in' } ); // → { items, share }
wl.add( 42, { variation: 51, qty: 2 } );
wl.update( 42, { qty: 3 } );
wl.remove( [ 42, 43 ] );
wl.toCart( [ 42, 43 ], { qty: { 42: 2 }, remove: true } ); // → { added, failed, removed }
wl.share( 'enable' );     // 'enable' | 'regenerate' | 'revoke' (logged in)
wl.ids(); wl.has( 42 );

AJAX — ?wc-ajax=mdly_wishlist_api

POST op = list · add · update · remove · cart · share, with id or ids[], variation, attrs[…], qty (or qty[id] for cart), remove, search, sort, stock. token reads a shared list (and cart adds from it). share needs action_name and the nonce from window.mdlyWishlist.nonce. Like WooCommerce's cart, the list belongs to the browser's session, so the other operations need no nonce.

For store owners

Products → All Products gets a sortable heart column: how many shoppers' lists hold each product.

How it stores lists

  • Logged-in shoppers: user meta _mdly_wishlist (product IDs and dates) and _mdly_wishlist_items (chosen variation and quantity). A share link's token is in _mdly_wishlist_share.
  • Guests: a first-party cookie, mdly_wishlist, holding product IDs, dates, the chosen variation and the quantity only, and mdly_wishlist_who, which says whether the list is a guest's. They are removed when the shopper logs out. A guest's own pick for an "any" attribute is not kept in the cookie; choose a complete variation, or log in.
  • When a guest logs in, their list is merged into the account's (the guest's variation and quantity win for products on both).
  • The cookie mirrors the list so the page's script can mark saved products without asking the server. That is why hearts are right even on pages served from a cache.