Televisión con Productos en Escaparate con Shopify: Solución de 100€ para pequeños comercios
Cómo convertí una Smart TV de 100€ en un sistema de señalización digital dinámico integrado con Shopify, reduciendo costes en un 97% frente a soluciones comerciales.
Una tienda de ropa minorista necesitaba captar la atención del público local. Aprovechando su ubicación frente a una línea de bus bastante concurrida pensó en instalar una pantalla orientada al público. Las soluciones del mercado oscilaban entre 1.000€ y 4.000€, más costes de mantenimiento y actualización de contenido. Una inversión arriesgada.
Desarrollé una alternativa: usando una Smart TV de 100€ conectada directamente a Shopify y al sistema POS del establecimiento. El resultado fue una solución sincronizada con el inventario, sin trabajo manual adicional, y con un coste del 97% inferior a las alternativas comerciales.
El problema: soluciones caras para un pequeño negocio
Las soluciones comerciales de digital signage podían costar entre 1.000€ y 4.000€, además de requerir mantenimiento constante del contenido. Para una pequeña empresa, esta inversión era costosa, especialmente considerando que alguien tendría que dedicar tiempo semanalmente a actualizar productos, precios y promociones.
La tienda ya utilizaba Shopify tanto para ventas online como para el sistema POS en el local. La oportunidad era clara: si lográbamos conectar una pantalla directamente a Shopify, todo quedaría centralizado. Actualizar productos una sola vez y que se reflejara automáticamente en el escaparate, la web y el punto de venta.
Prueba de concepto: ¿Podríamos usar una Smart TV?
La idea era buena: ¿puede una Android TV mostrar una presentación de diapositivas en un navegador web, de forma estable? ¿Puede el contenido mostrarse en vertical imitando el scroll infinito al que hoy en día estamos enganchados en redes sociales?
Antes de invertir tiempo en el desarrollo de la aplicación, necesitaba validar la viabilidad técnica.
Si esta solución no funcionaba, había alternativas con distinto nivel de complejidad:
- Raspberry Pi u otro mini PC conectado por HDMI
- Desarrollar una aplicación nativa para Android
- Solución offline con contenido en USB (descartada por no ser dinámica)
Instalando un navegador en Android TV
El primer desafío técnico fue conseguir un navegador funcional. Chrome y Firefox no están disponibles en la Play Store para Android/Android TV, por lo que tuve que:
-
Instalar Chrome vía APK: Descargué la APK desde una fuente confiable en otro dispositvo Android y lo transferí usando FileTransfer que también está disponible en Android TV.
-
Conectar periféricos: La interfaz de Chrome en Android no está optimizada para control remoto. Para la configuración inicial conecté un teclado y ratón Bluetooth, aunque después de configurarlo el navegador funciona sin necesidad de estos periféricos.
-
Plug & Play: Configuré Chrome para abrir por defecto la URL donde se alojaría la apliación web. De este modo podríamos rescindir del uso de los periféricos las próximas veces.
Rotando la pantalla a modo vertical
Android TV no incluye una opción nativa para rotar la pantalla en su interfaz de configuración. Probé varias aplicaciones de la Play Store que prometían esta funcionalidad sin éxito. La solución definitiva vino mediante ADB (Android Debug Bridge).
El proceso fue:
- Habilitar las opciones de desarrollador en Android TV (tocando 7 veces el número de compilación en Ajustes > Acerca de)
- Activar la depuración USB
- Conectarme vía ADB remoto desde mi ordenador
- Ejecutar los comandos de rotación
El comando que funcionó finalmente fue:
adb shell settings put system user_rotation 3
Este comando fuerza la orientación vertical (portrait) independientemente del giroscopio del dispositivo. El valor user_rotation 1 corresponde a 90 grados, 2 serían 180 grados, y 3 sería 270 grados.
Nota importante: Esta configuración no persiste después de un reinicio. Para hacerla permanente sería necesario crear un script que se ejecute al inicio.
Desarrollando la interfaz en Shopify
En lugar de crear una aplicación separada o un backend personalizado, aproveché el sistema de plantillas Liquid de Shopify para crear un plugin en la propia web del establecimiento y así mostrarlo en la pantalla.
Arquitectura de la solución
La página desarrollada incluye:
Carga automática de datos: Consulta productos, precios, imágenes y colecciones directamente desde la base de datos de Shopify usando Liquid templates.
Panel de control integrado: El gerente puede marcar productos y colecciones como “destacados” desde el backoffice de Shopify en la onfiguración del plugin de la plantilla web. No necesita acceder a ningún sistema adicional.
Carrusel multimedia: El diseño alterna automáticamente entre:
- Productos destacados (con precio o sin precio)
- Colecciones destacadas
- Videos promocionales
- Imágenes de campañas (rebajas, Black Friday, etc.)
Implementación técnica
El núcleo del sistema es una combinación de Liquid para cargar datos (imágenes, vídeos) y JavaScript vanilla para la lógica de presentación.
A continuación mostraré dos fragmentos de código del plugin para el tema de Shopify. Omitiré la parte del código encargada de generar el configurador del plugin desde el backoffice pero podrás encontrar el código fuente completo del plugin en mi GitHub.
La plantilla Liquid se encarga de generar el HTML con todas las diapositivas.
<div
style="
position: relative;
"
>
{% if small_image %}
<div
style="
background: url('{{ small_image | img_url: 'master' }}') no-repeat center / contain;
height: 5rem;
width: 5rem;
position: absolute;
z-index: 100;
right: 0;
margin: 1rem;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* Added soft shadow */;
"
>
</div>
{% endif %}
<div class="slideshow">
{% if section.settings.video_1 %}
{{ section.settings.video_1 | video_tag:
muted: true,
class: 'slide',
style: 'object-fit: cover;'
}}
{% endif %}
{% if section.settings.image_1 %}
<div
class="slide"
style="background: url({{ section.settings.image_1 | img_url: 'master' }}) no-repeat center / cover;"
>
</div>
{% endif %}
{% comment %} Omito más diapositivas de imagen/vídeo {% endcomment %}
{% endif %}
{% comment %} Selected products {% endcomment %}
{% if selected_products %}
{% if selected_products_title != '' %}
{% render 'cover-display',
title: selected_products_title,
description: selected_products_description,
img: selected_products_image,
class_name: 'slide'
%}
{% endif %}
{% for product in selected_products %}
{%
render 'product-display' with product,
show_all_images: show_all_product_images,
show_price: show_price,
class_name: 'slide'
%}
{% endfor %}
{% endif %}
{% comment %} Omito más diapositivas de imagen/vídeo {% endcomment %}
{% comment %} Selected collections {% endcomment %}
{% if selected_collections %}
{% for collection in selected_collections %}
{% render 'cover-display',
title: collection.title,
description: collection.description,
img: collection.image,
class_name: 'slide'
%}
{% for product in collection.products %}
{%
render 'product-display' with product,
show_all_images: show_all_product_images,
show_price: show_price,
class_name: 'slide'
%}
{% endfor %}
{% endfor %}
{% endif %}
{% comment %} Omito más diapositivas de imagen/vídeo {% endcomment %}
</div>
</div>
El código JavaScript se encarga de generar las transiciones y coordinar las diapositivas así como iniciar y pausar los vídeos que puedan contener.
document.addEventListener('DOMContentLoaded', function() {
var header = document.querySelector('header');
var slideshow = document.querySelector('.slideshow');
slideshow.style.height = `${window.innerHeight - header.offsetHeight}px`;
const forSlideChildren = (slide, callback) => {
Array.from(slide.children)
.forEach(callback);
}
const forSlideAndChildren = callback => {
var slides = slideshow.querySelectorAll('.slide');
slides
.forEach(slide => {
Array.from(slide.children)
.forEach(child => callback(slide, child));
})
}
forSlideAndChildren((slide, child) => child.style.transition = '1s');
const nextSlide = () => {
forSlideAndChildren((slide, child) => child.style.opacity = '0');
slideshow.scroll({
top: slideshow.scrollTop+slideshow.offsetHeight,
behavior: "smooth",
})
}
const waitSlide = (slide, callback) => {
if (slide instanceof HTMLVideoElement) {
slide.play();
slide.addEventListener('ended', callback);
return;
}
setTimeout(callback, {{ default_slide_duration }}*1000);
}
slideshow.addEventListener('scrollend',
() => {
const slides = slideshow.querySelectorAll('.slide');
const firstChild = slides[0];
const currentSlide = slides[1];
slideshow.removeChild(firstChild);
slideshow.appendChild(firstChild);
forSlideChildren(
currentSlide,
child => child.style.opacity = '1'
);
waitSlide(currentSlide, nextSlide)
}
)
const slides = slideshow.querySelectorAll('.slide');
const firstSlide = slides[0];
waitSlide(firstSlide, nextSlide);
});
Los estilos utilizados por el HTML generado y el código JavaScript que los inyecta en función de la diapositiva.
.slideshow {
position: relative;
overflow: hidden;
width: 100%;
}
.slide {
position: relative;
width: 100%;
height: 100%;
}
.products {
display: flex;
flex-wrap: wrap;
}
.product {
flex: 1 0 21%;
margin: 1%;
text-align: center;
}
.product img {
max-width: 100%;
height: auto;
}
Consideraciones de seguridad y acceso
Inicialmente consideré añadir autenticación para proteger la página dentro de la web con el plugin. Sin embargo, reflexionando sobre el caso de uso, no era necesario: el contenido está diseñado para ser público, visible para cualquier persona frente al establecimiento. No aportaría ningún beneficio real.
La página es técnicamente pública dentro del dominio de Shopify, pero no está enlazada desde ningún menú ni es indexable por buscadores (configurado mediante robots.txt y meta tags noindex).
Resultados e impacto
El escaparate digital lleva operativo más de 6 meses con resultados consistentes:
Ahorro económico
- Inversión inicial: 100€ (Smart TV) vs 1.000-4.000€ (soluciones comerciales)
- Coste de mantenimiento mensual: 0€ vs 50-150€ (actualización de contenido en soluciones tradicionales)
- ROI: La inversión se recuperó en menos de 2 semanas considerando el tiempo ahorrado en actualización manual de carteles
Impacto operativo
- 0 horas semanales de mantenimiento activo (vs 2-3 horas con cartelería física o digital tradicional)
- Sincronización perfecta entre inventario online, tienda física y escaparate
- Flexibilidad total para campañas de última hora
Mejoras observadas en el negocio
El impacto más significativo ha sido en la captación de atención:
- Incremento notable del tráfico de entrada durante horarios de baja afluencia
- Clientes preguntando específicamente por productos que vieron en el escaparate
- Mayor efectividad en la comunicación de promociones temporales
- Capacidad de reaccionar rápidamente a tendencias (si un producto se hace viral, puede destacarse en minutos)
Aprendizajes y lecciones técnicas
Lo que funcionó excepcionalmente bien
Integración con sistemas existentes: La decisión de construir sobre Shopify en lugar de crear un sistema separado fue acertada. Cero fricción en la adopción porque el equipo ya conocía la plataforma.
Tecnología accesible y suficiente: No necesitas hardware empresarial para soluciones profesionales. Una Smart TV de gama media es más que suficiente para un pequeño negocio.
Diseño iterativo: Empecé con una versión mínima (solo productos con precio) y fui añadiendo características (vídeos, colecciones, transiciones animadas) según las necesidades reales del negocio.
Desafíos y limitaciones encontradas
Estabilidad del hardware: La Smart TV ocasionalmente requiere un reinicio manual (aproximadamente 1-2 veces al mes), generalmente después de actualizaciones automáticas del sistema operativo.
Navegadores no nativos: Chrome no está diseñado para usarse en Android TV por lo que es necesario conectar periféricos para la configuración inicial.
Persistencia de configuración: La rotación de pantalla mediante ADB no persiste después de reinicios completos del sistema. Cada vez que la TV se apaga completamente (no en standby), hay que volver a ejecutar el comando.
Mejoras futuras planificadas
Aunque la solución actual cumple las necesidades del establecimiento, planteo las siguientes mejoras que aportarían más valor al producto:
Actualizaciones automáticas: Actualizar las diapositivas de la página instantáneamente después de realizar cambios en el backoffice (Polling, Server Sent Events, Web Sockets…, refrescar en horarios poco concurridos).
Contenido intelgiente: Mostrar contenido diferente según la hora del día, el tiempo (productos de oficina por la mañana, ropa de lluvia los días nublados).
Ocultar barra de búsqueda: Implementar una funcionalidad de pantalla completa. Actualmente los navegadores en Android no tienen una opción de ocultar la barra de búsqueda la cual quita espacio en pantalla y muestra al público información que no es relevante.
Conclusión
Este proyecto demuestra un principio fundamental del desarrollo: las soluciones efectivas no siempre requieren grandes presupuestos ni tecnología compleja. Con creatividad, aprovechamiento de herramientas existentes y un enfoque en resolver el problema real, es posible crear experiencias digitales profesionales a una fracción del coste de productos comerciales.
La clave estuvo en:
- Validar antes de construir: Confirmar la viabilidad técnica antes de invertir tiempo en desarrollo
- Reutilizar infraestructura: Aprovechar Shopify evitó crear y mantener un sistema paralelo
- Empezar simple: MVP funcional en 2 días, mejoras iterativas después
- Pensar en el usuario final: Cero curva de aprendizaje para el equipo de la tienda
Si estás considerando implementar algo similar, mi recomendación es empezar con una prueba de concepto. Los componentes básicos son económicos y el riesgo es mínimo. Si funciona, tendrás una solución escalable y mantenible. Si no, habrás aprendido mucho en el proceso.

¿Has implementado soluciones similares de digital signage? ¿Tienes un negocio retail que podría beneficiarse de esto?
Me encantaría conocer tu caso y ayudarte a adaptarlo. Encuéntrame en LinkedIn o escríbeme a mi correo electrónico.