# Ecommerce wishlist in Go (GoCommerce module)

> Let GoCommerce shoppers save products to a list kept by a token, guests included, and see which wished-for products are out of stock. Settings and limits.

- Canonical: https://kitcommerce.store/integrations/wishlist/
- Last updated: 2026-10-28

---

Marketing

## Ecommerce wishlist in Go

A Go package for what shoppers wanted and did not buy yet. A list is kept by a token the storefront holds, the way a cart is, so a guest can save a product before there is an account. The shop’s side ranks products by how many lists hold them and shows which of those are out of stock. Nothing is required.

- **Marketing** module
- **3** settings
- **7** tests
- **7** API operations
- **ext/wishlist**

### What it does

In the package’s own words, a wishlist is “what shoppers wanted and did not buy yet.” The storefront creates a list with POST /x/wishlist, which answers with its token, and then adds and removes products under /x/wishlist/{token}. Each item comes back with the product’s title, slug, SKU, price and how many the store could sell this minute.

The price and the stock come from the variant an item names, or from the product’s cheapest active variant when it names none, which is what a product card shows. Saving the same thing twice is not an error and not a second row. A list can carry an email when the shopper gives one, so the shop can write to the people waiting for a restock.

The package calls the shop’s side “the more interesting half”. The Wishlists screen ranks products by how many lists hold them, with how many of those lists gave an email, and can show only the ones out of stock: “a demand signal no other screen in the panel carries.”

### Configuration

Nothing is required. One Go setting bounds a list; the Plugins screen holds the page heading and whether the storefront asks for an email.

*Wishlist module settings — 3 settings, 0 required*

| Setting | Environment variable | Required | What it does |
| --- | --- | --- | --- |
| `MaxItems` | — | No | How many products one list may hold: 200 when zero. A list at the limit refuses another product with 409. Go only. |
| `heading` Page heading | — | No | The wishlist page’s heading, “Your wishlist” by default. Public. Panel only; there is no Config field for it. |
| `collect_email` Ask for an email on the wishlist page | — | No | The panel’s hint: so the shop can write when something wished for comes back in stock. Public, for the storefront to read; the module accepts an email whichever way it is set. Panel only. |

The module reads its Config struct, not the environment. The variable names are the ones the package’s own example or the reference binary uses; in your own `main()` you choose where each value comes from. Where a setting has a panel label, the admin’s settings drawer can hold it too, and a value typed there wins over Config.

### Setting it up

1. **Install the module** — Pass wishlist.New to gocommerce.New, as below, or start the reference binary with -wishlist. It adds two tables, and the plugin starts switched on.
2. **Keep the token** — POST /x/wishlist, with an email or with no body at all, answers with the new list and its token. The storefront stores the token as it does a cart’s; it is the only key to that list.
3. **Save and show** — POST /x/wishlist/{token}/items with a product_id, and a variant_id if the shopper chose one. GET /x/wishlist/{token} draws the page, stock included.
4. **Read the demand** — The Wishlists screen, or GET /api/admin/x/wishlist/wanted?out_of_stock=1, lists the most-wanted products the store cannot sell right now.

main.go

```
import (
	"github.com/itswadesh/gocommerce/core"
	"github.com/itswadesh/gocommerce/ext/wishlist"
)

app, err := gocommerce.New(cfg, wishlist.New(wishlist.Config{}))
```

The package doc’s own example, with its imports; cfg is your gocommerce.Config. The reference binary’s -wishlist flag and examples/store/main.go install it the same way. Import path `github.com/itswadesh/gocommerce/ext/wishlist`.

### How it works

- **A token, like a cart’s**

  32 bytes from crypto/rand, written as hex: the only credential a guest holds. Every storefront route takes it in the path, and a token nobody has answers 404.

- **Once per product and variant**

  A unique index on the list, the product and the variant, with a whole-product save counted as one, makes a repeated save a no-op answered with the list as it stands.

- **Checked before it is saved**

  The product has to exist, and a named variant has to belong to it, or the save answers 404. Otherwise, in the code’s words, a list fills with rows that can never be drawn.

- **Stock as the store sells it**

  Available is on hand less reserved, summed over the active variants an item covers. A variant that does not track inventory counts as always in stock.

- **A deleted product still counts**

  The product id is deliberately not a foreign key. A product deleted since stays in the ranking, and the shopper’s list marks it deleted rather than losing the row.

- **The token stays off the admin**

  The admin’s list of wishlists shows the id, email, item count and dates, never the token, “the shopper’s credential”. On a demo store or for an agent key the email is masked and searching by it matches nothing.

### What it does not do

Read these before an order depends on it. No store is known to run GoCommerce in production yet, so these come from the code, not from anyone’s experience.

- **Kept by token, not by account** — A list has no customer column. It follows a shopper only as far as the storefront keeps its token; nothing in the module joins two lists or ties one to a sign-in.
- **It sends nothing** — The module counts who is waiting and keeps their emails, and stops there. No restock mail is sent and no event is emitted when a wished-for product comes back.
- **Consent is the storefront’s** — An email is stored as given, with no confirmation and no record of consent. The collect_email switch only tells the storefront whether to ask.
- **The token is the whole key** — Anyone holding a list’s token can read and change it. There is no read-only link for sharing a list.
- **Lists are never cleared** — There is no route to delete a list and no expiry. A shopper can remove items one at a time and clear the email by sending an empty one; an operator can remove neither.
- **Products, not variants, in the ranking** — The ranking groups by product: which variant was wished for is on the list but not in the count, and out of stock means no active variant has any to sell. It reads as JSON pages; there is no CSV export.

FAQ

### Questions about the Wishlist module

**Does a shopper need an account?**

No. A list is created with POST /x/wishlist and kept by the token it returns, the way a cart is, so a guest can save products. The module has no link to customer accounts.

**Does it email shoppers when something is back in stock?**

No. It keeps the emails shoppers give and counts, for each product, how many lists with an email hold it. Sending the notice is left to something else.

**What happens when a list is full?**

The next save answers 409, “a wishlist holds at most 200 products”. MaxItems in Config changes the number.

**Who can see what shoppers saved?**

An operator with wishlists.read, which managers and staff hold by default. Switching the plugin off closes the storefront routes only; the Wishlists screen keeps working.

### Related modules

Each is a directory under `ext/`, imported the same way. Where this one fits in the store: [What modules add to a direct-to-consumer store](https://kitcommerce.store/solutions/d2c/).

- [Abandoned cart emails in Go Remind shoppers about baskets they left in a GoCommerce store: a sequence of emails per kind of basket, a counted link back, and the order each one brings back.](https://kitcommerce.store/integrations/cart-recovery/)
- [Google Merchant Center and Meta feeds in Go Publish a GoCommerce catalogue as a Google Merchant Center RSS feed and a Meta catalogue CSV: one item per variant, built live from the catalogue.](https://kitcommerce.store/integrations/feeds/)
- [IndexNow in Go Tell Bing, Yandex, Seznam and Naver the moment a GoCommerce product or collection changes, over IndexNow: the setup, the key file, and why Google is not in it.](https://kitcommerce.store/integrations/indexnow/)
- [Klaviyo API in Go Send a GoCommerce store’s orders and abandoned carts to Klaviyo as events, under the metric names Klaviyo’s flows know. The key, the delays, the limits.](https://kitcommerce.store/integrations/klaviyo/)

### Source

Everything on this page is read from [`ext/wishlist`](https://github.com/itswadesh/gocommerce/tree/main/ext/wishlist) in the GoCommerce repository, MIT licensed. When this page and the code disagree, the code is right and this page is out of date.

- [ext/wishlist on GitHub](https://github.com/itswadesh/gocommerce/tree/main/ext/wishlist)
- [All GoCommerce modules](https://kitcommerce.store/integrations/)

### Try it against a store of your own

The backend + admin quick start runs GoCommerce’s API and admin on your own machine, without a storefront. Add this module to it and try it on test orders before a real one depends on it.

[Backend + admin quick start](https://kitcommerce.store/#one-command) · [Read the module](https://github.com/itswadesh/gocommerce/tree/main/ext/wishlist) · [All integrations](https://kitcommerce.store/integrations/)
