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

# Scripts personalizados

> Execute JavaScript personalizado no Aftersell Cart com os slots de script Initialization e On cart update.

Os scripts personalizados permitem executar seu próprio JavaScript no carrinho usando o [Cart SDK](/pt/aftersell/cart/sdk-overview). Adicione-os no Cart Editor em **Cart settings → Custom script**, onde um dropdown alterna entre dois slots: **Initialization** e **On cart update**.

Escreva JavaScript puro nesses editores, sem tags `<script>`. **On cart update** tem uma ação **Reset to default** que restaura seu template inicial; **Initialization** não tem, então guarde sua própria cópia antes de limpá-lo.

<Note>
  Muito do que os lojistas costumavam fazer por script agora é uma configuração nativa. Confira [Antes de escrever um script](/pt/aftersell/cart/sdk-use-cases#before-you-write-a-script) primeiro: uma configuração continua funcionando através de redesigns do carrinho, e seu script pode não continuar.
</Note>

<div id="which-slot-to-use">
  ## Qual slot usar
</div>

|                  | Initialization                                                                                                                                                                           | On cart update                                                           |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| **Executa**      | Uma vez, quando o carrinho carrega.                                                                                                                                                      | A cada alteração do carrinho após o primeiro carregamento.               |
| **Você escreve** | O script inteiro.                                                                                                                                                                        | Apenas o corpo do handler. O wrapper `cart_updated` é travado.           |
| **Use para**     | Registrar comportamento uma única vez: [`configure`](/pt/aftersell/cart/sdk-configure), [`events.on`](/pt/aftersell/cart/sdk-events), [`hooks.register*`](/pt/aftersell/cart/sdk-hooks). | Regras que precisam ser reavaliadas contra o conteúdo atual do carrinho. |
| **Exemplo**      | Ocultar linhas de brinde grátis com um line transform.                                                                                                                                   | Manter um brinde grátis sincronizado com um limite de gasto.             |

<div id="initialization">
  ## Initialization
</div>

O script **Initialization** executa **uma vez quando o carrinho carrega**. É o seu ponto de entrada para preparar tudo: configurar o comportamento do carrinho, assinar eventos e registrar hooks. O [SDK](/pt/aftersell/cart/sdk-overview) está disponível como `window.aftersell.cart`.

Chamadas de configuração que você faz aqui ([`configure(...)`](/pt/aftersell/cart/sdk-configure), [`events.on(...)`](/pt/aftersell/cart/sdk-events), [`hooks.*`](/pt/aftersell/cart/sdk-hooks)) são seguras de chamar no topo do script mesmo antes de o carrinho ter inicializado completamente; elas são armazenadas em buffer e aplicadas quando ele inicializa. Ações que leem ou alteram o carrinho (como [`addItem`](/pt/aftersell/cart/sdk-actions#additemvariantid-quantity) ou [`getCart`](/pt/aftersell/cart/sdk-actions#getcart)) devem rodar dentro de [`ready()`](/pt/aftersell/cart/sdk-overview#ready) ou de um handler de evento.

O slot começa com três exemplos **comentados** — abrir o drawer a cada adição, reagir a `cart_loaded` e ocultar linhas de brinde grátis — então um script Initialization intocado não faz nada. Descomente um para testar, ou substitua-os.

O formato natural para este slot é um **registro único sem eventos envolvidos**: registre o comportamento uma vez e deixe o carrinho aplicá-lo dali em diante. Ocultar linhas de brinde grátis do drawer, sem alterar o total, é o exemplo fornecido disso:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerLineTransform((line) => {
  if (line.finalLinePrice === 0) line.setHidden(true);
});
```

[`registerLineTransform`](/pt/aftersell/cart/sdk-hooks#registerlinetransform) executa para cada linha conforme ela é renderizada, e `setHidden` é apenas de exibição, então a linha permanece no carrinho e ainda conta para o total, ela só não aparece no drawer. Veja [Ocultar e rotular linhas do carrinho](/pt/aftersell/cart/sdk-use-case-hide-lines) para mais do que um transform pode fazer.

Ações que leem o carrinho vão dentro de `ready()`:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.ready().then(() => {
  const state = window.aftersell.cart.actions.getCart();
  console.log('Cart loaded with', state.itemCount, 'items');
});
```

Acessar o DOM do carrinho exige a mesma espera, e exige [`shadowRoot`](/pt/aftersell/cart/sdk-overview#shadowroot): o carrinho é renderizado dentro de um shadow root, então `document.querySelector` não consegue ver nada no drawer.

<Tip>
  Vai ramificar por mercado, país ou moeda **antes** de o carrinho carregar? Leia [`context`](/pt/aftersell/cart/sdk-overview#context) em vez disso. Ele está disponível de forma síncrona, sem precisar de `ready()`, então você pode nem registrar handlers para compradores aos quais uma regra não se aplica.
</Tip>

<div id="on-cart-update">
  ## On cart update
</div>

O script **On cart update** executa toda vez que o carrinho muda. É um wrapper travado em torno de uma assinatura de `cart_updated`, então você edita apenas o corpo, e seu código recebe o `cart` atualizado.

Este slot é para regras que precisam ser **reavaliadas a cada mudança do carrinho**. Um limite de brinde grátis é o caso clássico (gaste \$75, ganhe uma sacola grátis), porque a resposta depende do conteúdo atual e nada mais consegue avisar quando ele muda:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.events.on('cart_updated', (cart) => {
  const GIFT_VARIANT_ID = 1234567890;
  const THRESHOLD = 7500;   // $75.00, in cents

  let giftLine = null;
  let subtotal = 0;
  (cart.items ?? []).forEach((line) => {
    if (line.variantId === GIFT_VARIANT_ID) giftLine = line;
    else subtotal += line.finalLinePrice;   // the gift itself never counts toward the threshold
  });

  const shouldHaveGift = subtotal >= THRESHOLD;
  const hasGift = Boolean(giftLine);

  // Bail when the cart already matches. This is the part that matters: adding or
  // removing an item fires cart_updated again, so without this check the handler
  // re-enters itself forever.
  if (shouldHaveGift === hasGift) return;

  if (shouldHaveGift) window.aftersell.cart.actions.addItem(GIFT_VARIANT_ID, 1);
  else window.aftersell.cart.actions.removeItem(giftLine.key);
});
```

<div id="keeping-the-cart-in-a-desired-state">
  ### Mantendo o carrinho em um estado desejado
</div>

A linha `if (shouldHaveGift === hasGift) return;` é o que torna isso seguro, e ela se generaliza para todo script que mantém o carrinho em um estado desejado. Este slot tanto reage a mudanças do carrinho quanto as causa, então cada `addItem` ou `removeItem` o reexecuta. Descreva o estado que você quer, compare com o estado que você tem e retorne cedo quando eles já concordam, para que o handler convirja depois de uma passada em vez de entrar em loop. Veja [as duas regras](/pt/aftersell/cart/sdk-events#the-two-rules) para a versão sem proteção a evitar e por que o payload é somente leitura.

Em uma loja mais lenta, também vale manter uma flag de operação em andamento no nível do módulo, para que duas mudanças rápidas não possam ambas iniciar uma adição antes de a primeira ser concluída.

<Note>
  `cart_updated` dispara apenas em mudanças **depois** do primeiro carregamento ([timing de eventos](/pt/aftersell/cart/sdk-events#cart_updated)), então um script neste slot não vai reconciliar um carrinho que já se qualifica quando a página carrega. Para uma versão que trata os dois casos, assine `cart_loaded` e `cart_updated` com a mesma função a partir do slot **Initialization**. Veja [Adicionar automaticamente um brinde grátis em um limite](/pt/aftersell/cart/sdk-use-case-free-gift).
</Note>

<div id="when-a-script-breaks">
  ## Quando um script quebra
</div>

Cada slot roda no seu próprio sandbox, então um script **Initialization** quebrado não impede o **On cart update** de rodar, e nenhum dos dois pode quebrar o carrinho em si.

Dentro de um slot, porém, a execução **para no primeiro erro**. Tudo abaixo daquela linha é pulado, o que significa que qualquer `configure`, `events.on` ou `hooks.register*` mais abaixo nunca é registrado. Essa é a explicação usual para "meu handler nunca dispara" quando o código parece correto.

O carrinho indica a linha com falha no console do navegador, e cada slot roda sob seu próprio nome de arquivo (`aftersell-cart-init.js` e `aftersell-cart-cart-update.js`), então você pode abrir qualquer um pelo painel Sources do DevTools e definir breakpoints. Veja [Depuração](/pt/aftersell/cart/sdk-overview#debugging) para as mensagens exatas e para o canal de debug que captura falhas de hooks mantidas fora do console.

Como `cart_loaded` [é reproduzido para assinantes tardios](/pt/aftersell/cart/sdk-events#cart_loaded), a ordem de registro nunca importa. A estrutura mais segura é registrar tudo primeiro e fazer o trabalho arriscado dentro dos handlers, onde um throw fica isolado naquele handler.

<div id="where-to-go-next">
  ## Por onde continuar
</div>

* **[Cart SDK](/pt/aftersell/cart/sdk-overview)**: os scripts personalizados são a forma de executar código do SDK. Veja as referências de [configure](/pt/aftersell/cart/sdk-configure), [eventos](/pt/aftersell/cart/sdk-events), [ações](/pt/aftersell/cart/sdk-actions) e [hooks](/pt/aftersell/cart/sdk-hooks) para a superfície completa, o [objeto de carrinho](/pt/aftersell/cart/sdk-cart-object) para a estrutura do que os handlers recebem, e os [casos de uso](/pt/aftersell/cart/sdk-use-cases) para snippets prontos.
* **[Blocos Custom code](/pt/aftersell/cart/custom-code-blocks)**: para adicionar marcação ao carrinho. Note que o modo HTML do bloco Custom code **não** executa JavaScript; use scripts personalizados (ou o modo React do bloco) para lógica.
