Customer Wishlist
Enable the End customer to add products to their wishlist from the merchant’s catalog in order to buy those products later, saving the research effort for them and increasing merchant sales.
Activation Steps for Merchants
There are no steps needed to be activated on a store; you just need to use a store subscribed to the Growth package or above.
Code Snippet Integration for Theme Partners
To properly integrate Wishlist into the theme, you’ll need to add these into the appropriate theme files:
1. Product Card component and Product page:
Insert the following in the template/products.twig
and template/category.twig
file:
You’ll need to create a variable in the template to check if this product is in the customer withlist to fill the icon.
{% if customer is not null and customer.wishlist is not empty %}
{% for itemId in customer.wishlist %}
{% if itemId == product.id %}
{% set in_wishlist = true %}
{% endif %}
{% endfor %}
{% endif %}
Then add this block in the card div or where you would like to show the heart icon.
<span class="add-to-wishlist" data-wishlist-id="{{ product.id }}">
{% if customer %}
<a class="icon-heart-mask {% if in_wishlist == true %}filled{% endif %}" onclick="addToWishlist(this, '{{ product.id }}')"></a>
{% else %}
<a class="icon-heart-mask" href="/auth/login?redirect_to={{ requestUri() }}"></a>
{% endif %}
<img class="loader d-none" src="{{ asset_url }}spinner.gif" width="20" height="20"/>
</span>
{% endif %}
2. For Main.js File:
Insert the following in the main.js file or the main javascript code file you have:
function fillWishlistItems(items) {
items.forEach((product) => {
$(`.add-to-wishlist[data-wishlist-id=${product.id}]`)
.find(".icon-heart-mask")
.addClass("filled");
});
}
function addToWishlist(elm, productId) {
$(elm).siblings(".add-to-wishlist .loader").removeClass("d-none");
$(elm).addClass("d-none");
// Remove From Wishlist if added
if ($(elm).hasClass("filled")) {
return removeFromWishlist(elm, productId);
}
zid.store.customer.addToWishlist(productId).then((response) => {
if (response.status === "success") {
$(elm).siblings(".add-to-wishlist .loader").addClass("d-none");
$(elm).addClass("filled").removeClass("d-none");
toastr.success(response.data.message);
} else {
toastr.error(response.data.message);
}
});
}
function removeFromWishlist(elm, productId) {
$(elm).siblings(".add-to-wishlist .loader").removeClass("d-none");
$(elm).addClass("d-none");
zid.store.customer.removeFromWishlist(productId).then((response) => {
if (response.status === "success") {
$(elm).siblings(".add-to-wishlist .loader").addClass("d-none");
$(elm).removeClass("d-none filled");
toastr.success(response.data.message);
if (location.pathname === '/account-wishlist') {
location.reload();
}
} else {
toastr.error(response.data.message);
}
});
}
function shareWishlist() {
$(".share-wishlist .loader").removeClass("d-none").siblings(".share-icon").addClass("d-none");
zid.store.customer.shareWishlist().then(async (response) => {
if (response.status === "success") {
$(".share-wishlist .loader").addClass("d-none").siblings(".share-icon").removeClass("d-none");
if (response.data.link) {
try {
await navigator.clipboard.writeText(response.data.link);
toastr.success(response.data.message);
} catch (error) {
console.log(error);
}
}
} else {
toastr.error(response.data.message);
}
});
}
You can replace toaster notification with any you’re using.
3. Wishlist page and Shared wishlist:
You need to create two separate pages for account-wishlist.twig
is for listing customer wishlist and wishlist.twig
is for listing shared wishlist.
For account-wishlist.twig
page, you can add this in the template, for example:
{% extends "layout.twig" %}
{% block header %} {{ include('header.twig') }} {% endblock %}
{% block main_content %}
<div class="container-parent">
<div class="container">
<div class="d-flex">
<div class="flex-grow-1">
<div class="account-content">
<div>
<div id="wishlist-list" class="row">
{% for product in wishlist.data %}
<div class="col-6 col-lg-4 py-3">
{% include 'product-card.twig' with {'product' : product, 'index': key} %}
</div>
{% endfor %}
</div>
{% include 'pagination.twig' with { 'totalPages' : products.last_page , 'currentPage' : products.current_page } %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block footer %} {{ include('footer.twig') }} {% endblock %}
You’ll need to add the topbar of the page with a share button to allow customers to share their wishlist with others; you can fire the function of shareWishlist
to create a link and copy it to the clipboard.
Share button snippet:
<button class="btn btn-sm btn-outline-secondary share-wishlist m-3" onclick="shareWishlist()">
<img class="loader d-none" src="{{ asset_url }}spinner.gif" width="25" height="20"/>
<span class="align-middle share-icon">
<i class="fa fa-share"></i>
</span>
<span class="px-1">{{ locals.shareLabel }}</span>
</button>
For wishlist.twig
page (listing shared wishlist):
{% extends "layout.twig" %}
{% block header %} {{ include('header.twig') }} {% endblock %}
{% block top_links %}
<style>
.add-to-wishlist, .share-wishlist {
display: none !important;
}
</style>
{% endblock %}
{% block main_content %}
<div class="container-parent">
<div class="container">
<div class="d-flex">
<div class="flex-grow-1">
<div class="account-content">
<div>
<div id="wishlist-list" class="row">
{% for product in wishlist.data %}
<div class="col-6 col-md-4 col-lg-3 py-3">
{% include 'product-card.twig' with {'product' : product, 'index': key} %}
</div>
{% endfor %}
</div>
{% include 'pagination.twig' with { 'totalPages' : products.last_page , 'currentPage' : products.current_page } %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block footer %} {{ include('footer.twig') }} {% endblock %}
{% block script %}
<script defer>
$(`.add-to-wishlist .share-wishlist`).remove();
</script>
{% endblock %}
Should be the same as account-wishlist.twig but without the share button, profile tabs and heart icon.
4. Custom CSS example:
.add-to-wishlist {
position: absolute;
right: 0;
z-index: 1;
display: inline-flex;
justify-content: center;
align-items: center;
margin: 10px;
width: 40px;
height: 35px;
cursor: pointer;
border-radius: 5px;
background-color: white;
}
.rtl .add-to-wishlist {
right: unset;
left: 0;
}
.icon-heart-mask {
display: inline-block;
width: 25px;
height: 20px;
mask-size: 100%;
mask-position: center;
mask-repeat: no-repeat;
mask-image: url('./heart-outlined.svg');
background-color: var(--secondary, #A1A0A9);
}
.icon-heart-mask.filled {
mask-image: url('./heart-filled.svg');
background-color: var(--primary_color, #D86F6F);
}