Resposta curta: sim, você pode adicionar uma wishlist ao Shopify sem um app. Não, o Shopify não traz uma nativamente. E não, a maioria dos métodos DIY não vai sobreviver a uma loja de verdade em escala — mas alguns funcionam bem se você tem menos de algumas centenas de produtos e um tema amigável para desenvolvedores.
Este guia traz todos os métodos que funcionam, o código real e uma avaliação honesta de onde cada um quebra. Ao final, você vai saber se deve implementar a versão DIY ou pular essa dor de cabeça.
O Shopify tem uma wishlist nativa?
Não. Em 2026, o Shopify ainda não inclui um recurso de wishlist em nenhum plano — nem no Basic, nem no Plus. Ou você constrói uma você mesmo ou instala um app de terceiros.
É por isso que essa keyword existe. Dezenas de milhares de lojistas buscam “shopify wishlist without app” todo mês na esperança de uma configuração escondida. Não existe. Mas existem quatro formas razoáveis de construir uma com Liquid, JavaScript e metafields — vamos passar por elas.
Método 1: wishlist com localStorage (o DIY mais comum)
Esse é o método que 90% dos tutoriais de “wishlist gratuita” ensinam. Você adiciona um botão de coração nos cards de produto, salva os dados do produto no localStorage do navegador e renderiza uma página de wishlist a partir desse array armazenado.
Prós: Não exige login. Funciona offline. Zero backend. ~50 linhas de código.
Contras: A wishlist vive em um navegador, em um único dispositivo. Se o cliente salvar no celular e voltar no desktop, a wishlist dele está vazia. Limpou os cookies? Sumiu. Trocou de navegador? Sumiu. Você também não consegue enviar e-mail quando um item baixa de preço ou volta ao estoque — você não tem ideia de quem é o cliente.
Passo 1 — Adicione um botão de wishlist na página do produto
Abra o editor de código do seu tema (Online Store → Themes → Edit code) e encontre o snippet do template do produto (geralmente snippets/product-card.liquid ou dentro de sections/main-product.liquid). Cole isso onde você quer o coração:
<button
type="button"
class="wishlist-btn"
data-id="{{ product.id }}"
data-handle="{{ product.handle }}"
data-title="{{ product.title | escape }}"
data-image="{{ product.featured_image | image_url: width: 400 }}"
data-price="{{ product.price | money }}"
aria-label="Add to wishlist">
<span class="wishlist-icon">♡</span>
<span class="wishlist-label">Save</span>
</button>
Passo 2 — Configure o JavaScript
Adicione isso em assets/wishlist.js (crie o arquivo) e inclua a partir do theme.liquid com {{ 'wishlist.js' | asset_url | script_tag }}:
(function () {
const KEY = 'shopify_wishlist_v1';
const read = () => JSON.parse(localStorage.getItem(KEY) || '[]');
const write = (list) => localStorage.setItem(KEY, JSON.stringify(list));
function syncButton(btn, list) {
const inList = list.some(i => i.id === btn.dataset.id);
btn.classList.toggle('in-wishlist', inList);
btn.querySelector('.wishlist-icon').textContent = inList ? '♥' : '♡';
btn.querySelector('.wishlist-label').textContent = inList ? 'Saved' : 'Save';
}
function updateCount() {
const count = read().length;
document.querySelectorAll('.wishlist-count').forEach(el => {
el.textContent = count;
el.hidden = count === 0;
});
}
document.querySelectorAll('.wishlist-btn').forEach(btn => {
syncButton(btn, read());
btn.addEventListener('click', () => {
let list = read();
const exists = list.find(i => i.id === btn.dataset.id);
if (exists) {
list = list.filter(i => i.id !== btn.dataset.id);
} else {
list.push({
id: btn.dataset.id,
handle: btn.dataset.handle,
title: btn.dataset.title,
image: btn.dataset.image,
price: btn.dataset.price,
addedAt: Date.now()
});
}
write(list);
syncButton(btn, list);
updateCount();
});
});
updateCount();
})();
Passo 3 — Construa a página da wishlist
Crie uma nova página em Online Store → Pages chamada “Wishlist” com handle wishlist. Depois crie um template templates/page.wishlist.liquid e atribua-o a essa página:
{% layout 'theme' %}
<div class="page-width wishlist-page">
<h1>Your wishlist</h1>
<div id="wishlist-grid" class="wishlist-grid"></div>
<p id="wishlist-empty" hidden>
Your wishlist is empty.
<a href="{{ routes.collections_url }}/all">Browse products</a>.
</p>
</div>
<script>
(function () {
const list = JSON.parse(localStorage.getItem('shopify_wishlist_v1') || '[]');
const grid = document.getElementById('wishlist-grid');
const empty = document.getElementById('wishlist-empty');
if (!list.length) { empty.hidden = false; return; }
grid.innerHTML = list.map(item => `
<article class="wishlist-card">
<a href="/products/${item.handle}">
<img src="${item.image}" alt="${item.title}" loading="lazy">
<h3>${item.title}</h3>
<p>${item.price}</p>
</a>
<button data-id="${item.id}" class="wishlist-remove">Remove</button>
</article>
`).join('');
grid.addEventListener('click', e => {
const btn = e.target.closest('.wishlist-remove');
if (!btn) return;
const next = JSON.parse(localStorage.getItem('shopify_wishlist_v1'))
.filter(i => i.id !== btn.dataset.id);
localStorage.setItem('shopify_wishlist_v1', JSON.stringify(next));
btn.closest('.wishlist-card').remove();
if (!next.length) { grid.innerHTML = ''; empty.hidden = false; }
});
})();
</script>
Essa é a wishlist completa com localStorage. Funciona. Também tem uma taxa de abandono de 30-50% para clientes multidispositivo, nenhuma analytics, e você não consegue enviar e-mail para ninguém quando algo que ele queria entra em promoção ou volta ao estoque. O que nos leva ao método 2.
Método 2: metafields de cliente (a abordagem DIY “adequada”)
Se seus clientes criam contas, você pode armazenar a wishlist no objeto customer via metafields. Agora a wishlist acompanha o cliente entre dispositivos, e você tecnicamente pode enviar e-mails para ele — embora enviar esses e-mails seja um problema à parte.
Prós: Sincronização entre dispositivos. Dados reais que você pode consultar. Sobrevive a limpezas de navegador.
Contras: Exige que o cliente faça login (queda imediata de 60-80% comparado ao modo anônimo). Escrever em metafields a partir do storefront exige a Storefront API com um customer access token, ou um App Proxy + uma pequena função serverless. Não existe solução de copiar e colar — você está se comprometendo com trabalho de desenvolvimento.
Configure o metafield
Vá em Settings → Custom data → Customers → Add definition:
- Namespace e key:
custom.wishlist - Tipo:
JSON - Acesso: Storefront read + write
Mostre o estado da wishlist no Liquid
{% if customer %}
{% assign wishlist_raw = customer.metafields.custom.wishlist.value | default: '[]' %}
{% assign wishlist = wishlist_raw | parse_json %}
<button
class="wishlist-btn-meta"
data-id="{{ product.id }}"
data-customer="{{ customer.id }}">
{% if wishlist contains product.id %}♥ Saved{% else %}♡ Save{% endif %}
</button>
{% else %}
<a href="{{ routes.account_login_url }}?return_url={{ request.path }}"
class="wishlist-btn-logged-out">♡ Log in to save</a>
{% endif %}
Escreva no metafield
É aqui que a coisa fica feia. A Storefront API não permite mutar customer.metafields diretamente a partir de JS anônimo — você precisa de um customer access token ou de um App Proxy autenticado. Um handler mínimo de App Proxy (Node.js, deployado no Vercel/Cloudflare Workers) fica assim:
// /api/wishlist-toggle (Shopify App Proxy)
export default async function handler(req) {
const { customerId, productId } = await req.json();
const query = `
mutation updateWishlist($id: ID!, $value: String!) {
customerUpdate(input: {
id: $id,
metafields: [{
namespace: "custom",
key: "wishlist",
type: "json",
value: $value
}]
}) {
customer { id }
userErrors { message }
}
}
`;
// 1. Fetch current list
// 2. Toggle productId
// 3. Send mutation to Admin API
// 4. Return new state
}
A implementação completa fica em torno de 200 linhas depois que você cobre autenticação, estados de erro e rate limiting. Tempo realista de construção para um desenvolvedor que nunca fez isso antes: 1-2 dias. Para quem já fez: 2-3 horas.
Método 3: carrinho escondido com line item properties (salvar para depois)
Alguns tutoriais sugerem abusar do carrinho adicionando itens de wishlist com quantidade 0 ou com uma propriedade customizada como _wishlist: true. Não faça isso. Isso quebra a matemática do carrinho, confunde o checkout e a maioria dos temas vai renderizar os itens de qualquer forma. Estou incluindo isso só para você saber que deve evitar quando vir essa sugestão no Reddit.
A única variante minimamente defensável: um atributo de carrinho separado de “Saved for later” que você renderiza fora do carrinho principal, assim:
<!-- in cart.liquid -->
{% assign saved = cart.attributes.saved_items | split: ',' %}
{% if saved.size > 0 %}
<div class="saved-for-later">
<h2>Saved for later</h2>
{% for handle in saved %}
{% assign p = all_products[handle] %}
<a href="/products/{{ p.handle }}">{{ p.title }} — {{ p.price | money }}</a>
{% endfor %}
</div>
{% endif %}
É uma solução pela metade. Atributos de carrinho desaparecem quando o carrinho é esvaziado. Pule.
Método 4: wishlist via URL compartilhável (o truque social)
Esse aqui não é uma wishlist de verdade — é um link de “compartilhe seus favoritos”. Você monta uma lista no client-side e a codifica em uma URL que o cliente pode compartilhar ou salvar nos favoritos.
// Build a share URL from the localStorage list
function getShareUrl() {
const ids = JSON.parse(localStorage.getItem('shopify_wishlist_v1') || '[]')
.map(i => i.id)
.join(',');
return `${location.origin}/pages/wishlist?items=${ids}`;
}
// On the wishlist page, hydrate from ?items=
const params = new URLSearchParams(location.search);
if (params.get('items')) {
const ids = params.get('items').split(',');
// Fetch each /products/{id}.js and render
Promise.all(ids.map(id =>
fetch(`/products/${id}.js`).then(r => r.json())
)).then(renderWishlist);
}
Útil como um complemento ao método 1 — dá aos clientes uma forma de compartilhar listas com amigos ou enviar para si mesmos. Não é uma wishlist por si só.
O veredito honesto: quando DIY serve e quando quebra
DIY funciona se você puder responder sim para as quatro perguntas:
- Sua loja tem menos de ~500 SKUs (para a manutenção manual continuar viável).
- Você não se importa com sincronização entre dispositivos (ou já está forçando contas de cliente de qualquer forma).
- Você não planeja enviar e-mail para os clientes quando itens da wishlist entrarem em promoção ou voltarem ao estoque.
- Você tem um desenvolvedor no time ou se sente confortável editando Liquid sozinho.
DIY quebra no momento em que você quer:
- Enviar um e-mail “seu item da wishlist voltou ao estoque” para um cliente — você não tem ideia de quem é dono daquela entrada no localStorage.
- Recuperar wishlists abandonadas com SMS ou e-mail — mesmo problema.
- Mostrar conversão de wishlist no analytics — você pode disparar eventos GA4, mas não consegue amarrar isso a receita sem trabalho de backend.
- Deixar visitantes salvarem sem forçar criação de conta, e sincronizar com o e-mail deles quando fizerem login depois.
- Entregar para um marketeiro não-técnico gerenciar.
Essas não são limitações teóricas. São os motivos pelos quais a maioria das lojas que começa com uma wishlist DIY troca para um app dentro de 6 meses.
Quanto uma wishlist DIY realmente custa (sendo honesto)
As pessoas pesquisam “sem app” porque assumem que o app é a opção cara. Vamos conferir.
Um desenvolvedor construindo a versão com localStorage: 2-4 horas. A $75/hora, isso dá $150-$300, mais zero custo recorrente. Razoável.
Um desenvolvedor construindo a versão com metafield e gatilhos de e-mail: 8-16 horas. $600-$1.200, mais um Klaviyo ou similar para de fato enviar os e-mails ($20-$45/mês). Mais manutenção toda vez que seu tema atualizar ou o Shopify mudar as extensões de checkout.
Um app de wishlist + um app de back-in-stock separado + um app de preorder separado: tipicamente $15-25/mês cada. Então $45-75/mês para os três recursos.
Um app combinado: uma única conta.
Ou: tenha os três num só app, com plano gratuito
Aviso — fazemos o Notify Me!, e construímos exatamente porque a maioria das lojas precisa de wishlist + back-in-stock + preorder juntos. Cliente salva um produto → ele sai de estoque → cliente é notificado → se nunca voltar, você oferece um preorder. Três recursos que pertencem juntos.
Como é a configuração na prática
Você ativa os recursos por página (produto, coleção, home) no painel — sem código de tema para manter:
A tela Wishlist no Notify Me! — modo visitante vem ativado por padrão, e a wishlist é vinculada à conta do cliente assim que ele faz login. Sem alterações de código.
Botão na página do produto — totalmente customizável
Escolha um ícone de coração, marcador ou estrela. Edite os rótulos dos dois estados. O widget é renderizado inline ao lado do seu botão Adicionar ao Carrinho:
Configurações do botão na página do produto — defina os rótulos antes/depois, o ícone e o estilo sem encostar no Liquid.
Widget de página de coleção — funciona em cada card
Onde os métodos DIY mais sofrem: colocar um botão de salvar funcional em cada tile da página de coleção. O app resolve isso com um único toggle:
Widget da página de coleção — escolha ícone, posição e estilo de exibição. Renderiza em cada card de produto automaticamente.
Preços (cobrança anual)
| Plano | Preço | Ações de wishlist | Notificações de volta ao estoque | Preorders |
|---|---|---|---|---|
| Lite | Grátis | 50 vitalício | 100 vitalício | 5 vitalício |
| Starter | $15,92/mês | 24.000/ano | 6.000/ano | 6.000/ano |
| Standard | $31,92/mês | 120.000/ano | 18.000/ano | 18.000/ano |
| Rocket | $55,92/mês | 300.000/ano | 60.000/ano | 120.000/ano |
| Plus | $399,92/mês | Ilimitado | Ilimitado | Ilimitado |
Detalhes completos dos planos na página de preços. O plano Lite gratuito existe para você de fato testar na sua loja antes de pagar qualquer coisa. A maioria das lojas fica no Starter a longo prazo — $15,92/mês substitui três apps que você instalaria separadamente.
Recursos que as versões DIY acima não conseguem igualar:
- Modo visitante (sem login forçado) — a wishlist se vincula automaticamente à conta no primeiro login
- Múltiplas listas nomeadas por cliente
- Widgets de wishlist nas páginas inicial, de coleção e de produto
- Disparos automáticos de e-mail e SMS em queda de preço, estoque baixo e volta ao estoque
- Botões de preorder e pagamentos parciais nativos
- Customização total via Liquid para combinar com seu tema
- Suporte a B2B e DTC out of the box
Start free on the Shopify App Store →
FAQ
Dá para adicionar uma wishlist ao Shopify sem programar?
Não sem um app. Todo método no-code exige instalar um app de wishlist ou colar código no seu tema. Não existe um toggle nativo.
Existe wishlist gratuita para Shopify?
Sim, algumas. O método com localStorage acima é gratuito se você mesmo construir. Em termos de app, o plano Lite do Notify Me! é gratuito até 50 ações de wishlist vitalícias, o que é suficiente para validar se os clientes realmente usam o recurso na sua loja antes de pagar por um plano maior.
O Shopify 2.0 tem wishlist?
Não. O Shopify 2.0 é a arquitetura de temas (sections, blocks, app blocks) — não adiciona um recurso de wishlist. Ele torna a instalação de um app de wishlist mais limpa via app blocks, o que é o motivo pelo qual a maioria dos apps modernos de wishlist se integra em temas 2.0 em segundos.
Dá para adicionar uma wishlist só com Liquid?
Parcialmente. O Liquid consegue exibir uma wishlist se o dado estiver num metafield de cliente, mas o Liquid não consegue escrever em metafields a partir do storefront. Você vai precisar de JavaScript e da Storefront API ou de um App Proxy para salvar itens.
Como adiciono uma wishlist à página de produto do Shopify sem app?
Use o Método 1 acima: cole o snippet do botão de wishlist no seu template de produto, adicione wishlist.js aos assets do seu tema e crie uma página de wishlist a partir de templates/page.wishlist.liquid. Código completo neste guia.
Wishlist realmente aumenta conversão?
Sim — salvar sinaliza intenção real de compra, e clientes que usam wishlist costumam converter a taxas significativamente maiores do que os que só navegam. O ganho maior vem de enviar e-mail para os donos da wishlist quando um item entra em promoção ou volta ao estoque — é aí que os métodos DIY falham.
O que acontece com uma wishlist em localStorage quando o cliente limpa os cookies?
Ela é deletada permanentemente. Sem backup, sem recuperação. Esse é o maior motivo isolado pelo qual lojas superam a abordagem DIY.
Uma wishlist pode disparar e-mails de volta ao estoque?
Só se você amarrar a wishlist ao e-mail do cliente. localStorage não consegue. Metafields de cliente conseguem, mas você ainda precisa de um backend para detectar mudanças de estoque e enviar o e-mail. Um app que faz as duas coisas — como o Notify Me! — elimina esse trabalho por completo.
Qual a diferença entre wishlist e waitlist?
Uma wishlist é uma lista curada de produtos que o cliente quer lembrar; uma waitlist é uma fila para um produto que está temporariamente fora de estoque ou em pré-lançamento. Wishlists são abertas; waitlists são limitadas no tempo pelo estoque ou data de lançamento. A maioria das lojas eventualmente quer as duas.
É melhor usar Continue Selling When Out of Stock ou uma wishlist?
Problema diferente. Continuar vendendo quando está fora de estoque permite aceitar pedidos para inventário indisponível (essencialmente um preorder). Uma wishlist deixa o cliente salvar itens sem se comprometer. Se você está tentando capturar demanda em um produto indisponível, geralmente quer os dois — uma wishlist para coletar intenção e uma opção de preorder para os clientes prontos para comprar agora.
Última atualização: junho de 2026. Escrito para temas Shopify no Online Store 2.0. Se seu tema for mais antigo (vintage), os caminhos do Liquid mudam um pouco — o JavaScript é idêntico.
