Shopify Checkout Extensibility: patrones de UX tras el EOL de Scripts el 30 de junio
En 13 días, el 30 de junio de 2026, Shopify Scripts llega a su fin. Para las tiendas que han usado Scripts para personalizar el checkout, esta ya no es una fecha teórica. La migración a la nueva Checkout Extensibility API (UI Extensions, Functions, Checkout Blocks) es obligatoria.
La buena noticia: la nueva API está más estructurada. La lógica del checkout queda separada de la capa de UX, lo que mejora la reutilización y la capacidad de testing. La noticia menos buena: muchos de los patrones de UX construidos con Scripts hay que replantearlos para la nueva arquitectura.
Este post te da 5 plantillas de patrones concretas para la transición.
Por qué el trabajo de UX empieza de nuevo
Scripts se ejecutaba en el servidor y podía manipular directamente los datos del checkout: cambiar precios, añadir productos, filtrar opciones de envío. La nueva API funciona de otra manera:
- UI Extensions se renderizan en el cliente en puntos de extensión definidos
- Checkout Functions se ejecutan en el servidor para la lógica (descuentos, filtros de envío, métodos de pago)
- Checkout Blocks son elementos de UI ya construidos que se colocan desde el editor
Esta separación es arquitectónicamente limpia. Pero significa que cada patrón existente hay que remapearlo. Un Script que implementaba "envío gratis a partir de 50 $" se convierte en una combinación de una Checkout Function (lógica de envío) y una UI Extension (visualización del banner).
Patrón 1: indicador de progreso
Qué hace: Muestra al comprador a qué distancia está del siguiente umbral (por ejemplo, envío gratis, un producto de regalo).
Solución anterior con Scripts: Comprobación del valor del carrito en el servidor, cálculo del resto, escrito de vuelta en el checkout como un metafield.
Nueva solución con UI Extensions:
// Extensions/progress-indicator/src/index.jsx
import { useCartLines, Text, ProgressBar } from '@shopify/checkout-ui-extensions-react';
export default function ProgressIndicator() {
const lines = useCartLines();
const total = lines.reduce((sum, line) => sum + line.cost.totalAmount.amount, 0);
const threshold = 50;
const progress = Math.min(total / threshold, 1);
const remaining = Math.max(threshold - total, 0);
if (progress >= 1) {
return <Text>Envío gratis incluido.</Text>;
}
return (
<>
<ProgressBar value={progress} />
<Text>Añade ${remaining.toFixed(2)} más para el envío gratis.</Text>
</>
);
}Consideraciones de UX:
- La barra de progreso debe ser accesible:
aria-labelyaria-valuenowlos gestiona el sistema de componentes de Shopify. - Copy: concreto y orientado a la acción. No "ya casi" (vago), sino "$X más" (acción clara).
- Colocación: bloque de resumen del carrito, encima de la CTA. No al final de la página, donde se ignora.
Ventaja de la nueva API: La extensión ve el carrito en tiempo real. Con Scripts se necesitaba un round-trip al servidor.
Patrón 2: integración de wallets express
Qué hace: Shop Pay, Apple Pay y Google Pay se colocan de forma destacada en el checkout para reducir la friction antes del formulario de checkout.
Solución anterior con Scripts: Scripts no podía renderizar métodos de pago por sí mismo. Este patrón había que implementarlo vía código de tema, lo que a menudo provocaba conflictos en storefronts headless.
Nueva solución con Checkout Extensions (los wallets son nativos):
Los métodos de pago express se pueden integrar en el punto de extensión purchase.checkout.payment-method-list.free-payment-methods-before de la nueva arquitectura de Extensibility. Shopify renderiza Shop Pay, Apple Pay y Google Pay de forma nativa. El trabajo de UX está en el posicionamiento correcto y en una jerarquía visual clara.
Checklist de UX:
- Muestra los wallets express antes del formulario, no después de "Continuar al pago".
- Separador visual claro entre las opciones express y el formulario estándar (por ejemplo, "O continúa con los datos de la tarjeta").
- Mobile-first: en dispositivos móviles, Apple Pay y Google Pay usan biometría. El TTFB y el LCP tienen que ser sólidos, de lo contrario el flujo biométrico se rompe.
El Checkout Growth Kit incluye componentes ya listos exactamente para este flujo express, con la optimización móvil ya probada.
Advertencia: La integración de wallets está ligada a la plataforma. Construir tu propio checkout headless (sin pasar por Shopify Checkout) da más flexibilidad, pero conlleva más complejidad.
Patrón 3: validación personalizada
Qué hace: Impide que el usuario complete el checkout con datos incompletos o incorrectos (por ejemplo, campos obligatorios que faltan en atributos personalizados).
Solución anterior con Scripts: Shopify Scripts no podía disparar validaciones en el cliente. La validación pasaba por el JavaScript del tema o no se hacía en absoluto, una fuente de bugs frecuente.
Nueva solución con Checkout Functions:
// functions/custom-validation/src/run.js
export function run(input) {
const errors = [];
const attributes = input.cart.attribute || [];
const companyName = attributes.find(a => a.key === 'company_name');
if (!companyName || !companyName.value.trim()) {
errors.push({
localizedMessage: 'El nombre de la empresa es obligatorio para pedidos B2B.',
target: 'cart.attribute.company_name'
});
}
return { errors };
}Consideraciones de UX:
- Los mensajes de error deben aparecer justo junto al campo afectado, no como un toast genérico en la parte superior de la página.
- Copy: concreto y orientado a la solución. "Falta el nombre de la empresa", no "Error en el campo 3".
- Requisito de accesibilidad: los mensajes de error deben poder anunciarse a los lectores de pantalla. El campo
targeten la salida de las Functions vincula el mensaje de error con el elemento DOM correcto.
Patrón 4: bloque de upsell dinámico
Qué hace: Muestra productos complementarios contextualmente relevantes en el checkout según el contenido del carrito.
Solución anterior con Scripts: Scripts podía añadir productos al carrito, pero no podía renderizar una UI rica para recomendaciones de producto. La UI de upsell venía del tema.
Nueva solución con UI Extensions + Checkout Functions:
// Extensions/dynamic-upsell/src/index.jsx
import { useApplyCartLinesChange, ProductThumbnail, Button, Text } from '@shopify/checkout-ui-extensions-react';
export default function DynamicUpsell({ productRecommendation }) {
const applyChange = useApplyCartLinesChange();
const addProduct = () => {
applyChange({
type: 'addCartLine',
merchandiseId: productRecommendation.variantId,
quantity: 1,
});
};
return (
<div>
<ProductThumbnail source={productRecommendation.imageUrl} size="small" />
<Text size="medium">{productRecommendation.title}</Text>
<Text size="small" appearance="subdued">{productRecommendation.price}</Text>
<Button onPress={addProduct} kind="secondary">
Añadir al pedido
</Button>
</div>
);
}Consideraciones de UX:
- Nunca muestres más de un producto de upsell a la vez. Más de uno aumenta la tasa de abandono.
- Etiquétalo claramente como "Otros también compraron" o "Combina bien con", nunca como un artículo obligatorio.
- Haz A/B testing de la colocación: la posición (antes o después de la dirección de envío) supone una diferencia del 10-20% en la tasa de adopción.
Para la implementación en el Headless Frontend for Shopify, los bloques de upsell forman parte del conjunto estándar de componentes de checkout.
Patrón 5: botón de checkout accesible
Qué hace: La CTA principal del checkout debe estar correctamente implementada para lectores de pantalla, navegación por teclado y requisitos de contraste.
Por qué esto pasa a primer plano: Los requisitos de accesibilidad se están endureciendo en los mercados europeos. Construir una nueva implementación de checkout es el momento adecuado para hacerlo bien desde el principio, no como un parche posterior.
Nueva solución con UI Extensions:
Shopify Checkout Extensibility usa el framework Checkout UI Extensions React, que implementa los atributos ARIA correctamente por defecto. Tu trabajo no está en el marcado ARIA, sino en:
- Contraste de color: los botones de CTA deben cumplir el nivel AA de WCAG 2.1 (ratio de contraste 4.5:1).
- Gestión del foco: tras abrirse un modal (por ejemplo, validación de dirección), el foco debe moverse dentro del modal y volver al elemento que lo activó al cerrarse.
- Comunicar los estados de carga: mientras se procesa el pedido, el lector de pantalla debe anunciar "Se está procesando el pedido", no limitarse a mostrar un spinner.
// Correcto: comunicar el estado de carga
<Button
loading={isProcessing}
accessibilityLabel={isProcessing ? 'El pedido se está procesando, espera por favor.' : 'Realizar pedido'}
onPress={handleSubmit}
>
{isProcessing ? 'Procesando...' : 'Realizar pedido'}
</Button>El Performance and Core Web Vitals module incluye comprobaciones de cumplimiento WCAG para los componentes de checkout como parte del pipeline de QA automatizado.
También relevante: Composable Visual Page Builder para la capa de experiencia previa al checkout.
Resumen: qué cambia con el EOL
- Dimensión | Antes del EOL (Scripts) | Después del EOL (Extensibility API)
- Ejecución de la lógica | En el servidor (síncrona) | Functions en el servidor + Extensions en el cliente
- Renderizado de UI | Código del tema | UI Extensions en puntos de extensión declarados
- Capacidad de testing | Difícil (sin framework de unit test) | Mejor (las Functions son JS/TS puro)
- Despliegue | Editor de Scripts de Shopify | CI/CD vía Shopify CLI
- Accesibilidad | Manual | Parcialmente gestionada por el sistema de componentes
La fecha del EOL no es un objetivo de migración blando. Shopify desactiva Scripts el 30 de junio. Si todavía tienes Scripts en producción: convierte la migración en prioridad esta semana.
Para más contexto sobre el sunset general de Scripts: Shopify Scripts End of Life 2026, para marcas Plus.