El cliente tenía Shopify Advanced a 280 EUR / mes, 12 000 SKU, 4 almacenes, dual pricing B2B + B2C, 65 % de tráfico orgánico desde Google SK y CZ. La migración headless a Medusa.js se cerró tras 4 meses, dos semanas antes del Black Friday. Ningún ranking orgánico se perdió, ningún pedido en curso se perdió y la integración Stripe pasó de 14 pasos manuales por cada producto nuevo a cero. Este artículo va de lo que hicimos, lo que la pifiamos y lo que haríamos de otra forma.
Por qué headless — y cuándo NO
Headless commerce tiene dos motivos válidos:
1. **Flexibilidad de checkout custom / B2B / multi-storefront.** Shopify (incluso Advanced y Plus) tiene una pipeline de checkout rígida. Para B2B con vencimiento net-60, tiers de precios custom, multi-warehouse splitting o tax rules complejos (SK-DE-AT cross-border) Shopify se vuelve una lucha con los límites de la API y los templates Liquid. 2. **Performance + UX del storefront.** Un storefront Next.js con ISR (Incremental Static Regeneration) + edge caching alcanza LCP < 1,2 s en 4G. Un storefront renderizado en Liquid de Shopify tiene LCP 2,5–4,0 s. Para un negocio SEO-driven es una diferencia medible en facturación.
**Cuándo NO headless:** - Catálogos < 500 SKU + checkout B2C estándar → Shopify o BigCommerce salen más baratos y rápidos - El equipo no tiene capacidad para storefront Next.js propio (CMS custom, checkout custom, integraciones) - La hoja de ruta de pagos/contabilidad/marketing es toda Shopify-native (Shopify Payments, Shopify Tax, Shopify Email)
Para esos clientes encaja mejor el «semi-headless» existente — Shopify Hydrogen + Oxygen, que da frontend headless sin salir del ecosistema Shopify.
Decisiones de stack en 2026
Backend: Medusa.js vs Saleor vs Commerce.js
**Medusa.js v2.x** - Node.js, PostgreSQL, Redis - Modular, arquitectura de plugins - Mejor developer experience en 2026 - Set de features B2B más débil out-of-the-box (hay que tirar de plugin o código propio para quotes, approvals, customer hierarchy) - **Precio:** open source self-hosted, o Medusa Cloud desde 200 EUR / mes - **Cuándo:** B2C + B2B ligero, equipo dev con experiencia Node
**Saleor** - Python, Django, GraphQL-first - El set B2B más potente (customer groups, channel-based pricing, quote requests) - Multilanguage + multi-currency nativos - Curva de aprendizaje mayor, overhead GraphQL - **Precio:** open source self-hosted, o Saleor Cloud desde 500 EUR / mes - **Cuándo:** B2B-first, multi-storefront, pricing complejo
**Commerce.js / Swell.is** - Hosted-only, sin self-host - Setup rápido, pero vendor lock-in - **Cuándo:** PoC / MVP, catálogo pequeño
Para un retailer SK con 12 k SKU y 30 % de cuota B2B elegimos **Medusa.js v2** — hosting propio sobre Hetzner Cloud (CCX23, 4 vCPU + 16 GB RAM, 35 EUR / mes), PostgreSQL 16 en nodo separado, Redis para cache + queue.
Frontend: Next.js 16 con App Router
- ISR (Incremental Static Regeneration) para páginas de producto — revalidate cada 60 s
- Edge runtime para /api routes (Cloudflare Workers o Vercel Edge)
- Tailwind 4 + shadcn/ui para desarrollo de UI rápido
- Server Components para product detail (TTFB rápido), Client Components para cart / interactive elements
- Bundle size target: < 180 KB de JS enviado para la home
Servicios periféricos
| Función | Elección 2026 | Precio | |---------|---------------|--------| | Search | Algolia | 0,50 EUR / 1k search ops, ~180 EUR / mes para 12 k SKU + 400 k searches mensuales | | Payments | Stripe (Standard + Connect para B2B) | 1,4 % + 0,25 EUR por transacción UE, B2B Connect 0,5 % flat | | Email / Marketing | Klaviyo | 90 EUR / mes para 10 k perfiles | | Observability | Sentry + PostHog | Sentry 26 EUR / mes, PostHog 0 EUR (free tier hasta 1 M eventos) | | Image CDN | Cloudflare Images | 5 EUR / mes + 1 EUR / 100 k delivery | | DAM (Digital Asset Management) | Cloudinary o Imgproxy self-hosted | 90 EUR / mes o 15 EUR self-hosted | | Tax | Avalara AvaTax (SK + EU OSS) | 250 EUR / mes | | Shipping | Packeta API + Slovenská pošta API | 0 EUR (consumption-based) | | Reviews | Trustpilot Business | 200 EUR / mes |
OPEX total: ~750 EUR / mes (vs Shopify Advanced 280 EUR + Apps Shopify innecesarios 350 EUR = 630 EUR previamente).
Plan de migración — 4 meses, 6 fases
Mes 1: auditoría + preparación de datos
**Semana 1–2: catalog audit** - Export Shopify product CSV + Metafields export - Mapping del schema de producto de Shopify → schema de producto de Medusa (variants, options, prices, tax_rates) - Identificación de problemas de calidad de datos (SEO descriptions faltantes, duplicate handles, broken images) - 12 000 SKU se descompusieron en: 9 200 productos únicos × 1,3 variants de media = 12 100 product_variants en Medusa
**Semana 3: URL audit para 301 mapping** - Crawl de todas las URL de Shopify con Screaming Frog → 14 800 URLs únicas - Categorize: product pages (12 000), collection pages (240), CMS pages (45), pagination URLs (2 200), other (300) - Plan: mantener product handle (URL slug) → Medusa con el mismo handle → 0 redirects necesarios para 11 800 URL - Plan: collection pages mapping → la mayoría 1:1, pero las Shopify smart collections no se mapean directo a Medusa product categories → 80 mappings manuales - Pagination URLs (?page=2) → en Medusa misma estructura, naturalmente conservadas
**Semana 4: customer + order export** - 18 400 clientes con actividad en últimos 24 meses → import a Medusa - 47 000 pedidos históricos → migración a archive read-only en Medusa (innecesarios en sistema activo, pero necesarios para compliance legal + customer support) - Customer groups B2B + pricing tiers (Bronze/Silver/Gold) → Medusa customer_group + price_list
Mes 2: build de backend + integraciones
**Semana 5–6: setup Medusa + módulos custom** - Setup Hetzner Cloud, Coolify para orquestación Docker, GitHub Actions CI/CD - Módulos Medusa: product, order, customer, fulfillment, payment (Stripe), tax (plugin Avalara) - Módulos custom: - Tax handling específico SK (DPH 23 %, reducido 5 %, exento) - Invoicing específico SK (requiere IČO, DIČ, IČ DPH, fecha de emisión, fecha de entrega, vencimiento) - B2B quote request flow (workflow Medusa custom + admin UI)
**Semana 7–8: integraciones periféricas** - Algolia: index de products + variants, faceting (categoría, precio, marca, disponibilidad), synonyms (SK + CZ) - Klaviyo: webhook customer + order → eventos Klaviyo (cart_abandoned, ordered_product, etc.) - Avalara: webhook order_placed → cálculo AvaTax → almacenar tax breakdown en order - Sentry: error tracking backend + frontend, upload de source maps
Mes 3: build de frontend + continuidad SEO
**Semana 9–10: páginas core del storefront** - Setup Next.js 16, Tailwind 4, shadcn/ui - Home, Category, Product Detail, Cart, Checkout (multi-step), Account, Order History - ISR para Product + Category (revalidate 60 s) - Server Components por defecto, Client Components solo para cart/wishlist state
**Semana 11: SEO migration** - **Continuidad de sitemap:** el sitemap.xml de Next.js genera las mismas URL que Shopify, más URL nuevas si surgen - **301 redirect map:** /apps/customer-portal/* → /account/*, /collections/ → /c/* (cambiamos la estructura de URL de categorías) - **Structured data:** Product schema (price, availability, sku, brand, aggregateRating, review), Offer schema, BreadcrumbList, Organization - **Open Graph + Twitter Card:** og:image generado vía Next.js dynamic OG image route (1200×630, branding, hero del producto, precio) - **robots.txt + meta robots:** conservar noindex para /account/*, /cart, /checkout - **Canonical URLs:** canonical explícito en cada página de producto, motivo: Shopify lo usaba con parámetro ?variant=, Medusa lo hace con URL separada o client-side state, hace falta canonical sobre la URL base del producto
**Semana 12: cutover plan** - Plan de cutover DNS (TTL 60 s 24 h antes del cutover) - Database snapshot Shopify → Medusa import (último delta) - Cambio de webhook Stripe (Shopify Stripe → Medusa Stripe) - Cambio de webhook Klaviyo - Notificación a clientes: «el sábado noche de 02:00 a 04:00 el e-shop no estará disponible»
Mes 4: cutover + estabilización
**Semana 13: soft launch** - Subdominio shop-new.domain.sk → storefront Next.js + backend Medusa - 5 % del tráfico routed vía Cloudflare Workers split test - Sentry watch: cero errores nuevos durante 48 h - Monitoring Klaviyo: cart abandonment rate estable
**Semana 14: full cutover** - Cutover DNS (apex domain → new infra) - 301 redirect map desplegado en Cloudflare Workers (pre-DNS-cutover ya activo) - Shopify se queda en modo read-only durante 30 días (archive legal de pedidos pasados) - Monitorización de picos de tickets de customer support
**Semana 15: post-launch fix** - 12 horas de bug fixing en las primeras 72 h (nada crítico, pero 8 minor — edge cases de checkout, workflow B2B quote, algunos issues de synonyms en Algolia)
**Semana 16: performance tuning + SEO check** - Auditoría Lighthouse, target LCP < 1,5 s (logrado 1,1 s) - Search Console: indexing status check, ningún 404 nuevo, ningún rank drop > 5 % en top 50 keywords - A/B test new product detail page vs Shopify-style → +14 % de conversion rate
Lo que nos hizo daño (y qué haríamos diferente)
Lento: invoicing específico SK
**Plan:** 4 días de desarrollo para módulo de invoicing custom.
**Realidad:** 3 semanas.
El requisito legal eslovaco para una factura incluye 14 campos obligatorios (§ 74 ley de DPH), además el electronic invoicing para B2B por encima de 5 000 EUR tiene sus propios requirements EDI (E-faktúra Finančná správa). Además VAT OSS para ventas cross-border UE necesita per-transaction reporting al MyTaxOffice. Además rovers (`rožďanský faktúrový riadok formát`) para cash transactions tiene sus propios requerimientos.
**Lección:** estimar el overhead de compliance SK/EU en 3× el cálculo inicial. Ningún feature de compliance UE es «2-day implementation».
Rápido: Algolia sync
**Plan:** 5 días para Algolia integration + indexing.
**Realidad:** 2 días.
Medusa tiene plugin first-party Algolia (`@medusajs/algolia`) que emite eventos webhook (product.created, product.updated, product.deleted) → reindex Algolia. El setup fue configurar API keys + schema del índice. Real 2 días.
**Lección:** primero buscar plugin first-party / community. Si existe y tiene 1 k+ GitHub stars, no empiece integración custom.
Lento: B2B quote workflow
**Plan:** 1 semana.
**Realidad:** 3 semanas.
El cliente B2B quiere un «quote request» para pedidos superiores a 5 000 EUR. Workflow: 1. El cliente añade productos al carrito → click «Solicitar oferta» (en vez de «Añadir al carrito») 2. El quote aparece en el admin panel, el sales rep lo aprueba y, si procede, ajusta precio / shipping / payment terms 3. El cliente recibe email con enlace al quote → puede accept (crea order con condiciones a medida) o reject
Medusa v2 tiene el módulo `quote` en versión alpha en 2026, pero el workflow + UI los tuvimos que construir custom. Más admin permissions para distintos sales reps. Más email templates en SK.
**Lección:** los workflows B2B-specific en headless commerce son siempre custom. Saleor habría ahorrado quizá 1 semana aquí (tiene módulo de quote built-in en stable), pero la decisión Medusa estaba justificada por developer experience para el resto del stack.
Rápido: 301 redirect manteniendo SEO
**Plan:** 1 semana para 301 mapping + monitoring.
**Realidad:** 3 días.
Cifra: conservar el product handle (URL slug) de Shopify en Medusa. La URL de Shopify era `/products/produkt-handle`, Medusa con el mismo patrón. 11 800 de 14 800 URL quedaron idénticas — ningún redirect necesario.
Para el resto (collections, customer portal, algunas CMS pages) desplegamos un 301 map en Cloudflare Workers (`URL Rewrite Rules`) — 280 reglas explícitas + 12 regex patterns. **Cero URLs indexadas perdidas** en Search Console tras 60 días.
**Lección:** si puede conservar el patrón de URL, hágalo. Si tiene que cambiarlo, construya el redirect map *antes* del cutover, no después.
Checklist SEO — qué verificar antes del cutover
1. **Paridad de sitemap:** el sitemap.xml de Next.js debe contener todas las URL del sitemap original de Shopify. Diff mediante script `sitemap-diff` en CI. 2. **301 redirect map:** cada URL change no trivial indexada en `redirects.json`, validada contra load tests de producción. 3. **Canonical URLs:** canonical explícito en cada página, motivo: Shopify usaba query params (?variant=), el nuevo stack puede usar URLs path-based — canonical evita penalización por duplicate content. 4. **Continuidad de structured data:** Product schema (offers, availability, price, sku) en paridad con el Shopify original. Test con Google Rich Results Test antes del cutover. 5. **Open Graph migration:** og:image, og:title, og:description por página. Dynamic OG image generation vía Next.js dynamic route + edge runtime. 6. **robots.txt:** conservar noindex para admin, account, cart, checkout. Añadir directiva `Sitemap:`. 7. **Internal linking:** breadcrumbs, related products, category navigation. Crawl con Screaming Frog para confirmar que ninguna página queda huérfana. 8. **Core Web Vitals:** LCP, FID/INP, CLS target para top 50 landing pages. Lighthouse CI en deployment pipeline. 9. **Search Console reverification:** nueva property para la nueva infraestructura (si DNS no cambia no hace falta verification nueva, pero se recomienda URL property). 10. **Monitoring:** watch post-launch de 30 días para indexing status, cambios de ranking en top 100 keywords, delta de tráfico orgánico.
ROI cutoff — cuándo merece la pena migrar
Una migración headless de este alcance cuesta **40–80 k EUR** en costes de engineering (incluyendo internal time + external dev shop), más 4 meses de timeline.
**Retorno a 3 años:**
| Beneficio | Ahorro anual | |-----------|--------------| | Shopify Advanced + Apps savings | 4 200 EUR | | LCP improvement → +6 % conversion | 12 k SKU × 20 EUR AOV × 1,2 k orders/mes × 0,06 = ~17 280 EUR | | Eliminated Shopify Plus upgrade (would be next, 25 k+ USD / year) | 23 000 EUR | | Faster B2B quote handling | 12 000 EUR (1 FTE day × 24 meses) | | **Total 3-year savings** | **170 940 EUR** |
ROI: ~2,5 años con inversión de 60 k EUR.
**Para quién NO se devuelve:** - < 2 000 SKU, < 500 pedidos / mes → Shopify sigue siendo más barato - No tiene dev team o partner externo comprometido para mantenimiento a 3 años - La hoja de ruta no habla de B2B / multi-storefront / checkout custom
Consejo práctico
La migración no es «comprar Medusa, los programadores la hacen». Es un **proyecto business + tech + SEO + ops** a 3–6 meses. Los mayores fallos que hemos visto:
1. **Underestimated EU compliance.** SK invoicing, OSS VAT, GDPR — todo consume más tiempo del que prometen los PoC con datos de prueba. 2. **No 301 plan = lost rankings.** 90 días de pérdida en tráfico orgánico = 30–50 % de pérdida de facturación. Basta un cutover malo. 3. **No customer support runbook.** Cutover sin plan de incidentes 24/7 = vuelta en pánico a Shopify tras la primera crisis. 4. **Underestimated data migration.** 47 k pedidos históricos no son «CSV import de fin de semana».
---
*Hacemos migraciones headless commerce para catálogos de 2 k–50 k SKU, full-stack (Medusa.js / Saleor + Next.js + integraciones + continuidad SEO). Si está pensando en dejar Shopify o BigCommerce, el primer project assessment (workshop de 4 horas) recorre la decisión de stack, timeline, presupuesto y plan de 301 redirect para su catálogo concreto antes de comprometerse con la migración.*