> ## 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.

# Visión general

> Cómo funciona el Cart SDK de Aftersell: el punto de entrada global, las cuatro partes de la API, cuándo se carga y cómo ejecutar código contra él de forma segura.

El **Cart SDK** es una API de JavaScript para el Aftersell Cart en tu tienda. Te permite cambiar cómo se comporta el carrito, reaccionar a lo que hacen los compradores y leer o cambiar el contenido del carrito desde código.

Ejecutas código del SDK mediante [Scripts personalizados](/es/aftersell/cart/custom-scripts), o mediante el modo React de un [bloque Custom code](/es/aftersell/cart/custom-code-blocks) para un bloque que renderiza su propia UI.

<Note>
  Mucho de lo que los comerciantes le piden al SDK ya es una configuración. Antes de escribir un script, verifica si un [bloque del carrito](/es/aftersell/cart/blocks-overview), las [condiciones por mercado/país/moneda](/es/aftersell/cart/blocks-overview#show-or-hide-by-market-country-or-currency) o una [configuración del carrito](/es/aftersell/cart/cart-settings) ya lo hacen. Esos siguen funcionando a través de rediseños del carrito, y tu script puede que no.
</Note>

<div id="the-global-entry-point">
  ## El punto de entrada global
</div>

Todo cuelga de un solo global:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart
```

<Note>
  **Todos los snippets de estos docs escriben `window.aftersell.cart` completo**, así que cualquiera de ellos funciona por sí solo cuando lo pegas. Crear un alias una vez (`const cart = window.aftersell.cart;`) y usar `cart` a partir de entonces también es perfectamente válido, y seguro incluso antes de que el carrito se cargue. Solo recuerda incluir esa línea si acortas un snippet, ya que un `cart` suelto por sí solo lanza `cart is not defined`.
</Note>

Cuatro partes hacen el trabajo:

<Columns cols={2}>
  <Card title="Configure" icon="sliders" href="/es/aftersell/cart/sdk-configure">
    Establece cómo se comporta el carrito: cuándo se abre el drawer, cómo se formatea el dinero, si Aftersell intercepta el agregar al carrito.
  </Card>

  <Card title="Events" icon="tower-broadcast" href="/es/aftersell/cart/sdk-events">
    Reacciona a lo que sucede: el carrito se cargó, se agregó un artículo, el drawer se abrió, se hizo clic en el checkout.
  </Card>

  <Card title="Actions" icon="wand-magic-sparkles" href="/es/aftersell/cart/sdk-actions">
    Lee y cambia el carrito: ábrelo, agrega un artículo, actualiza una cantidad, lee el estado actual.
  </Card>

  <Card title="Hooks" icon="plug" href="/es/aftersell/cart/sdk-hooks">
    Cambia cómo funciona el carrito en sí: oculta o reetiqueta líneas, reordénalas, adjunta datos extra, controla el agregar al carrito.
  </Card>
</Columns>

<Note>
  Si un script tuyo dejó de dispararse al agregar al carrito, empieza por [Intercepción de agregar al carrito](/es/aftersell/cart/add-to-cart-interception). Explica por qué Aftersell toma el control del agregado, y todas las formas de excluir un formulario.
</Note>

Más tres miembros menores:

| Miembro      | Para qué sirve                                                                    |
| ------------ | --------------------------------------------------------------------------------- |
| `ready()`    | Una Promise que se resuelve una vez que el carrito se ha cargado por primera vez. |
| `context`    | Contexto del comprador renderizado por el servidor, legible de forma síncrona.    |
| `shadowRoot` | El shadow root del carrito, para consultar elementos dentro del drawer.           |

<div id="events-actions-or-hooks">
  ## ¿Eventos, acciones o hooks?
</div>

Los tres son fáciles de confundir, y elegir el equivocado es la razón más común por la que un script no hace lo que su autor esperaba:

| Quieres…                                          | Usa        | Ejemplo                                                      |
| ------------------------------------------------- | ---------- | ------------------------------------------------------------ |
| Ejecutar código *cuando algo sucede*              | **Evento** | Enviar un evento de analíticas cuando se agrega un artículo. |
| *Cambiar lo que hay en* el carrito                | **Acción** | Agregar un regalo gratis una vez que el total supera \$50.   |
| Cambiar *cómo funciona o se renderiza el carrito* | **Hook**   | Ocultar las líneas de regalo gratis del drawer.              |

La distinción que más importa: una **acción cambia el carrito real del comprador** (y su total), mientras que un **hook solo cambia lo que se renderiza**. Ocultar una línea con un hook la deja en el carrito y en el total; eliminarla con una acción la saca de verdad.

<div id="how-and-when-it-loads">
  ## Cómo y cuándo se carga
</div>

El carrito se carga en dos etapas, y el SDK está construido para que no tengas que pensar en el orden:

1. Un pequeño **stub** crea `window.aftersell.cart` inmediatamente, así que siempre está ahí.
2. El SDK completo se carga poco después y toma el control, actualizando el stub en su lugar, así que una referencia que capturaste antes sigue funcionando.

Eso te da dos categorías de llamada:

<Columns cols={2}>
  <Card title="Llamadas de configuración: seguras de inmediato" icon="circle-check">
    `configure(...)`, `events.on(...)` y cada llamada `hooks.register*`. Se almacenan en búfer antes del arranque y se reproducen en orden una vez que el SDK se carga. Ponlas al principio de tu script.
  </Card>

  <Card title="Acciones: espera a ready()" icon="clock">
    Todo lo que está bajo `actions.*`. Ejecútalas dentro de `ready()` o de un handler de eventos. Llamadas demasiado pronto, advierten en la consola y no hacen nada, de forma segura: las asíncronas aún se resuelven, así que una cadena `.then()` no se romperá.
  </Card>
</Columns>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Set-up: fine at the top level, before the cart has loaded.
window.aftersell.cart.configure({ open_on_add_to_cart: 'always' });

window.aftersell.cart.events.on('item_added', (payload) => {
  console.log('Added', payload.item.title);
});

// Actions: wait until the cart is ready.
window.aftersell.cart.ready().then(() => {
  const state = window.aftersell.cart.actions.getCart();
  console.log(state.itemCount, 'items');
});
```

<div id="ready">
  ### ready()
</div>

`ready()` devuelve una Promise que se resuelve una vez que la primera carga del carrito **se asienta**. Se resuelve tanto en fallo como en éxito, así que un comprador con una conexión inestable nunca deja tu script colgado. Verifica si `getCart()` es `null` en lugar de asumir que llegó un carrito.

Llamar a `ready()` después de que el carrito ya se cargó se resuelve inmediatamente, así que es seguro usarla como una compuerta general de "el carrito ya existe" en cualquier parte de tu código.

<Tip>
  No necesitas `ready()` dentro de un handler de eventos. Para cuando `cart_loaded`, `cart_updated` o `item_added` se dispara, el carrito está cargado y es seguro llamar a las acciones.
</Tip>

<div id="context">
  ## context
</div>

`window.aftersell.cart.context` contiene datos del comprador renderizados por el servidor, legibles de forma síncrona, sin necesidad de `ready()`. Úsalo para ramificaciones por mercado o país que deben ocurrir antes de que el carrito se cargue.

| Campo                     | Descripción                                                                            | Disponible antes del arranque               |
| ------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------- |
| `shopify_market`          | El mercado de Shopify del comprador.                                                   | Sí                                          |
| `customer_country`        | Código de país de dos letras.                                                          | Sí                                          |
| `customer_currency`       | Código de moneda activo.                                                               | Sí                                          |
| `money_format`            | El formato de dinero de Shopify de la tienda.                                          | Sí                                          |
| `backend_url`             | Host directo del backend, usado como respaldo cuando el app proxy no está configurado. | Sí                                          |
| `storefront_access_token` | Token para llamadas a la Storefront API.                                               | **No**: se agrega cuando el carrito arranca |

<Warning>
  `storefront_access_token` es el único campo de `context` que el servidor no renderiza en `cart.context`. Se agrega a `context` cuando el carrito arranca, así que leerlo al principio de tu script devuelve `undefined`. Espera primero a `window.aftersell.cart.ready()`.
</Warning>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
if (window.aftersell.cart.context.customer_country === 'CA') {
  // Canada-only behavior, decided before the cart loads.
}
```

<Note>
  Para mostrar configuraciones de bloque diferentes por mercado, país o moneda, usa las [condiciones en el editor del carrito](/es/aftersell/cart/blocks-overview#show-or-hide-by-market-country-or-currency) en su lugar. No se requiere script. La UI completa de Conditions está disponible hoy en [Rewards](/es/aftersell/cart/rewards-block#per-market-rewards).
</Note>

<div id="shadowroot">
  ## shadowRoot
</div>

El carrito se renderiza dentro de un shadow root, así que `document.querySelector` **no puede ver nada dentro del drawer**. Para alcanzar un elemento en el carrito, consulta el shadow root:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const root = window.aftersell.cart.shadowRoot;
const button = root?.querySelector('.cart-external-checkout-button');
```

Apunta a las mismas **clases públicas `cart-external-*`** que usa [Custom CSS](/es/aftersell/cart/custom-css). Esos son los asideros soportados. Las gemelas `cart-internal-*` son la fontanería propia del carrito, así que consulta las externas en su lugar.

<Warning>
  Recurre al shadow root solo cuando ningún bloque, configuración o hook haga el trabajo. Un hook sobrevive a un rediseño del carrito; una consulta al DOM es un problema de mantenimiento de tu código.
</Warning>

El shadow root solo está presente una vez que el carrito ha arrancado, así que léelo dentro de `ready()` o de un handler de eventos en lugar de al principio de tu script.

<div id="debugging">
  ## Depuración
</div>

Un script roto nunca debe tumbar el agregar al carrito ni el drawer, así que el SDK contiene los fallos en lugar de dejar que se propaguen. Dónde aflora un fallo depende de qué se rompió:

| Qué falló                                                                                  | Dónde aparece                                                 |
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------- |
| Tu script lanzó una excepción en el nivel superior                                         | `console.error`, nombrando la línea y lo que nunca se ejecutó |
| Un handler de [eventos](/es/aftersell/cart/sdk-events) lanzó una excepción                 | `console.error`; los demás handlers siguen ejecutándose       |
| Un [hook](/es/aftersell/cart/sdk-hooks) lanzó una excepción                                | Silencioso. Va al canal de depuración de abajo                |
| Una [acción](/es/aftersell/cart/sdk-actions) se ejecutó antes de que el carrito se cargara | `console.warn`; la llamada no hace nada                       |

<div id="when-your-script-throws">
  ### Cuando tu script lanza una excepción
</div>

Un script personalizado **se detiene en el primer error**, así que cada `configure`, `events.on` y `hooks.register*` debajo de esa línea nunca se ejecuta. El carrito lo dice explícitamente:

```
[aftersell-cart] Initialization script error on line 12 — 4 more line(s) did not run;
any configure/events/hooks below are unregistered.
```

Ese es el mensaje que debes buscar cuando un handler que definitivamente registraste nunca se dispara: probablemente nunca se alcanzó. El número de línea es la instrucción de nivel superior donde la ejecución se detuvo, no la función interna que lanzó la excepción, y se omite en lugar de adivinarse si el stack del navegador no es utilizable.

Tus scripts también se ejecutan bajo sus propios nombres de archivo, así que aparecen como `aftersell-cart-init.js` y `aftersell-cart-cart-update.js` en DevTools. Puedes abrirlos desde el panel Sources y establecer breakpoints como en cualquier otro archivo.

<div id="the-debug-channel">
  ### El canal de depuración
</div>

Los fallos de hooks se mantienen deliberadamente fuera de la consola para que los compradores nunca los vean. En su lugar van aquí:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// After reproducing the problem, inspect what was swallowed:
window.aftersellCartDebugEvents.filter((entry) => entry.level === 'ERROR');

// Or watch them live:
window.addEventListener('aftersell-cart-debug', (event) => console.log(event.detail));
```

<div id="where-to-go-next">
  ## Adónde ir después
</div>

<Columns cols={2}>
  <Card title="Configure" icon="sliders" href="/es/aftersell/cart/sdk-configure">
    Cada opción, con un ejemplo cada una.
  </Card>

  <Card title="Events" icon="tower-broadcast" href="/es/aftersell/cart/sdk-events">
    Cada evento, cuándo se dispara y qué no hacer en un handler.
  </Card>

  <Card title="Actions" icon="wand-magic-sparkles" href="/es/aftersell/cart/sdk-actions">
    Cada acción, con un snippet cada una.
  </Card>

  <Card title="Hooks" icon="plug" href="/es/aftersell/cart/sdk-hooks">
    Cada hook, y cómo se componen los registros.
  </Card>

  <Card title="Objeto cart" icon="table-list" href="/es/aftersell/cart/sdk-cart-object">
    La forma del carrito y sus líneas.
  </Card>

  <Card title="Casos de uso" icon="book-open" href="/es/aftersell/cart/sdk-use-cases">
    Soluciones completas y ejecutables a solicitudes comunes.
  </Card>
</Columns>
