Skip to main content
Una plantilla personalizada te permite anular cómo se renderiza un bloque individual. En lugar de la UI integrada del bloque, el carrito renderiza tu propio JSX, usando los mismos datos que el bloque usaría normalmente. Es una capacidad transversal más que un bloque en sí: la mayoría de los bloques la exponen desde su pestaña Code. Esta página cubre lo que aplica a todos los bloques. Para las props que un bloque específico te entrega, ve a la referencia del propio bloque.

Plantilla personalizada vs. bloque Custom code

Suenan parecido pero hacen cosas diferentes:
  • Una plantilla personalizada reemplaza el renderizado de un bloque existente con tu propio marcado, y te entrega los datos propios de ese bloque (el título y el conteo de artículos del Header, los totales del Summary, etcétera). No agrega nada nuevo; rediseña un bloque.
  • El bloque Custom code agrega un bloque nuevo de HTML o React arbitrario en cualquier parte del carrito.
Recurre a una plantilla personalizada cuando el bloque integrado está casi bien pero necesitas un layout o marcado diferente. Recurre a un bloque Custom code cuando quieras agregar algo que los bloques integrados no cubren.

Usar una plantilla personalizada

  1. Selecciona un bloque en el editor y abre su pestaña Code.
  2. Edita la plantilla predeterminada. Las plantillas personalizadas son solo JSX (la elección entre HTML o JSX es exclusiva del bloque Custom code).
  3. Haz clic en Compile. Compilar elimina los tipos y transpila el JSX, así que detecta errores de sintaxis. Los errores de tipos no detienen la compilación: el editor los marca inline mientras escribes, con el mismo IntelliSense que autocompleta las props del bloque.
  4. Activa la plantilla para que el carrito la use en lugar del renderizado integrado.
  5. Reset to default restaura la plantilla original del bloque en cualquier momento.

Escribir una plantilla con IA

La pestaña Code incluye un botón Copy AI prompt (icono de varita ✦). Al hacer clic, copia a tu portapapeles un brief autónomo que puedes pegar directamente en una sesión de chat con IA (Claude, ChatGPT o similar). El prompt incluye todo lo que la IA necesita para escribir una plantilla válida para ese bloque específico:
  • Las reglas de compilación (expresión única, sin export default, sin imports)
  • Las props exactas que recibe el bloque, coincidiendo con lo que muestra el IntelliSense del editor
  • La firma de función bloqueada que el editor impone
  • Reglas específicas del bloque (formatos de dinero, qué handlers conectar, requisitos de accesibilidad)
  • Una sección para completar donde pegas tu plantilla actual y describes el cambio que quieres
Después de copiar, abre una sesión de IA, pega el prompt, completa los dos espacios en blanco al final (tu plantilla actual y el cambio que quieres) y envíalo. La IA devuelve una plantilla completa que puedes pegar de vuelta en el editor y compilar.
Pega tu plantilla existente en la sección para completar en lugar de dejarla en blanco. La IA la usa como punto de partida, así que cualquier personalización que ya hayas hecho se conserva en lugar de ser reemplazada por la predeterminada.
El prompt es específico de cada bloque. El botón Copy AI prompt solo aparece en bloques que admiten plantillas personalizadas.
La plantilla predeterminada de la que partes es una copia funcional del marcado integrado del bloque, así que siempre tienes una referencia correcta y que renderiza para modificar, en lugar de una página en blanco. Recurre a Reset to default cuando quieras recuperar esa referencia.No siempre es una coincidencia byte a byte. La plantilla predeterminada del Header también renderiza logoUrl, para el cual el marcado integrado no tiene ubicación, así que activar esa plantilla es la forma en que una imagen de encabezado subida aparece por primera vez.

Qué reemplaza tu plantilla

Una plantilla reemplaza el renderizado del bloque por completo. No queda ningún envoltorio alrededor de tu JSX, lo que tiene consecuencias que vale la pena conocer antes de empezar a borrar cosas:
La pestaña Design es la que sorprende a la gente. Mientras una plantilla personalizada está activa, los campos de la pestaña Design se deshabilitan y aparece un ícono de advertencia junto al encabezado “Design”. Pasa el cursor sobre el ícono para ver el motivo. Dale estilo al bloque desde tu plantilla, ya sea inline o con tu propio CSS. Los campos se vuelven a habilitar en cuanto desactivas la plantilla personalizada.
Lo que conservas: la posición del bloque en el carrito, su interruptor de visibilidad, sus configuraciones (que siguen alimentando las props que recibes), el panel de Custom CSS del carrito y el skeleton de carga integrado. Esto último sorprende a la gente. El bloque verifica si el carrito sigue cargando antes de llegar a tu plantilla, así que el skeleton integrado se renderiza durante la carga y tu plantilla solo se ejecuta una vez que el carrito está listo. No tienes que construir un estado de carga.

Qué está disponible dentro de una plantilla

Tu plantilla es un único componente de función. Se compila desde TSX, así que las anotaciones de tipo están permitidas y se eliminan en tiempo de compilación. Por eso las plantillas predeterminadas están escritas con ellas:
La línea de la firma y la llave de cierre están bloqueadas: el editor no te deja editar ninguna de las dos, y al pasar el cursor muestra “Locked — this line can’t be edited.” Tú escribes el cuerpo entre ellas. Reset to default es lo único que puede reemplazarlas. Qué más importa:
  • Tienes cinco hooks: useState, useEffect, useMemo, useRef y useCallback. Más Fragment, para <>…</>.
  • No hay imports. No puedes hacer import de nada, y no hay un objeto React en alcance, así que no hay React.useReducer ni React.Children. Si un hook no está en la lista de arriba, no está disponible.
  • Las props son de solo lectura. Mutar una prop no servirá de nada. Para cambiar el carrito, usa las props de handler que el bloque te da (onClose, increment, selectPlan, etcétera) en lugar de escribir directamente en las props.
  • window es alcanzable, así que una plantilla puede llamar al Cart SDK vía window.aftersell.cart cuando necesita algo que las props del bloque no cubren.

Convenciones en todos los bloques

Tres reglas se cumplen en todas partes, y conocerlas elimina la mayor parte de las conjeturas:
  • Las props *Html son texto enriquecido pre-sanitizado. Renderízalas con dangerouslySetInnerHTML. Ya pasaron por el sanitizador del carrito, y los tokens del comerciante como {{total_price}} ya están resueltos.
  • Los precios que llegan como string ya están formateados en el formato de dinero de la tienda. Los precios como number están en centavos. Un bloque te da uno u otro, y la tabla de cada bloque indica cuál.
  • isLoading siempre es false dentro de una plantilla. El bloque renderiza su skeleton integrado y solo llama a tu plantilla una vez que el carrito se ha cargado, así que la prop se pasa por completitud más que para que ramifiques sobre ella.
Algunos bloques no devuelven nada en ciertos estados, así que tu plantilla nunca es llamada con datos vacíos. La plantilla de Rewards nunca ve un milestones vacío, y la plantilla de Subscription upgrade nunca ve un view nulo. La referencia de cada bloque indica dónde aplica esto, así que puedes omitir la rama del estado vacío.

Dar estilo a una plantilla personalizada

La plantilla predeterminada de la que partes lleva los classnames del bloque. Cómo das estilo a tus ediciones depende de cuánto te alejes de ese punto de partida.

Las dos familias de clases

Cada elemento en una plantilla predeterminada lleva un classname emparejado, y hacen trabajos muy diferentes: Así que cart-internal-header__title es lo que hace que el título se vea como el título integrado, y cart-external-header__title es el asidero que debes usar cuando quieres cambiar cómo se ve.

Cambios pequeños: conserva ambos classnames

Si estás reordenando elementos, cambiando etiquetas o agregando algo dentro de la estructura existente, deja los classnames como están. Conservas gratis la apariencia integrada, y rediseñas mediante Custom CSS apuntando a los ganchos cart-external-*.

Reestructuración: elimina ambos classnames

Cuando estás cambiando la estructura del DOM en lugar de ajustarla, quita ambas familias de tu marcado y usa tus propios classnames en su lugar. Hay una razón distinta para cada una. Elimina cart-internal-* porque el CSS integrado fue escrito para el DOM integrado. Mantén esas clases en marcado reestructurado y heredarás reglas de layout que asumen elementos que ya no tienes: contenedores flex que esperan otros hijos, espaciado entre elementos que se movieron, posicionamiento relativo a algo que eliminaste. Esto suele manifestarse como que tu propio CSS “no funciona” cuando en realidad las reglas integradas son las que están ganando.
Elimina cart-external-* porque es un nombre compartido, no tuyo. Esos classnames significan algo específico en el marcado integrado, y tu Custom CSS se escribe una sola vez para todo el carrito. Si una plantilla reestructurada los reutiliza, cualquier regla que escribas apuntará tanto a tu estructura como a la integrada.Eso sale mal en el momento en que desactivas la plantilla personalizada: el bloque vuelve a su marcado integrado, y tu CSS sigue apuntando a él, ahora dando estilo a un DOM para el que nunca fue escrito. Tu propio prefijo mantiene los dos limpiamente separados, de modo que desactivar una plantilla sea una reversión limpia.
Dos formas de dar estilo a lo que has construido:

Opción 1: tus propios classnames más Custom CSS

Lo mejor para cualquier cosa que vayas a mantener o reutilizar. Dale a tus clases un prefijo con el que nadie más colisione, normalmente el nombre de tu tienda o marca:
Luego, en el editor del carrito, selecciona Cart settings en el panel izquierdo y abre la pestaña Custom CSS a la derecha:
Un prefijo importa más de lo que parece. Sin uno, una clase como .header o .title corre el riesgo de colisionar con las clases propias del carrito, la plantilla de otra app o un bloque futuro.

Opción 2: estilos inline

Sin ida y vuelta al panel de CSS, y todo vive en un solo lugar:
Bueno para andamiaje de layout y casos puntuales. Sus límites son los habituales: sin :hover ni otras pseudoclases, sin media queries y sin reutilización entre bloques. Recurre a la Opción 1 cuando quieras cualquiera de esas cosas.

Elegir un enfoque

El carrito se renderiza en un shadow root, así que la hoja de estilos de tu tema no puede alcanzar su interior. Los estilos de una plantilla personalizada tienen que venir del panel Custom CSS propio del carrito o de estilos inline, no de tu tema. Consulta Custom CSS.

Cuando una plantilla falla

Una plantilla rota nunca rompe el carrito. El bloque no renderiza nada y todo lo que lo rodea sigue funcionando, lo cual es seguro pero fácil de pasar por alto: un espacio en blanco donde debería estar tu bloque es el síntoma. Como el bloque desaparece silenciosamente en lugar de mostrar un error visible, verifica siempre una plantilla en vista previa antes de publicar. Si un bloque ha desaparecido, abre primero la consola del navegador. Dos cosas contra las que vale la pena protegerse, ya que ambas hacen crashear una plantilla que asume lo contrario:
  • Props anulables. Muchas props son null en condiciones normales (logoUrl sin logo, imageUrl sin imagen, variantTitle en un producto de una sola variante). Verifícalas antes de usarlas.
  • Arrays que pueden estar vacíos. discountTags y discountCodes son [] mucho más a menudo que no.

Limitaciones

  • Las plantillas personalizadas son anulaciones de visualización. Para ejecutar lógica contra el carrito (suscribirte a eventos, agregar artículos, reaccionar a cambios), usa Scripts personalizados y el Cart SDK.
  • Casi todos los bloques admiten una. Las excepciones son el bloque Express payments, que aloja los propios botones de pago de Shopify, y el contenedor Cart items en sí, aunque la fila Product dentro de él sí admite una plantilla personalizada.
  • Una plantilla no puede cambiar lo que un bloque hace fundamentalmente. Cambia cómo se presentan los datos del bloque, no los datos ni el comportamiento detrás de ellos.

Props de cada bloque

Cada bloque pasa sus propios datos. La tabla completa de props, con tipos y un ejemplo desarrollado, vive en la página de ese bloque: El bloque Custom code es la única superficie que agrega marcado en lugar de reemplazar el renderizado de un bloque, así que sus props son diferentes: todo el carrito, más una acción de agregar al carrito. Consulta Bloques de código personalizado → Props.