En la Guia de arquitectura Shopify cubrimos los fundamentos. Hoy, una pregunta practica que surge en casi cada proyecto Shopify: Deberia construir esta funcionalidad en el theme (Liquid) o en una custom app?
En smplx., no respondemos esta pregunta de forma teorica. Analizamos tu caso de uso, calculamos costes, rendimiento y mantenimiento -- y luego tomamos una decision fundamentada.
Las diferencias fundamentales
Codigo del theme (Liquid)
Que es Liquid?
Liquid es el lenguaje de plantillas de Shopify. El codigo en el theme se ejecuta en el storefront -- es decir, en el navegador del cliente. Esto lo hace rapido para cosas simples, pero tambien limitado.
Arquitectura:
Navegador del cliente -> Liquid en el Theme -> HTML renderizado
Pros:
- Despliegue sencillo (Git push, Theme Editor)
- Disponible inmediatamente despues del push
- Buen rendimiento para cosas simples (no se necesita llamada API)
- Cerca de los datos del catalogo (Products, Collections, etc.)
- Sin infraestructura adicional
Contras:
- Sin logica del lado del servidor (riesgo de seguridad con datos sensibles)
- Limites con logica de negocio compleja
- Herramientas de depuracion limitadas
- Sin acceso a la Admin API
- Dificil de testear automaticamente
Custom App
Que es una Custom App?
Una custom app es codigo que se ejecuta en los servidores de Shopify (backend) o en tus propios servidores. Tiene acceso a la Admin API y puede trabajar directamente con los datos de la tienda.
Arquitectura:
Navegador del cliente -> Shopify Admin / Tu App -> Liquid en el Theme (opcional) -> HTML renderizado
Pros:
- Acceso a la Admin API (operaciones de escritura!)
- Logica del lado del servidor = procesamiento seguro
- Webhooks para arquitectura orientada a eventos
- Escalable para escenarios complejos
- Mejores herramientas de depuracion
- Testing automatizado posible
Contras:
- Proceso de despliegue mas complejo
- Limites de tasa de API a considerar
- Mas infraestructura (Servidor / Shopify Platform)
- Mayor latencia para datos en tiempo real
- Costes de hosting/infraestructura
Decisiones del mundo real: Ejemplos concretos
Ejemplo 1: Logica de descuentos dinamica
Escenario: Quieres dar descuentos automaticamente a los clientes basandote en su historial de compras.
Opcion 1: En el theme (Liquid)
{% if customer %}
{% if customer.orders_count > 10 %}
<p class="discount-banner">
Cliente VIP! +10% en todo!
</p>
{% endif %}
{% endif %}
Problema:
- Solo visualizacion en la UI, no se aplica al carrito
- Sin acceso a datos de pedidos en tiempo real
- No es posible la automatizacion
Opcion 2: Custom App con Admin API
// Al anadir producto al carrito (via Webhook)
const app = express();
app.post('/webhooks/orders/create', async (req, res) => {
const order = req.body.order;
const customer = order.customer;
if (customer.orders_count > 10) {
// Admin API: Crear codigo de descuento automaticamente
await shopify.post('/admin/api/2024-01/discount_codes.json', {
discount_code: {
price_rule_id: VETERAN_RULE_ID,
code: `VIP_${customer.id}`,
}
});
}
res.status(200).send({ success: true });
});
Decision: Custom App (Webhooks + Admin API) Razon: La aplicacion automatica de descuentos requiere logica del lado del servidor
Ejemplo 2: Extension de checkout personalizada
Escenario: Quieres un campo personalizado en el checkout (p. ej., "fecha de entrega deseada").
Opcion 1: Theme Liquid + JavaScript
<input type="date" name="attributes[preferred_delivery_date]">
<script>
// Validacion en el navegador
document.querySelector('form').addEventListener('submit', (e) => {
const date = document.querySelector('input[name*="delivery_date"]').value;
if (new Date(date) < new Date()) {
e.preventDefault();
alert('Por favor elige una fecha futura');
}
});
</script>
Problema:
- El checkout es demasiado sensible para solo validacion en el navegador
- Sin conexion con la logica de fulfillment
- Sin notificacion al almacen
Opcion 2: Checkout Extension (App Block)
// Extension en Checkout UI (API moderna de Shopify)
import { useExtensionInput } from '@shopify/checkout-ui-extensions-react';
import { Box, Text, Select } from '@shopify/checkout-ui-extensions-react';
export default function DeliveryDateExtension() {
const { extensionPoint } = useExtensionInput();
return (
<Box border="base" padding="base">
<Text>Fecha de entrega deseada:</Text>
<Select
options={generateFutureDate()}
onChange={(value) => applyAttributes({ delivery_date: value })}
/>
</Box>
);
}
Decision: Checkout Extension (arquitectura moderna de apps) Razon: El checkout es core de Shopify -- las extensions son el lugar correcto
Ejemplo 3: Caso de estudio Bekateq
Bekateq tenia originalmente una tienda con mas de 5 custom apps para diversas funciones. La complejidad ya no era manejable.
Problema:
- Cada app necesitaba monitorizacion
- Diferentes despliegues
- El rate limiting era critico
- Los costes de mantenimiento se disparaban
Solucion: Bekateq migro a una unica custom app con mas de 4.400 lineas y cero dependencias (excepto el Shopify SDK).
Leccion clave: No toda pequena funcion necesita una app separada. Pocas apps bien pensadas > muchas apps pequenas.
Matriz de decision: Cuando uso que?
| Funcionalidad | Theme (Liquid) | Custom App | Checkout Extension |
|---|---|---|---|
| UI de pagina de producto | Si | No | No |
| Filtros de collection | Si | Opcional | No |
| Logica del carrito | Solo vista | Si | Si |
| Campo de checkout | Inseguro | Posible | Si |
| Automatizacion de descuentos | No | Si | No |
| Procesamiento de webhooks | No | Si | No |
| Panel de administracion | No | Si | No |
| Sincronizacion en tiempo real con sistema externo | No | Si | No |
Comparacion de rendimiento
Escenario: Producto se anade a una collection
Solo Theme (Liquid Loop):
Peticion del navegador -> Servidor renderiza -> HTML con loop
Tiempo de renderizado: ~200ms (depende del tamano de la collection)
Custom App (GraphQL Admin API):
Peticion del frontend -> Llamada Admin API -> Logica del backend -> Webhook -> Actualizacion del theme
Latencia: ~500-1000ms (llamada API + procesamiento de webhook)
Mejor practica:
- Critico en tiempo (< 500ms): Theme
- No critico en tiempo (automatizacion, tareas en segundo plano): Custom App
Shopify App Bridge: El puente entre ambos mundos
App Bridge te permite escribir JavaScript en el theme que se comunica con una custom app sin recargar la pagina.
Ejemplo: El theme habla con la app
// En el JavaScript del Theme Liquid
const client = ShopifyApp.apiClient;
document.querySelector('.add-to-cart').addEventListener('click', async () => {
// Llama al backend de la Custom App
const response = await fetch('/api/custom-app/add-to-cart-hook', {
method: 'POST',
body: JSON.stringify({ productId: '123', quantity: 1 })
});
const result = await response.json();
if (result.allowed) {
// Continuar con el checkout estandar
} else {
alert(result.reason);
}
});
Ventaja: UI del theme con logica de la app. Lo mejor de ambos mundos combinado.
Admin API: Cuando necesita tu app acceso de escritura?
La Admin API tiene dos scopes:
- read_products: Leer datos
- write_products: Escribir datos
El acceso de escritura es costoso -- consume mas llamadas API y requiere mas testing.
Necesitas acceso de escritura para:
- No: Mostrar datos (solo acceso de lectura)
- No: Mostrar una lista filtrada (solo acceso de lectura)
- Si: Crear/editar productos (acceso de escritura!)
- Si: Sincronizacion de inventario (acceso de escritura!)
- Si: Creacion automatica de descuentos (acceso de escritura!)
Errores que vemos frecuentemente
Error 1: "Construire todo en una custom app masiva"
Problema: Mas de 5.000 lineas, dificil de testear, miedo al despliegue.
Solucion: Dividir por responsabilidad. Las 4.400 lineas de Bekateq estaban altamente enfocadas.
Error 2: "Usare Liquid para operaciones seguras"
Problema: Datos de clientes, descuentos, precios -- todo visible en el codigo fuente.
Solucion: Todo lo que es sensible pertenece a una custom app.
Error 3: "Rate limits? Nos ocuparemos de eso mas tarde"
Problema: La app funciona lento, recibe errores 429, los clientes ven errores.
Solucion: Desde el dia 1: Implementar manejo de rate limits.
Nuestros principios de arquitectura en smplx.
1. Liquid para presentacion El codigo del theme es solo para UI. Sin logica critica de negocio.
2. Admin API solo cuando sea necesario Acceso de lectura donde sea posible, acceso de escritura solo para operaciones reales de administracion.
3. Webhooks para automatizacion No consultes la API cada 10 segundos -- los webhooks disparan la logica.
4. Cultura de testing Las custom apps deben ser testeables automaticamente.
5. Apps minimas Una responsabilidad por app. Un proposito grande y claro.
La checklist de decision
Preguntate:
- Es sensible en datos? -> Custom App
- Necesito acceso a la Admin API? -> Custom App
- Se ejecuta automaticamente (webhook)? -> Custom App
- Debe ser super rapido (< 200ms)? -> Theme
- Es solo visualizacion de UI? -> Theme
- Debe ser testeable? -> Custom App
- Necesita monitorizacion de infraestructura? -> Custom App
Si mas de 2 puntos indican Custom App -> Custom App.
Costes: Theme vs. Custom App
Desarrollo de theme:
- 10k-50k EUR costes unicos
- 100-500 EUR/mes mantenimiento
- Bajos costes de escalado
Custom App:
- 30k-150k EUR desarrollo unico
- 500-2.000 EUR/mes infraestructura + monitorizacion
- Mayores costes de escalado (por peticion)
Sin embargo: Una custom app con un proposito claro es mas barata que 3 hacks de theme que tienes que arreglar cada mes.
Perspectiva a largo plazo
Despues de 2-3 anos, se ve asi:
Enfoque solo theme:
Ano 1: Coste: $30k (Dev) + $1.2k (Hosting)
Ano 2: Coste: $10k (Bug-Fixes) + $1.2k (Hosting)
Ano 3: Coste: $20k (Gran funcionalidad) + $1.2k (Hosting)
Total: $64.6k
Problema: El codigo se volvio demasiado complejo, ya no se puede cambiar
Enfoque basado en apps (estilo Bekateq):
Ano 1: Coste: $80k (Dev) + $6k (Hosting)
Ano 2: Coste: $5k (Bug-Fixes) + $6k (Hosting)
Ano 3: Coste: $10k (Nueva funcionalidad) + $6k (Hosting)
Total: $113k
Ventaja: El codigo es mantenible, nuevas funcionalidades tardan 5 dias en lugar de 15
Despues del ano 3, pagas menos por nuevas funcionalidades porque el desarrollo es 3 veces mas rapido.
Sobre el autor
Claudio Gerlich es Technical Architect en smplx. y esta especializado en tecnologia Shopify desde 2020. Con smplx., hemos asesorado arquitectonicamente a mas de 50 tiendas -- desde personalizaciones simples de theme hasta sistemas complejos multi-app.
Bekateq es un gran ejemplo: Les ayudamos a reestructurar su arquitectura de apps de caotica a elegante.
smplx. es Shopify Technical Partner (desde 2020) con sede en Munsterland, NRW.