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

# Exigir aceptación de términos antes del checkout

> Un caso de uso del Cart SDK que agrega una casilla de términos y condiciones al Aftersell Cart y bloquea el checkout hasta que el comprador la acepta.

Agrega una casilla de verificación debajo del botón de checkout e impide que el comprador continúe hasta que la marque. Útil para aceptación de términos, verificaciones de edad y confirmaciones de productos hechos a pedido.

<Warning>
  **El evento `checkout` no puede cancelar el checkout.** Se dispara como una notificación justo antes de que el navegador navegue, así que devolver `false` o llamar a `preventDefault` no hace nada. La única forma de condicionar el checkout es impedir que el botón responda a los clics *antes* de que se presione, que es lo que muestra esta página.

  Trátalo como un elemento disuasorio de UI, no como una garantía legal. Un comprador decidido todavía puede llegar al checkout directamente.
</Warning>

<div id="how-it-works">
  ## Cómo funciona
</div>

Tres piezas:

1. Un **bloque de código personalizado** debajo del botón de checkout renderiza la casilla.
2. Mientras la casilla está sin marcar, el bloque agrega una clase a los botones de checkout y de pago exprés del carrito a través del [shadow root](/es/aftersell/cart/sdk-overview#shadowroot).
3. **CSS personalizado** hace que esa clase deshabilite los clics.

<div id="step-1-add-the-checkbox-block">
  ## Paso 1: Agrega el bloque de la casilla
</div>

Agrega un [bloque de código personalizado](/es/aftersell/cart/custom-code-blocks) debajo de tu bloque de botón de Checkout, cámbialo al modo **React component** y pega:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  const [accepted, setAccepted] = useState(false);

  useEffect(() => {
    const root = window.aftersell?.cart?.shadowRoot;
    if (!root) return;

    const targets = root.querySelectorAll(
      '.cart-external-checkout-button, .cart-external-express-buttons'
    );
    targets.forEach((el) => el.classList.toggle('checkout-gated', !accepted));
  }, [accepted, props.cart]);

  return (
    <div style={{ width: '100%', fontSize: '14px', textAlign: 'center' }}>
      <label style={{ display: 'flex', gap: '6px', justifyContent: 'center', alignItems: 'center' }}>
        <input
          type="checkbox"
          checked={accepted}
          onChange={(e) => setAccepted(e.target.checked)}
        />
        <span>
          I accept the{' '}
          <a href="https://yourstore.com/terms" target="_blank" rel="noopener noreferrer">
            Terms &amp; Conditions
          </a>
        </span>
      </label>
      {!accepted && (
        <div style={{ color: '#c00', fontWeight: 600, marginTop: '6px' }}>
          Please accept the terms above to continue.
        </div>
      )}
    </div>
  );
}
```

Haz clic en **Compile** y luego activa **"Use custom template"**. El bloque no renderiza nada hasta que lo hagas.

La dependencia `props.cart` importa: vuelve a aplicar la clase después de que el carrito se re-renderiza, lo que de otro modo la borraría.

<div id="step-2-add-the-css">
  ## Paso 2: Agrega el CSS
</div>

En **Cart settings → Custom CSS**:

```css theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
.checkout-gated {
  pointer-events: none !important;
  opacity: 0.5 !important;
}
```

`pointer-events: none` es lo que realmente bloquea el clic; la opacidad solo le muestra al comprador el porqué.

<div id="step-3-test-it">
  ## Paso 3: Pruébalo
</div>

En la [vista previa](/es/aftersell/cart/previewing-carts), confirma que:

* El botón de checkout está atenuado y no responde a los clics al cargar.
* Marcar la casilla lo habilita; desmarcarla vuelve a deshabilitar el botón.
* Los botones de pago exprés también están bloqueados.
* Agregar o quitar un artículo no vuelve a habilitar el botón mientras la casilla está sin marcar.

Este último punto es el fallo más común. Si el botón se vuelve a habilitar solo después de un cambio en el carrito, el efecto no se está volviendo a ejecutar. Verifica que `props.cart` esté en el arreglo de dependencias.

<div id="tracking-who-accepted">
  ## Registrar quién aceptó
</div>

La casilla es estado que solo existe en el navegador; nunca llega al pedido. Para registrar la aceptación, estámpala en cada línea como una propiedad en el momento de agregar al carrito:

```html theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
<input type="hidden" name="properties[_terms_version]" value="2026-01">
```

Agrégalo a tu formulario de producto en el tema. Shopify lee `properties[...]` directamente del formulario, así que el valor llega al pedido sin importar quién realice el agregado: Aftersell, el tema u otra app.

Una propiedad con el prefijo `_` no aparece en la línea visible para el comprador pero sí llega a Shopify, por lo que figura en el pedido. Esto registra *qué* versión de los términos estaba vigente, no que el comprador marcó la casilla.

<div id="things-to-get-right">
  ## Cosas que debes hacer bien
</div>

* **Apunta solo a las clases `cart-external-*`.** Las gemelas `cart-internal-*` son la plomería interna del carrito, no un asidero para tu código. Consulta [CSS personalizado](/es/aftersell/cart/custom-css).
* **Verifica que `shadowRoot` exista** antes de usarlo. Es `undefined` hasta que el carrito arranca.
* **El bloque no renderiza nada hasta que el carrito carga**, así que el botón de checkout nunca está brevemente activo antes de que se aplique el bloqueo.
* **Un bloque React que lanza un error no renderiza nada** y el resto del carrito sigue funcionando, lo que aquí significa un botón de checkout sin proteger. Prueba en la vista previa antes de publicar.

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

* **[Bloques de código personalizado](/es/aftersell/cart/custom-code-blocks)**: el modo React y sus props.
* **[CSS personalizado](/es/aftersell/cart/custom-css)**: la convención de clases públicas.
* **[Events](/es/aftersell/cart/sdk-events#checkout)**: lo que el evento `checkout` puede y no puede hacer.
