13 · Checkout UI Extensions
Personalización del checkout con targets y APIs.
Las Checkout UI Extensions son componentes React — preact bajo el capó — que se renderizan en puntos específicos del checkout de Shopify. El checkout en sí mismo está bloqueado: no puedes modificar su HTML ni inyectar JavaScript arbitrario. Lo que sí puedes hacer es declarar una extensión que se monta en un “target” definido — antes de la dirección, después de los artículos del carrito, en la pantalla de confirmación — y que el comprador ve integrada como parte del flujo nativo.
-
shopify app generate extension --type checkout_ui --name gift-message— Scaffold de la extensión de checkout (una sola vez) -
shopify app dev— Preview local con el Checkout Editor del dev store -
shopify app deploy— Publicar la extensión al registro de Shopify
Buscá los bloques con badge ✓ Ejecutar en el contenido. Los bloques con 📖 Referencia son ilustrativos — no los ejecutes.
Qué es y por qué existe
El checkout de Shopify es intencionalmente hermético. Shopify no permite que código arbitrario de terceros se ejecute dentro del proceso de pago — las implicaciones de seguridad y de performance son demasiado severas. Lo que sí permite, desde el lanzamiento del modelo de Checkout Extensibility en 2023, es que las apps declaren extensiones que se montan en puntos de integración predefinidos y controlados.
Ese cambio liquidó checkout.liquid. La plantilla checkout.liquid era el mecanismo antiguo para personalizar el checkout en cuentas Shopify Plus — acceso completo al HTML del checkout, poder para inyectar scripts, cambiar el layout. Shopify la deprecó para cuentas Plus en 2024 y hoy está en modo legacy para todos los planes. El reemplazo es Checkout Extensibility: Checkout UI Extensions para la UI, Shopify Functions para la lógica.
La ventaja del modelo de extensiones sobre checkout.liquid no es solo para Shopify — también es para el desarrollador. Las extensiones son sandboxadas: no pueden romper el flujo de pago, no tienen acceso al DOM del checkout, y la API que exponen es curada y estable. Tus extensiones sobreviven a las actualizaciones del checkout de Shopify sin que tengas que mantenerlas activamente.
El runtime
La tecnología subyacente es preact, con una API de React compatible. Esto significa que escribes componentes como si fuera React, pero el runtime es preact — más ligero. Las extensiones se compilan a Wasm y se sirven desde la CDN de Shopify.
Los imports vienen del paquete @shopify/ui-extensions-react/checkout. NO importes de react directamente — el runtime no es React, y los imports de React pueden causar errores en tiempo de ejecución dentro del sandbox de la extensión.
Targets de extensión
Un “target” es el punto de montaje donde tu extensión aparece en el checkout. Hay dos categorías:
Block targets: el comerciante coloca tu extensión en el Checkout Editor, igual que coloca bloques en el Theme Editor. La extensión aparece donde el comerciante decide, dentro de la zona configurable. El target purchase.checkout.block.render es el más frecuente y el que usarás para features como “campo de mensaje de regalo”, “selector de fecha de entrega”, o “programa de puntos”.
Static targets: la extensión se monta automáticamente en una posición fija del checkout sin configuración del comerciante. Ejemplos:
purchase.checkout.delivery-address.render-before— antes del formulario de direcciónpurchase.checkout.cart-line-item.render-after— después de cada artículo del carritopurchase.checkout.contact.render-after— después del campo de email de contactopurchase.checkout.reductions.render-before— antes de la sección de descuentospurchase.checkout.payment-method-list.render-before— antes de los métodos de pagopurchase.thank-you.block.render— en la página de confirmación de pedidopurchase.order-status.block.render— en la página de estado del pedido
La lista completa de targets varía por versión de API — consulta la documentación oficial para ver todos los disponibles en 2026-04 y posteriores.
Estructura del proyecto
// brew-atlas-app/extensions/gift-message/ (directorio de la extensión)
extensions/
└── gift-message/
├── src/
│ └── index.tsx
├── shopify.extension.toml
└── package.jsonA diferencia de las Functions (Rust), las Checkout UI Extensions tienen su propio package.json porque son proyectos de JavaScript/TypeScript. El CLI las instala como workspaces del monorepo del app.
El TOML de la extensión
# brew-atlas-app/extensions/gift-message/shopify.extension.toml
api_version = "2026-04"
[[extensions]]
name = "Gift message"
handle = "gift-message"
type = "ui_extension"
[[extensions.targeting]]
module = "./src/index.tsx"
target = "purchase.checkout.block.render"Una sola extensión puede declarar múltiples [[extensions.targeting]] apuntando a distintos targets — por ejemplo, renderizar un campo en el checkout Y una confirmación en la thank-you page. Cada targeting tiene su propio módulo o puede apuntar al mismo.
La extensión: campo de mensaje de regalo
// brew-atlas-app/extensions/gift-message/src/index.tsx
import {
reactExtension,
BlockStack,
Text,
TextField,
Divider,
useApplyAttributeChange,
useAttributeValues,
} from '@shopify/ui-extensions-react/checkout';
// El punto de entrada de la extensión declara el target y el componente raíz
export default reactExtension(
'purchase.checkout.block.render',
() => <GiftMessageExtension />,
);
function GiftMessageExtension() {
// Leer el atributo actual del pedido (si el comprador ya escribió algo)
const [giftMessage] = useAttributeValues(['gift_message']);
// Callback para actualizar el atributo en el pedido
const applyAttributeChange = useApplyAttributeChange();
function handleChange(value: string) {
applyAttributeChange({
type: 'updateAttribute',
key: 'gift_message',
value: value,
});
}
return (
<BlockStack spacing="base">
<Divider />
<Text size="medium" emphasis="bold">
Mensaje de regalo
</Text>
<Text size="small" appearance="subdued">
Tu mensaje aparecerá en una tarjeta incluida en el envío.
</Text>
<TextField
label="Mensaje (opcional)"
value={giftMessage ?? ''}
onChange={handleChange}
multiLine={3}
maxLength={200}
/>
</BlockStack>
);
}El hook useAttributeValues lee los atributos de orden existentes. Los atributos de orden son pares clave-valor que viajan con el pedido — visibles para el comerciante en el Admin y accesibles desde el Admin API. useApplyAttributeChange los actualiza en tiempo real mientras el comprador escribe.
El package.json de la extensión
// brew-atlas-app/extensions/gift-message/package.json
{
"name": "gift-message",
"version": "0.0.1",
"private": true,
"scripts": {
"build": "shopify app build --filter gift-message"
},
"devDependencies": {
"@shopify/ui-extensions": "*",
"@shopify/ui-extensions-react": "*",
"typescript": "^5.0.0"
}
}Las versiones de @shopify/ui-extensions y @shopify/ui-extensions-react deben coincidir con la api_version declarada en el TOML. El CLI gestiona esto automáticamente cuando genera la extensión — si los actualizas manualmente, asegúrate de que la versión del paquete es compatible con la versión de API que declaraste.
APIs disponibles en el checkout
El paquete @shopify/ui-extensions-react/checkout expone docenas de hooks para leer el estado del checkout y proponer cambios:
Lectura de datos:
useCartLines()— las líneas del carrito con cantidades, variantes, y preciosuseTotalAmount()— el total del pedidouseDeliveryGroups()— los grupos de entrega y métodos de envío seleccionadosuseEmail()— el email de contacto del compradoruseLocalizationCountry()— el país de localizaciónuseShippingAddress()— la dirección de envío (si el comprador la completó)useAttributeValues(keys)— atributos de orden por clave
Cambios propuestos (requieren confirmación del runtime):
useApplyAttributeChange()— actualizar atributos del pedidouseApplyDiscountCodeChange()— añadir o quitar códigos de descuentouseApplyNoteChange()— actualizar la nota del pedido
Componentes UI disponibles:
Los componentes exportados desde el paquete (BlockStack, InlineStack, Text, TextField, Button, Checkbox, Banner, Divider, Image, etc.) son los únicos elementos UI que puedes usar. No puedes usar HTML nativo (<div>, <p>) — estás dentro de un renderer controlado, no en el DOM del navegador directamente.
Restricciones del sandbox
Las Checkout UI Extensions corren en un sandbox con restricciones deliberadas:
Red: por defecto, las extensiones no pueden hacer requests HTTP. Para habilitar acceso a un servidor externo, debes declararlo en el TOML bajo [extensions.capabilities] con network_access = true. Las apps con network_access pasan por una revisión adicional para apps públicas.
DOM: no tienes acceso al DOM del checkout. Solo puedes usar los componentes del paquete de extensiones. No puedes ejecutar document.querySelector, window.location.href, ni ninguna API del browser directamente.
Datos: solo tienes acceso a los datos que los hooks exponen. No puedes leer campos del formulario de checkout que no estén en la API — como datos de tarjeta de crédito, por razones obvias.
Tiempo de ejecución: las extensiones tienen un timeout de ejecución. Las operaciones de larga duración (loops costosos, awaits largos) pueden causar que la extensión se descarte.
Activación por el comerciante
Después de hacer shopify app deploy, la extensión existe en el registro de Shopify pero no es visible en ningún checkout. El comerciante tiene que activarla desde el Checkout Editor en Admin → Configuración → Checkout → Personalizar.
Para block targets, el comerciante la añade desde el panel de bloques del editor — exactamente igual que añade un bloque de app en el Theme Editor. Para static targets, la activación puede ser automática o requerir habilitación explícita dependiendo del target.
Puentes mentales
Las Checkout UI Extensions son a Shopify lo que las extensiones de navegador son a Chrome: código sandboxado que extiende una experiencia de usuario bloqueada. No puedes modificar el HTML del checkout, igual que una extensión de Chrome no puede reemplazar el motor de renderizado del navegador. Lo que sí puedes hacer es añadir UI en puntos de integración predefinidos (targets / content scripts en URIs específicos) y leer un subconjunto controlado del estado de la página (hooks de checkout / APIs de Chrome Extension). La restricción no es arbitraria — es lo que hace posible que Shopify garantice que ninguna extensión puede romper el proceso de pago.
Estado 2026
Lo relevante al 2026:
checkout.liquidestá muerto: para cuentas Plus fue deprecado en 2024. Para todos los planes, el modelo de Checkout Extensibility reemplaza cualquier personalización legacy. No hay razón para usarcheckout.liquiden código nuevo.- API 2026-04 es la versión estable actual para extensiones de checkout. Las versiones
2025-07,2025-10siguen siendo válidas y soportadas. Si creas una extensión nueva, usa2026-04. - Nuevos targets en 2026: los targets de “order status” (
purchase.order-status.block.render) y “thank you” (purchase.thank-you.block.render) están GA. Úsalos para continuidad post-compra — confirmaciones, upsells, contenido de onboarding. - Performance: las extensiones se compilan a Wasm y se pre-renderizan. Shopify audita el bundle size de las extensiones en el proceso de revisión de apps públicas. Mantén las dependencias mínimas.
Proyecto · Brew Atlas
La extensión gift-message de Brew Atlas añade un campo de mensaje de regalo en el checkout. El comerciante la activa desde el Checkout Editor y la coloca donde prefiera dentro del flujo.
El mensaje queda guardado como atributo del pedido (gift_message) y es visible para el equipo de fulfillment en el detalle del pedido en el Admin. También es accesible desde el Admin GraphQL API en order.attributes.
Los archivos están en ~/proyectos/shopify/brew-atlas/brew-atlas-app/extensions/gift-message/. Para desplegar y previsualizar:
Desde ~/proyectos/shopify/brew-atlas/brew-atlas-app/:
shopify app dev
Desde ~/proyectos/shopify/brew-atlas/brew-atlas-app/:
shopify app deploy
Después del deploy, el comerciante activa la extensión desde Admin → Configuración → Checkout → Personalizar → Add block → Apps → Gift message.
Qué vas a crear/tocar en esta sección (archivos):
~/proyectos/shopify/brew-atlas/brew-atlas-app/extensions/gift-message/src/index.tsx— la extensión de checkout.~/proyectos/shopify/brew-atlas/brew-atlas-app/extensions/gift-message/shopify.extension.toml— target y metadatos.~/proyectos/shopify/brew-atlas/brew-atlas-app/extensions/gift-message/package.json— dependencias del paquete.
Comandos a ejecutar (orden):
shopify app generate extension --type checkout_ui --name gift-messagedesde~/proyectos/shopify/brew-atlas/brew-atlas-app/(scaffold, una sola vez).shopify app devdesde~/proyectos/shopify/brew-atlas/brew-atlas-app/(preview local).shopify app deploydesde~/proyectos/shopify/brew-atlas/brew-atlas-app/(publicar).
Errores comunes
Los atributos de pedido que escribes con useApplyAttributeChange son visibles para el comerciante en el Admin y en cualquier integración que lea el pedido via Admin API. No los uses para datos que el comprador no debería saber que estás guardando, y no los uses para datos sensibles (ningún identificador personal más allá del flujo de pedido). Los atributos de pedido son parte del registro público del pedido, no un campo privado de la extensión.
No importes de react directamente en una Checkout UI Extension. El runtime es preact y el paquete @shopify/ui-extensions-react ya proporciona el wrapper correcto. Importar React directamente puede causar que el bundle crezca innecesariamente o que fallen las invocaciones del runtime en el sandbox de Shopify.
Las extensiones de checkout necesitan activación manual por el comerciante en el Checkout Editor después de cada deploy. El deploy sube la extensión al registro, pero no la activa automáticamente en los checkouts existentes. Para apps públicas, incluye instrucciones de activación en el proceso de onboarding de tu app — muchos comerciantes instalan la app y esperan que “funcione solo” sin entender que hay un paso de configuración en el Checkout Editor.
Para testear tu extensión sin desplegar, usa el comando de preview del CLI: shopify app dev levanta un servidor local y muestra un link de preview del checkout editor del dev store. Puedes hacer cambios en el código y ver el resultado en el editor en tiempo casi real. Los errores de compilación de TypeScript aparecen en la terminal — leer esos errores es más rápido que depurar en el browser.
Checklist senior
- Puedes explicar por qué
checkout.liquidestá deprecado y qué lo reemplaza en el modelo de Checkout Extensibility - Conoces la diferencia entre block targets y static targets: cuándo el comerciante configura la posición y cuándo es automática
- Sabes los hooks principales:
useCartLines,useApplyAttributeChange,useAttributeValues, y en qué casos usar cada uno - Entiendes por qué no puedes usar HTML nativo ni APIs del browser directamente en una extensión de checkout
- Sabes que
network_access = trueen el TOML es necesario para que la extensión pueda hacer requests HTTP - Entiendes que los atributos de pedido son visibles para el comerciante y en el Admin API — no son datos privados
- Sabes que después de
shopify app deploy, el comerciante debe activar la extensión desde el Checkout Editor - Puedes usar el preview del CLI (
shopify app dev) para iterar sobre la extensión sin desplegar
Quiz · ¿Lo tenés claro?
-
1. ¿Por qué `checkout.liquid` está deprecado y qué lo reemplaza?
checkout.liquid daba acceso completo al HTML del checkout en Plus → imposible garantizar PCI y consistencia. Shopify lo deprecó para Plus en 2024 y lo reemplazó con el modelo dual: UI Extensions + Functions, cada una en su sandbox.
-
2. ¿Cuál es la diferencia entre un block target y un static target?
Block targets son 'opcionales/configurables' (el merchant decide). Static targets son 'siempre ahí' — se renderizan automáticamente cuando la extensión está activa en un punto fijo del flujo.
-
3. Quieres hacer fetch a tu backend desde una Checkout UI Extension. ¿Qué paso es obligatorio?
Por defecto, una Checkout UI Extension no puede hacer red. Hay que declarar `network_access = true` en `shopify.extension.toml` y listar los dominios permitidos. Sin eso el fetch se bloquea en el sandbox.
-
4. Tu extensión necesita guardar 'coffee_notes' en el pedido para que el merchant lo vea. ¿Cómo?
`useApplyAttributeChange` es el hook para escribir attributes. Importante: los attributes NO son privados — el merchant los ve y están en Admin API. No metas ahí secretos del cliente.
-
5. Desplegaste la extensión con `shopify app deploy`. El merchant no la ve en su checkout. ¿Qué falta?
Deploy ≠ activar. Cada merchant debe ir al Checkout Editor y arrastrar la extensión al target (block targets) o aceptarla (static targets). Es explícito para que el merchant tenga control.
Siguiente
Las Checkout UI Extensions cubren la experiencia del comprador durante el proceso de pago. El siguiente bloque completa la historia de extensiones de UI abordando el otro lado del customer journey: las Customer Account UI Extensions, que permiten a tu app añadir funcionalidad en el área de cuenta del cliente — subscripciones, historial personalizado, acciones post-compra.