> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chargefy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Criar um funil de upsell

> Ofereça produtos extras depois de um pagamento confirmado por cartão ou Pix, com um clique quando houver cartão salvo e checkout assistido quando não houver.

Um **funil de upsell** aproveita o melhor momento de venda que existe: o segundo
seguinte à compra aprovada. Em vez de mandar o comprador direto para a página de
obrigado, um funil de upsell pode levar o comprador para uma página sua com uma
nova oferta. Se houver um cartão salvo, o aceite tenta cobrar com um clique. Se
não houver — ou se essa cobrança for recusada — a Chargefy abre um checkout
compacto com **cartão e Pix**, já preenchido com os dados conhecidos do
comprador.

Você monta a sequência num canvas: cada etapa é uma oferta, e cada oferta tem
duas saídas — o que acontece se ele aceitar e o que acontece se ele recusar.
Aceitou o upsell? Talvez venha um segundo produto. Recusou? Talvez venha uma
versão mais barata. A sequência é sua.

<Frame caption="No canvas, cada card representa uma oferta. As saídas &#x22;Sim&#x22; e &#x22;Não&#x22; conectam a próxima etapa do percurso.">
  <img src="https://mintcdn.com/scaleup-28315a31/ETX95EjiUd8FtxIq/assets/payments/create-upsell-funnel/canvas-configured.jpg?fit=max&auto=format&n=ETX95EjiUd8FtxIq&q=85&s=ca40e1e78eddcdfff3529cf5cb4e4170" alt="Canvas real de um funil ativo com o link de pagamento de entrada e duas ofertas conectadas pelo caminho Sim" width="1280" height="720" data-path="assets/payments/create-upsell-funnel/canvas-configured.jpg" />
</Frame>

<Note>
  **A página da oferta é sua, os botões são nossos.**

  A Chargefy não hospeda a página de upsell. Você cria e publica a página da oferta
  no seu próprio site, com **total controle sobre o conteúdo, o layout e a
  identidade visual**. A Chargefy insere apenas os dois botões de decisão —
  "quero" e "não quero" — nos pontos que você definir.
</Note>

## O que precisa acontecer para o comprador entrar no funil

O funil é armado no instante em que o pagamento é aprovado. Todas as condições
abaixo precisam valer ao mesmo tempo:

| Condição                                                                            | Por quê                                                                                                   |
| ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| A venda veio do [payment link](/payments/create-payment-link) que dá start no funil | O funil é uma propriedade do link, não da sessão avulsa. Sessões criadas direto pela API não armam funil. |
| O pagamento foi confirmado no **cartão de crédito ou Pix**                          | Boleto não dá start em funil.                                                                             |
| O dinheiro foi **confirmado**                                                       | Emitir um QR Code não basta. O funil começa apenas depois da confirmação do Pix ou do cartão.             |
| O funil está **ativo** e tem **etapa de entrada**                                   | Sem primeira oferta não há para onde mandar o comprador.                                                  |
| Funil e link estão no **mesmo ambiente**                                            | Um funil de produção não recebe tráfego de sandbox, e vice-versa.                                         |

Faltou alguma? O comprador simplesmente segue o caminho normal do checkout —
a `success_url` do link. **Nenhum problema no funil derruba, atrasa ou desfaz a
venda que já foi aprovada.** O funil é sempre um extra em cima de uma compra que
já deu certo.

## A jornada do comprador

<Steps>
  <Step title="Ele paga no checkout">
    Compra normal no seu payment link, com cartão ou Pix confirmado.
  </Step>

  <Step title="A Chargefy o leva para a página da primeira oferta">
    Em vez da `success_url`, ele cai na página que você definiu na etapa de
    entrada, levando uma **chave de acesso** na URL. É ela que diz quem é ele e
    qual oferta ele está vendo.
  </Step>

  <Step title="Ele decide">
    Um clique em "quero" tenta o cartão salvo, quando ele existe. Sem cartão ou
    depois de uma recusa definitiva, abre um modal para escolher Pix ou cartão.
    Um clique em "não quero" registra a recusa e segue o caminho configurado.
  </Step>

  <Step title="A decisão leva à próxima etapa">
    Cada saída ("sim" e "não") aponta para outra etapa ou encerra o funil. Se
    aponta para outra etapa, a Chargefy leva o comprador para a página dela, com
    a chave de acesso atualizada.
  </Step>

  <Step title="O funil termina">
    Na última etapa, o comprador vai para o endereço final que você configurou
    no botão — normalmente a sua página de obrigado ou a área de membros.
  </Step>
</Steps>

<Note>
  No Pix da compra inicial, mantenha a página do checkout aberta. Assim que o
  pagamento for confirmado, ela leva o comprador para a primeira oferta. Se o
  comprador fechar a página antes da confirmação, não há recuperação automática
  desse acesso ao funil.
</Note>

<Warning>
  **A `success_url` do link não é o fim do funil**

  Quando o funil arma, ele assume o pós-pagamento inteiro. O destino final é o
  que você colocar no atributo `complete-url` dos botões da última etapa. Sem
  ele, o comprador fica na própria página da oferta e vê um aviso de compra
  confirmada — o que funciona, mas quase nunca é o que você quer.
</Warning>

## Anatomia de uma etapa

Cada etapa do funil junta cinco coisas:

| O que você define        | Para que serve                                                                                                             |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| **Nome interno**         | Só para você se achar no canvas. O comprador nunca vê.                                                                     |
| **URL da página**        | O endereço da sua página que hospeda os botões daquela oferta.                                                             |
| **Oferta**               | Um preço avulso do seu catálogo. É esse valor que o "sim" cobra.                                                           |
| **Texto dos botões**     | A frase de cada botão, até 60 caracteres. Em branco, a Chargefy usa "Sim, eu quero essa oferta" e "Não, obrigado".         |
| **Parcelas sob o botão** | Liga ou desliga a linha "12x de R\$ 40,83 sem juros" abaixo do aceite. A cobrança parcela do mesmo jeito, exibindo ou não. |

E duas saídas: **sim** e **não**. Cada uma aponta para outra etapa ou fica vazia,
encerrando o funil ali.

<Frame caption="Ao selecionar uma etapa, você configura a URL da oferta, o preço do catálogo e o texto dos dois botões enquanto acompanha o resultado no próprio canvas.">
  <img src="https://mintcdn.com/scaleup-28315a31/AL7TxjaPFJ8w5l48/assets/payments/create-upsell-funnel/stage-editor.jpg?fit=max&auto=format&n=AL7TxjaPFJ8w5l48&q=85&s=353e84df39937037313d726905e021b2" alt="Editor real de uma etapa do funil com URL da página, oferta, textos de aceite e recusa e prévia dos botões" width="2000" height="1418" data-path="assets/payments/create-upsell-funnel/stage-editor.jpg" />
</Frame>

<Note>
  A oferta é sempre um preço avulso do seu catálogo — não um valor digitado à
  mão. Isso mantém relatório, produto e conciliação consistentes com o resto da
  operação. O preço precisa estar ativo, no mesmo ambiente do funil e valer no
  mínimo R\$ 5,00.
</Note>

## Instalar os botões na sua página

A página da oferta é uma página comum do seu site. Você só marca onde os dois
botões entram.

<Frame caption="Exemplo de uma página de oferta: o conteúdo e o layout são seus; a Chargefy renderiza apenas os dois botões de decisão.">
  <img src="https://mintcdn.com/scaleup-28315a31/AL7TxjaPFJ8w5l48/assets/payments/create-upsell-funnel/offer-page.svg?fit=max&auto=format&n=AL7TxjaPFJ8w5l48&q=85&s=d123896448aab4e33970fea1b62f7e42" alt="Mockup de uma página de oferta com imagem do produto, texto de venda, preço e os botões Sim, quero adicionar à compra e Não, obrigado" width="1280" height="760" data-path="assets/payments/create-upsell-funnel/offer-page.svg" />
</Frame>

Carregue a biblioteca uma vez, no `<head>`:

```html theme={"theme":"css-variables"}
<script src="https://api.chargefy.io/v1/chargefy.js"></script>
```

E marque os dois lugares onde os botões devem aparecer:

```html theme={"theme":"css-variables"}
<chargefy-offer-accept
  complete-url="https://meusite.com/obrigado"
></chargefy-offer-accept>
<chargefy-offer-decline
  complete-url="https://meusite.com/obrigado"
></chargefy-offer-decline>
```

O atributo `complete-url` é opcional e só entra em ação quando aquela decisão
**encerra** o funil. Enquanto houver próxima etapa, quem manda é o funil — a
Chargefy leva o comprador para a página seguinte e ignora o `complete-url`.

<Tip>
  **O código é igual em todas as etapas**

  Você não muda uma linha entre a etapa 1 e a etapa 3. Quem decide qual oferta
  aparece é a chave de acesso que vem na URL, resolvida no servidor da Chargefy —
  não o HTML da página. Uma etapa nova só precisa de uma página nova com o mesmo
  trecho colado.
</Tip>

### A identidade visual vem da sua marca

Cor, fonte e formato de canto dos botões seguem a identidade da sua organização
— a mesma que veste o seu checkout. Não há ajuste por página nem por etapa, de
propósito: o comprador acabou de pagar numa tela sua e precisa reconhecer o
botão como parte da mesma experiência. Ajuste a identidade em **Configurações →
Checkout** no dashboard, no mesmo lugar do
[Checkout Builder](/payments/configure-checkout-page).

<Frame caption="A mesma integração acompanha a cor, a tipografia, o formato dos cantos e o tema definidos para o checkout.">
  <img src="https://mintcdn.com/scaleup-28315a31/AL7TxjaPFJ8w5l48/assets/payments/create-upsell-funnel/button-branding.svg?fit=max&auto=format&n=AL7TxjaPFJ8w5l48&q=85&s=29d048d3f0ab0048c5d6b0384ab771b4" alt="Comparação dos botões de upsell em três identidades visuais: tema claro com cantos arredondados, tema escuro com formato pill e tema claro editorial com cantos retos" width="1440" height="690" data-path="assets/payments/create-upsell-funnel/button-branding.svg" />
</Frame>

O que muda por etapa é só o **texto** de cada botão, porque cada oferta merece o
próprio convite.

## Duração da sessão

A sessão do funil começa quando a compra inicial é aprovada e dura **30
minutos**. Durante esse período, a chave de acesso na URL identifica o comprador,
a etapa atual e a oferta que ele pode aceitar.

Sem uma chave de acesso válida, os botões não aparecem. Isso acontece quando
alguém abre a página sem ter vindo de uma compra aprovada, quando a sessão vence
ou quando o funil já terminou. A página continua funcionando normalmente, mas
sem permitir a cobrança de uma oferta.

A chave de acesso vale para uma única sequência. Depois de 30 minutos, a sessão
expira, os botões somem e a chave não pode ser reutilizada.

<Note>
  A chave de acesso não expõe número, código de segurança, token ou dados
  cadastrais. Quando o funil precisa pedir outra forma de pagamento, o
  Chargefy.js abre uma página hospedada pela Chargefy: centralizada no desktop e
  em tela cheia no celular. Sua página recebe apenas os estados necessários,
  como pagamento concluído ou modal fechado.
</Note>

## Cada "sim" é uma cobrança independente

Aceitar uma oferta **não** aumenta o valor da compra original. A Chargefy cria
uma cobrança nova, separada:

| Característica                | Como funciona                                                                                                                                               |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Documento gerado              | Um `payment_intent` próprio, com o `charge` correspondente. Quando o modal é necessário, ele também usa uma `checkout.session` exclusiva daquela oferta.    |
| Webhook                       | [`payment.intent.succeeded`](/api-reference/webhooks/payment.intent.succeeded), igual a qualquer outra venda aprovada.                                      |
| Parcelamento                  | Espelha a compra que deu start: todo o funil cobra no mesmo número de parcelas escolhido no checkout do link principal, limitado pelo valor de cada oferta. |
| Juros ou taxa de conveniência | Nunca. O comprador paga exatamente o valor do preço, mesmo parcelando.                                                                                      |
| Fatura                        | Não gera. Upsell é venda avulsa, não item de fatura.                                                                                                        |

Na prática: no extrato e nos relatórios, cada oferta aceita aparece como uma
venda própria, na hora em que aconteceu. Sua automação de entrega não precisa de
tratamento especial — ela reage ao mesmo evento de sempre.

## Quando o clique não consegue cobrar

O texto do botão continua exatamente como você escreveu. O comportamento é que
se adapta:

| Situação                                           | O que o comprador vê                                                                                                     |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Há cartão salvo e a cobrança é aprovada            | A oferta é paga e o funil avança sem abrir formulário.                                                                   |
| Não há cartão salvo                                | Abre o modal com **Pagar com Pix** e **Pagar com cartão**.                                                               |
| O cartão salvo é recusado de forma definitiva      | Abre o mesmo modal para o comprador escolher outra forma.                                                                |
| A resposta da cobrança é incerta, como num timeout | O botão permanece processando enquanto a Chargefy reconcilia. Outra cobrança não é aberta até o resultado ser conhecido. |

No Pix, o QR Code é gerado na hora. Fechar e reabrir o modal mostra o mesmo QR
Code enquanto ele estiver válido. Depois que vencer, o comprador pode gerar
outro no mesmo checkout. Enquanto um Pix está pendente, a tentativa fica nele;
o comprador não inicia uma cobrança paralela no cartão.

No cartão, nome, documento, telefone e endereço conhecidos aparecem
preenchidos, mas continuam editáveis. Número do cartão e código de segurança
nunca são reaproveitados no formulário. Se esse novo cartão for aprovado e
salvo, ele passa a ser o cartão de um clique das ofertas seguintes.

<Frame caption="Sem cartão salvo, o checkout assistido já abre com os dados conhecidos do comprador. Ele pode corrigir qualquer campo antes de pagar.">
  <img src="https://mintcdn.com/scaleup-28315a31/ETX95EjiUd8FtxIq/assets/payments/create-upsell-funnel/card-prefilled.jpg?fit=max&auto=format&n=ETX95EjiUd8FtxIq&q=85&s=1db828db3551889ee4bb45d9543191b5" alt="Modal de pagamento de uma oferta com abas para cartão e Pix e dados cadastrais do comprador já preenchidos" width="1280" height="720" data-path="assets/payments/create-upsell-funnel/card-prefilled.jpg" />
</Frame>

<Frame caption="Ao escolher Pix, o QR Code nasce no mesmo modal. Fechar e reabrir preserva este código enquanto ele estiver válido.">
  <img src="https://mintcdn.com/scaleup-28315a31/ETX95EjiUd8FtxIq/assets/payments/create-upsell-funnel/pix-modal.jpg?fit=max&auto=format&n=ETX95EjiUd8FtxIq&q=85&s=b43b86f7f99ab5382f88092a22ef60bc" alt="Modal de pagamento de uma oferta exibindo um QR Code Pix com contador de validade" width="1280" height="720" data-path="assets/payments/create-upsell-funnel/pix-modal.jpg" />
</Frame>

## A mesma oferta não é cobrada duas vezes

Cada etapa aceita **uma decisão só**. Clicar novamente, atualizar a página
durante o processamento ou voltar pelo navegador não cria outra cobrança. A
Chargefy mostra o resultado já registrado ou informa que a decisão ainda está
sendo processada.

Essa proteção é aplicada antes de a cobrança ser enviada ao banco.

## Status do funil na lista

| Status         | O que significa                                                                                                                                  |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Ativo**      | Está no ar e recebendo compradores de verdade.                                                                                                   |
| **Incompleto** | A chave está ligada, mas falta algo: o payment link que dá start está arquivado ou ausente, ou nenhuma etapa de entrada definida. Ninguém entra. |
| **Inativo**    | Desligado. O link que dá start segue a `success_url` normal do checkout.                                                                         |

"Incompleto" existe porque ligar a chave não coloca um funil no ar. Sem link
ativo ninguém entra, e sem etapa de entrada o checkout não tem para onde mandar
o comprador. O status diz a verdade em vez de prometer um funil que não roda.

## O link que dá start

Cada funil é disparado por **um** payment link, e cada link dá start em **um**
funil. Você escolhe esse link na criação do funil e pode trocá-lo depois, nas
configurações. Link e funil precisam estar no mesmo ambiente.

<Frame caption="Se o funil estiver sem link de entrada, o primeiro card fica vermelho, explica o bloqueio e leva direto à configuração.">
  <img src="https://mintcdn.com/scaleup-28315a31/ETX95EjiUd8FtxIq/assets/payments/create-upsell-funnel/missing-entry-link.jpg?fit=max&auto=format&n=ETX95EjiUd8FtxIq&q=85&s=d55932b9a30c2e47f1005e8d96f15a3f" alt="Canvas de um funil incompleto com o card inicial em vermelho, selo Sem link e botão Escolher link de pagamento" width="1280" height="720" data-path="assets/payments/create-upsell-funnel/missing-entry-link.jpg" />
</Frame>

Trocar o link é reversível e vale a partir da próxima compra — quem já está
andando pelo funil termina o percurso que começou. Remover o funil solta o link:
ele volta à `success_url` normal. As cobranças já feitas e as métricas do
período são preservadas.

## Testar em sandbox

Funis funcionam em sandbox exatamente como em produção. Crie o funil no ambiente
de teste escolhendo um payment link de teste e conclua a compra com cartão ou
Pix. Para conferir o fallback, entre com Pix — ou use um cartão salvo que seja
recusado na oferta — e aceite uma etapa. O modal permite gerar um novo Pix ou
informar outro cartão sem pedir novamente o que a Chargefy já conhece.

Cartões de teste e cenários em [Sandbox](/api-reference/sandbox).

## Ler o estado do funil na sua página

Para uma página de oferta mais elaborada — mostrar o valor no título, o final do
cartão, um contador — o Chargefy.js expõe o estado da chave de acesso atual:

```js theme={"theme":"css-variables"}
Chargefy.Funnel.getState().then((run) => {
  console.log(run.offer.name, run.offer.amount, run.card?.last4);
});
```

A promessa é rejeitada quando não há chave de acesso válida na URL, o que também
serve como teste de "essa visita veio de uma compra?".

```json theme={"theme":"css-variables"}
{
  "id": "frun_8kR3mW6qT2xN9pJv",
  "object": "funnel_run",
  "appearance": {
    "accent_color": "#5149EF",
    "border_style": "rounded",
    "font_family": "inter",
    "theme": "light"
  },
  "card": {
    "brand": "visa",
    "last4": "4242"
  },
  "created_at": "2026-08-08T14:09:27+00:00",
  "expires_at": "2026-08-08T14:39:27+00:00",
  "livemode": true,
  "metadata": {},
  "next_url": null,
  "offer": {
    "accept_label": "Sim, quero o kit completo",
    "amount": 19990,
    "currency": "brl",
    "decline_label": "Não, obrigado",
    "installments": {
      "count": 12,
      "per_installment_amount": 1666
    },
    "name": "Kit completo",
    "step": "fstp_4mT8qW2vR7xK9pLc"
  },
  "payment_action": null,
  "status": "active"
}
```

Os botões continuam sendo a forma suportada de cobrar e recusar. `getState()`
serve para enfeitar a página em volta deles.

## Limites

| Limite                                     | Valor                   |
| ------------------------------------------ | ----------------------- |
| Etapas por funil                           | 50                      |
| Funis por payment link                     | 1                       |
| Payment links por funil                    | 1                       |
| Validade da chave de acesso                | 30 minutos              |
| Valor mínimo da oferta                     | R\$ 5,00                |
| Texto de cada botão                        | 60 caracteres           |
| Formas de pagamento que entram no funil    | Cartão de crédito e Pix |
| Formas de pagamento de uma oferta no modal | Cartão de crédito e Pix |

## Próximos passos

<CardGroup cols={2}>
  <Card title="Criar um Link de pagamento" icon="link" href="/payments/create-payment-link">
    O link que recebe a compra e arma o funil.
  </Card>

  <Card title="Chargefy.js" icon="code" href="/api/chargefy-js">
    Referência do script que renderiza os botões da oferta.
  </Card>

  <Card title="Produtos, preços e descontos" icon="cube" href="/products-prices-discounts/overview">
    Modele o catálogo que alimenta as ofertas das etapas.
  </Card>

  <Card title="Entrega de webhooks" icon="webhook" href="/integrate/webhooks/delivery">
    Reaja a cada upsell aprovado para liberar o produto.
  </Card>
</CardGroup>
