Passo a passo
-
Inclua o SDK
Adicione a tag
<script>no<head>ou antes do</body>:<script src="https://pay.celetus.com/assets/js/celetus.upsell.sdk.js"></script> -
Monte o HTML do seu jeito
O SDK não injeta DOM — você controla 100% do markup. Dê
idnos elementos que vai preencher (título, preço, botões, QR code).<div class="upsell"> <h1 id="titulo">Carregando…</h1> <p id="preco"></p> <img id="produto-img" alt="" /> <div id="passo-oferta"> <button id="sim">Sim, quero!</button> <button id="nao">Não, obrigado</button> </div> <div id="passo-pix" hidden> <img id="qr" alt="QR Code PIX" /> <button id="copiar">Copiar chave PIX</button> </div> <div id="passo-pago" hidden>✅ Pagamento confirmado!</div> </div> -
Pegue a
keyno painelNo painel Celetus, em Funil de vendas, clique no ícone
</>da etapa que você quer integrar e copie o valor dakey. Ela fica hardcoded no seu código — mesma mecânica que o widget iframe atual já usa hoje comUpsell.Widget.show({ key }). -
Inicialize e carregue os dados
Passe a
keynoinit()e useloadStep()para buscar os dados do passo (produto, preço, labels). Osfido SDK lê sozinho da URL (plantado pelo redirect do checkout).const upsell = CeletusUpsell.init({ key: "SUA_KEY_AQUI" // ← copiada do painel Celetus }); upsell.loadStep().then(step => { document.getElementById("titulo").textContent = step.productName; document.getElementById("preco").textContent = step.valueFormatted; document.getElementById("produto-img").src = step.productImage; document.getElementById("sim").textContent = step.positiveButtonLabel; document.getElementById("nao").textContent = step.negativeButtonLabel; }); -
Amarre os botões
document.getElementById("sim").onclick = () => upsell.accept(); document.getElementById("nao").onclick = () => upsell.decline(); -
Reaja aos eventos
Se for PIX, o código chega no evento
qrReady. Se for cartão one-click, o eventopaiddispara direto.upsell.on("qrReady", ({ pixQrUrl, pixQrCode }) => { document.getElementById("passo-oferta").hidden = true; document.getElementById("passo-pix").hidden = false; const qr = document.getElementById("qr"); // pixQrUrl pode ser uma URL http OU um código copia-e-cola. if (pixQrUrl && pixQrUrl.startsWith("http")) { qr.src = pixQrUrl; } else { // Código copia-e-cola — use qrcode.js se quiser gerar imagem local. qr.alt = pixQrCode; } document.getElementById("copiar").onclick = () => { navigator.clipboard.writeText(pixQrCode); }; }); upsell.on("paid", () => { document.getElementById("passo-pix").hidden = true; document.getElementById("passo-oferta").hidden = true; document.getElementById("passo-pago").hidden = false; // Avança para a próxima etapa do funil (configurada no painel Celetus) setTimeout(() => upsell.next(), 1500); }); upsell.on("failed", ({ reason }) => alert("Pagamento: " + reason)); upsell.on("error", (err) => console.error(err)); -
Encadeamento automático entre etapas
Um funil de upsell pode ter várias etapas em sequência. As URLs da próxima etapa são configuradas no painel Celetus (positiva e negativa) — você não precisa hardcodar caminhos no código. Use:
upsell.next()— auto-detecta direção pelo estado atual (positivo sepaid, negativo caso contrário)upsell.decline()— atalho para o caminho negativo (quando o cliente clica "Não, obrigado")
O SDK preserva a query string da página no redirect (exceto
?key=, substituída pela key da próxima etapa), garantindo quesfid, UTMs e outros params cheguem intactos.Se preferir, use
step.positivePageUrldiretamente em um<a href>, ou chameupsell.next({ noRedirect: true })pra obter a URL de destino sem navegar. -
(Opcional) Gerar QR a partir do copia-e-cola
Quando o evento traz só o código copia-e-cola em string, inclua a lib
qrcodevia CDN para gerar a imagem localmente:<script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.3/build/qrcode.min.js"></script> <script> upsell.on("qrReady", ({ pixQrUrl, pixQrCode }) => { const qr = document.getElementById("qr"); if (pixQrUrl && pixQrUrl.startsWith("http")) { qr.src = pixQrUrl; } else if (pixQrCode) { QRCode.toDataURL(pixQrCode, { width: 240 }, (err, url) => { if (!err) qr.src = url; }); } }); </script>
⚠️ Link de uso único (importante para testes)
localStorage por 1 minuto para
sobreviver a reloads dentro dessa janela.
-
Se ver a mensagem "Link inválido ou já consumido" no
evento
error, gere uma nova compra de teste para obter umsfidnovo. -
upsell.clearStepCache()limpa a cópia local, mas não recupera um link já consumido no backend.
Exemplo executável
Veja um arquivo completo pronto pra abrir no navegador: abrir exemplo.html.
Deploy
Hospede o HTML em qualquer lugar (S3, Netlify, Vercel, GitHub Pages, seu WordPress, Framer, Wix). Depois configure no painel Celetus, no passo do funil, a URL da sua página customizada — o checkout principal passa a redirecionar para lá após a compra.