← Help

Save to wishlist button

The button lets visitors of your shop or blog save one of your products to their Things To Have wishlist. It is a single link — no script to load, nothing that runs on your visitors' machines, and no account needed to put it on your site.

Build your button

Fill in the product address and name, then copy the snippet. Paste it wherever you want the button to appear.

Leave empty to get a snippet with a placeholder you can fill in from your shop template

Optional. Include a currency, like 24 USD. In a template, use PRODUCT_PRICE

Optional. Shown while someone signs in to save it. In a template, use PRODUCT_IMAGE

<a href="https://thingstohave.app/add?v=1&amp;via=embed&amp;url=PRODUCT_URL&amp;name=PRODUCT_NAME" target="_blank" rel="noopener nofollow" style="display:inline-flex;align-items:center;gap:0.5em;box-sizing:border-box;min-height:2.5em;padding:0.5em 1em;border-radius:4px;font-family:inherit;font-size:0.875em;font-weight:400;line-height:1;text-decoration:none;white-space:nowrap;vertical-align:middle;color-scheme:light dark;border:2px solid #d3d3d3;border-color:light-dark(#d3d3d3,#34383f);background:#ffffff;background:light-dark(#ffffff,#23262c);color:#000000;color:light-dark(#000000,#e8e8e8)"><img src="https://thingstohave.app/embed/star.svg" width="18" height="18" alt="" style="display:block;width:1.25em;height:1.25em;border:0">Save to wishlist</a>

That is the whole install. There is no key to store, nothing to configure, and nothing to keep up to date.

One button per product

If you are pasting the snippet into a template rather than a single page, leave the address and name empty. The snippet then contains PRODUCT_URL and PRODUCT_NAME, which you replace with your template's own variables.

Encode both values, or the link breaks silently. They sit inside a query string, so an unencoded &, # or ? in a product name ends the parameter early. A product called Porter-Yoshida & Co. Tanker saves as Porter-Yoshida, with Co. Tanker read as a stray parameter and thrown away. Nothing errors — the visitor just gets a wishlist entry with the wrong name.

Every template language has a filter for this:

PlatformAddressName
Shopify{{ shop.url | append: product.url | url_encode }}{{ product.title | url_encode }}
WordPress<?php echo urlencode( get_permalink() ); ?><?php echo urlencode( get_the_title() ); ?>
Jinja / Nunjucks{{ product.url | urlencode }}{{ product.title | urlencode }}
JavaScriptencodeURIComponent(product.url)encodeURIComponent(product.title)

Leave the rest of the snippet as it is.

Note that the builder above only accepts a real web address in the address field. If you paste a template variable into it, it falls back to the PRODUCT_URL placeholder — which is the value you want anyway.

Link parameters

The button is a link to /add. If you would rather build the URL yourself, this is the contract:

ParameterRequiredMeaning
urlyesThe product page address, URL-encoded. Must be http or https
namenoThe product name, URL-encoded
pricenoAmount with a currency, like 24 USD or 19,99 €. An amount without a currency is ignored
imagenoProduct image address, URL-encoded. Must be http or https
vnoWhich version of the snippet this is. We use it to tell old buttons apart
vianoWhere the click came from. The button sends embed

Pass the canonical product address, not whatever path the visitor happens to be on. A wishlist entry outlives the filtered, sorted or campaign-tagged URL someone arrived through, and the canonical address is the one that will still resolve a year from now.

Unknown parameters are dropped.

Light, dark, or automatic

The default button carries its own light and dark palettes and switches with the visitor's system setting, so it looks right on a site that follows prefers-color-scheme. Browsers too old to understand that show the light palette.

Pick Light or Dark instead if your site pins its palette. A permanently dark page wants the dark button for every visitor, whatever their system is set to.

What happens when someone clicks

A new tab opens on Things To Have with the name and link already filled in, and we fetch the price and image. The visitor picks a list and saves.

Visitors who are not signed in are asked to sign in first, then land back on the filled-in form with nothing lost. That sign-in page shows them what they are about to save, built only from what your link carries — so filling in name, price and image is what makes it look like your product rather than a bare address.

Good to know

  • We do not track your visitors. The button is an ordinary link. Nothing runs until someone clicks it.
  • The link is marked nofollow. We do not want your product pages passing us search ranking, and you should not have to think about whether a widget is quietly doing that. It also carries noopener, which stops the new tab from reaching back into your page.
  • A strict content policy can strip the styling. If your site sends a Content-Security-Policy whose style-src omits 'unsafe-inline', browsers drop the button's inline styles; if its img-src excludes thingstohave.app, the star does not load. Neither breaks anything — the button falls back to a plain working link.

Adding things without a browser

For phone shortcuts, scripts, or automation services, use the Webhook API instead. If you only want to save pages for yourself as you browse, the quick add bookmarklet is a better fit.