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

# Bloques de código personalizado

> El bloque Custom code de Aftersell Cart: agrega tu propio HTML o React en cualquier parte del cajón, incluso dentro de Cart items.

> El bloque **Custom code** agrega tu propio HTML o React al carrito. Colócalo en cualquier sección del cajón, o anídalo dentro de [**Cart items**](/es/aftersell/cart/cart-items-block) como sub-bloque para que se repita en cada línea. A diferencia de otros bloques, no tiene configuraciones de Content ni sección de Design: el bloque *es* el código, así que trabajas completamente en su pestaña **Code**.

<Frame>
  <img src="https://mintcdn.com/aftersell/1Y3gBpUfxv16VGSW/images/aftersell/cart-custom-code-block-add-and-enable.gif?s=6717cc64a8765b0c06b65990f99e12ff" alt="Vista previa animada de agregar y activar un bloque Custom code en el editor de Aftersell Cart" title="Vista previa animada de agregar y activar un bloque Custom code en el editor de Aftersell Cart" width="1200" height="558" data-path="images/aftersell/cart-custom-code-block-add-and-enable.gif" />
</Frame>

<div id="add-and-turn-on-a-custom-code-block">
  ## Agregar y activar un bloque Custom code
</div>

1. Agrega un bloque **Custom code** a cualquier sección, o como sub-bloque bajo **Cart items**.
2. Selecciónalo y abre la pestaña **Code**.
3. Elige **HTML** o **React component**. Los bloques nuevos usan HTML de forma predeterminada.
4. Escribe tu código.
5. Si elegiste React, haz clic en <span style={{display:'inline-flex',alignItems:'center',gap:'4px',background:'#1C1C1C',color:'#fff',border:'1px solid #0A0A0A',borderRadius:'4px',padding:'0 6px',fontSize:'0.85em',fontWeight:500,lineHeight:'1.4em',verticalAlign:'middle'}}><svg width="8" height="9" viewBox="0 0 10 12" fill="none" aria-hidden="true" style={{display:'block'}}><path d="M1.5 1.2v9.6L8.8 6 1.5 1.2Z" stroke="#fff" strokeWidth="1.5" strokeLinejoin="round" /></svg>Compile</span>.
6. Activa **"Use custom template"**. Para este bloque, ese interruptor significa "mostrar mi código personalizado", y viene desactivado de forma predeterminada, por lo que nada se renderiza hasta que lo habilites.
7. Mantén activado el conmutador del ojo de la barra lateral para que el bloque siga siendo visible para los compradores.

Tanto el conmutador del ojo como **"Use custom template"** deben estar activados para que el bloque aparezca.

<div id="behavior">
  ## Comportamiento
</div>

* El bloque no renderiza nada hasta que el carrito se ha cargado.
* Tampoco renderiza nada cuando el ojo de la barra lateral está desactivado, **"Use custom template"** está desactivado, el código está vacío o React falla al compilar o renderizar. Como una falla es silenciosa, revisa tu bloque en la [vista previa](/es/aftersell/cart/previewing-carts) antes de publicar.

<div id="html-mode">
  ## Modo HTML
</div>

El modo HTML sustituye un pequeño conjunto de tokens en tu marcado. Es para contenido estático o basado en tokens, no para ejecutar lógica.

* **Las etiquetas `<script>` en línea no se ejecutan**, y el modo HTML **no tiene acceso al SDK ni a `window`.**
* Para lógica, usa el [**modo React**](#react-mode) o los [scripts personalizados](/es/aftersell/cart/custom-scripts) con el [Cart SDK](/es/aftersell/cart/sdk-overview).

<div id="tokens">
  ### Tokens
</div>

Los valores de los tokens son **cadenas formateadas** (formato de moneda de la tienda, un porcentaje con `%` o una cantidad), listas para insertarse en el marcado:

| Token                    | Qué muestra                                                                   |
| ------------------------ | ----------------------------------------------------------------------------- |
| `{{pre_cart_total}}`     | Total del carrito antes de los descuentos.                                    |
| `{{post_cart_total}}`    | Total del carrito después de los descuentos.                                  |
| `{{savings_amount}}`     | Monto ahorrado (total antes del descuento menos total después del descuento). |
| `{{savings_percentage}}` | Ahorro como porcentaje, incluido el signo `%` (por ejemplo `15%`).            |
| `{{cart_quantity}}`      | Número de artículos visibles en el carrito.                                   |

<div id="example">
  ### Ejemplo
</div>

```html theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
<div class="cart-external-custom-code_html">
  You saved {{savings_amount}} ({{savings_percentage}})
</div>
```

<div id="react-mode">
  ## Modo React
</div>

El modo React compila un componente y le pasa los datos del carrito más una acción de `add-to-cart`.

* El editor bloquea el envoltorio en `function CustomCode(props: CustomCodeProps) { … }`, y tú editas solo el cuerpo entre esas líneas.
* Debes hacer clic en <span style={{display:'inline-flex',alignItems:'center',gap:'4px',background:'#1C1C1C',color:'#fff',border:'1px solid #0A0A0A',borderRadius:'4px',padding:'0 6px',fontSize:'0.85em',fontWeight:500,lineHeight:'1.4em',verticalAlign:'middle'}}><svg width="8" height="9" viewBox="0 0 10 12" fill="none" aria-hidden="true" style={{display:'block'}}><path d="M1.5 1.2v9.6L8.8 6 1.5 1.2Z" stroke="#fff" strokeWidth="1.5" strokeLinejoin="round" /></svg>Compile</span> y luego activar **"Use custom template"**, antes de que el bloque se muestre.
* Tu componente puede usar `useState`, `useEffect`, `useMemo`, `useRef` y `useCallback`.
* A diferencia del modo HTML, React se ejecuta en el contexto de la página, por lo que puede llamar a `window` y al [Cart SDK](/es/aftersell/cart/sdk-overview) cuando están disponibles.
* Si tu componente lanza errores en tiempo de ejecución, el bloque no renderiza nada y el resto del carrito sigue funcionando.

<div id="props">
  ### Props
</div>

Los totales y los montos de ahorro son enteros en la [unidad menor](/es/aftersell/cart/sdk-actions#formatmoneycents) de la moneda (centavos para USD), por lo que `$12.50` es `1250`, no `12.50`. No son cadenas de dinero formateadas como los tokens de HTML.

| Prop                                            | Tipo                        | Descripción                                                                                                                                         |
| ----------------------------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cart`                                          | `AftersellCart`             | El carrito actual. Consulta la [referencia del objeto de carrito](/es/aftersell/cart/sdk-cart-object).                                              |
| `line`                                          | `AftersellCartLine \| null` | Solo se establece cuando el bloque es un sub-bloque de Cart items (un renderizado por línea); `null` en una sección.                                |
| `preCartTotal`                                  | `number`                    | El total del carrito **antes de los descuentos** (`original_total_price` de Shopify), en la unidad menor de la moneda (p. ej., centavos).           |
| `postCartTotal`                                 | `number`                    | El total del carrito **después de los descuentos**, en la unidad menor de la moneda.                                                                |
| `savings`                                       | `{ amount, percentage }`    | Monto y porcentaje de ahorro.                                                                                                                       |
| `addProduct(variantId, quantity?, properties?)` | `function`                  | Agrega un producto al carrito, marcado con la atribución de este bloque para que las [analíticas](/es/aftersell/cart/analytics) puedan acreditarlo. |

<div id="the-cart-and-line-shapes">
  ### Las estructuras de cart y line
</div>

`cart` y `line` son los mismos objetos que el SDK expone en todas partes, por lo que están documentados una sola vez en la **[referencia del objeto de carrito](/es/aftersell/cart/sdk-cart-object)**: cada campo del carrito, de una línea y de un bundle.

Los que más usarás: `cart.items`, `cart.itemCount`, `cart.totalPrice`, `line.title`, `line.quantity`, `line.finalLinePrice`.

Tres cosas específicas de este bloque:

* **`line` solo se establece en un sub-bloque de Cart items**, donde tu componente se renderiza una vez por línea. Colocado como sección, `line` es `null` y en su lugar lees `cart.items`.
* **Los componentes de un bundle no están en `cart.items`.** Cuando las líneas están [agrupadas en un bundle](/es/aftersell/cart/sdk-use-case-bundles), solo aparece la línea ancla; sus componentes viven en `line.bundle.children`.
* **Las líneas ocultas por una [transformación de línea](/es/aftersell/cart/sdk-hooks#registerlinetransform) tampoco están ahí**, aunque siguen contando para `cart.totalPrice`.

<div id="examples">
  ### Ejemplos
</div>

Mostrar el recuento de artículos:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  return (
    <div className="cart-external-custom-code_jsx">
      {props.cart.itemCount} items
    </div>
  );
}
```

Como sub-bloque de Cart items, usa `props.line` para contenido por producto. El bloque se renderiza una vez por línea, etiquetado con el producto y la variante de esa línea:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  if (!props.line) return null;
  return (
    <div className="cart-external-custom-code_jsx">
      {props.line.productTitle}
      {props.line.variantTitle ? ` · ${props.line.variantTitle}` : ''}
    </div>
  );
}
```

<div id="reading-enrichment-metadata">
  ### Leer los metadatos de enriquecimiento
</div>

Cada artículo de `cart.items` lleva un campo `metadata`: un objeto vacío `{}` hasta que un [enriquecedor de carrito](/es/aftersell/cart/sdk-hooks#registercartenricher) lo rellena. Una vez rellenado, está indexado por el `id` del enriquecedor y contiene los datos de Storefront del producto o la variante de esa línea:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  return (
    <ul>
      {(props.cart.items ?? []).map((item) => {
        const note = item.metadata?.shipping?.shippingNote;
        return (
          <li key={item.key}>
            {item.title}
            {note ? ` · ${note.value}` : ''}
          </li>
        );
      })}
    </ul>
  );
}
```

`metadata` siempre está presente y su valor predeterminado es un objeto vacío `{}` hasta que se completa la búsqueda asíncrona del enriquecedor (la prueba de "aún no enriquecido" es `Object.keys(item.metadata).length === 0`). Usa encadenamiento opcional (`item.metadata?.enricherId`) al leer la clave de un enriquecedor específico, ya que esa clave está ausente hasta que el enriquecimiento llega.

<div id="reading-discount-codes-and-line-discounts">
  ### Leer los códigos de descuento y los descuentos por línea
</div>

`cart.discountCodes` enumera los códigos de descuento aplicados al carrito, y `discountAllocations` de cada línea enumera los descuentos aplicados a esa línea específica:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  const codes = props.cart.discountCodes;
  return (
    <div>
      {codes.length > 0 && (
        <p>Active discounts: {codes.join(', ')}</p>
      )}
      <ul>
        {(props.cart.items ?? []).map((item) => {
          return (
            <li key={item.key}>
              {item.title}
              {item.discountAllocations.map(
                (discount) => ` · ${discount.title} (-${(discount.amount / 100).toFixed(2)})`
              )}
            </li>
          );
        })}
      </ul>
    </div>
  );
}
```

<div id="placement-and-limits">
  ## Ubicación y límites
</div>

* **Región:** cualquiera (superior, cuerpo o inferior). También disponible como sub-bloque de Cart items.
* **Máximo:** ilimitado.
* **Estado:** carrito lleno y vacío (como bloque de sección). Como sub-bloque de Cart items, solo se renderiza cuando el carrito tiene líneas, una instancia por línea.
* No está bloqueado, así que puedes eliminarlo u ocultarlo.
* No hay sección de Design por bloque. Dale estilo a través de tu propio marcado, el [**CSS personalizado**](/es/aftersell/cart/custom-css) y tus [**configuraciones de diseño**](/es/aftersell/cart/design-settings) globales.

<div id="when-to-use-custom-code-block-vs-custom-template-vs-custom-script">
  ## Cuándo usar el bloque de código personalizado vs. la plantilla personalizada vs. el script personalizado
</div>

|                                                                    | Qué hace                                                                                       | Cuándo usarlo                                                                              | Ejemplo                                                                                                                                                                               |
| ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Bloque de código personalizado**                                 | Agrega un bloque *nuevo* con tu propio HTML o React.                                           | Algo que los bloques integrados no cubren.                                                 | Una línea de total estimado que suma tu tarifa fija de envío al total del carrito, o una cuenta regresiva de fecha límite de entrega encima del botón de checkout.                    |
| **[Plantilla personalizada](/es/aftersell/cart/custom-templates)** | Reemplaza el renderizado de un bloque *existente* con tu JSX, usando los datos de ese bloque.  | El bloque integrado está casi bien, pero necesitas un marcado diferente.                   | Reconstruir la [fila Product](/es/aftersell/cart/cart-items-block#custom-template) para que el nombre de la variante, los ahorros y el selector de cantidad queden en una sola línea. |
| **[Script personalizado](/es/aftersell/cart/custom-scripts)**      | Ejecuta JavaScript contra el carrito a través del [Cart SDK](/es/aftersell/cart/sdk-overview). | Lógica, eventos y configuración a nivel de todo el carrito, en lugar de marcado del cajón. | Gasta \$75 y llévate un tote gratis: [agrega el regalo](/es/aftersell/cart/sdk-use-case-free-gift) cuando el carrito cruce el umbral, y quítalo si el comprador baja del mismo.       |
