¡Dale vida a tu tienda!: Añade una sección con productos aleatorios a tu tema en Shopify

En el mundo del ecommerce, mantener la frescura y la novedad en tu tienda puede ser un desafío, pero es esencial para captar y mantener la atención de tus clientes. Hoy te traigo una estrategia sencilla pero efectiva para dinamizar tu tienda Shopify: mostrar una sección con productos escogidos aleatoriamente de una coleccción.

En nuestra tienda (Fun At Home: tienda online de manualidades, kits de arte, juguetes didácticos, pinturas por número y diamond painting) queríamos mostrar una sección de novedades, con 8 productos, pero el problema es que a veces tenemos más de 8 productos para mostrar, por lo que busqué una forma de ordenar aleatoriamente los productos de la colección y mostrar los primeros 8, de modo que los visitantes vayan viendo nuevas novedades si ingresan varias veces al sitio (además tiene un beneficio en términos de SEO ya que tu sitio se ve actualizado y no estático).

El problema fue que no encontré ninguna forma de hacerlo, sólo entrar a pagar por algún plugin que ofreciera esta funcionalidad.

La solución

No es tan sencillo lograr elegir un subconjunto de productos aleatorios de una colección, por restricciones de Shopify y de liquid, el lenguaje de programación que Shopify utiliza, pero luego de darle muchas vueltas, logré encontrar una solución simple que cumple con el objetivo, aunque no es exactamente "elegir 8 productos de forma aleatoria de la colección", sino elegir "un punto de partida aleatorio y mostrar 8 productos". Lo importante cumple con todos los objetivos que estaba buscando y probablemente lo de ustedes si llegaron a este post.

Veamos el paso a paso:

1. Determina el Punto de Inicio:

Primero, vamos a calcular un índice de inicio aleatorio. Esto se basa en el tiempo actual para asegurar que la selección de productos varíe con cada visita:

{% assign total_products = collection.products.size %}
{% assign max_start = total_products | minus: 8 %} <!-- Asumiendo que quieres mostrar 8 productos -->
{% assign start_index = "now" | date: "%S" | modulo: max_start %}
  1. Muestra los productos:

Luego, iteramos sobre los productos de la colección y comenzamos a mostrarlos solo cuando alcanzamos el punto de inicio aleatorio:

{% assign products_shown = 0 %}
{% for product in collection.products %}
  {% if forloop.index0 >= start_index %}
    <!-- Inserta tu código de visualización de productos aquí -->
    {% assign products_shown = products_shown | plus: 1 %}
    {% if products_shown >= 8 %}{% break %}{% endif %}
  {% endif %}
{% endfor %}

De esta forma lo que haces es saltar productos hasta llegar a un puntos de inicio seleccionado de manera aleatoria, para luego mostrar el número de productos que quieres mostrar (en el ejemplo 8).

Un detalle importante es que el punto de inicio puede ser desde el primer producto hasta el total de productos - productos a mostrar, (por ejemplo si la colección tiene 100 productos y vamos a mostrar 8, elegimos un punto de partida entre el 1 el 92, para asegurar tener siempre a lo menos 8 productos para mostrar).

Ten en cuenta que debes adaptar este código a tu tema, a modo de ejemplo, muestro como tenemos implementado esto en Fun At Home, donde tenemos instalado el tema wookie (aprovecho de dejarte el link), les dejo el bloque completo tal como está funcionando hoy:

Primero el código original de la sección "Products Masonry":

{%- assign slider_mode = true -%}
{%- assign item = section.settings -%}

{%- assign name_collection = item.collection -%}
{%- if name_collection == blank -%}{%- assign name_collection = "all" -%}{%- endif -%}
{%- assign collection = collections[name_collection] -%}
{%- assign length = item.limit | plus: 0 -%}

<div class="{% if item.top_offset == 'none' %}nomargin {% elsif item.top_offset == 'small' %}tt-offset-small {% endif %}container-indent">
  <div class="container{% if item.fullwidth %}-fluid{% endif %}" data-sectionname="index_sectionmasonry_products">
    {% if item.show_title %}<div class="tt-block-title">
      <h2 class="tt-title">{{ item.text1 }}</h2>
      {% unless item.text2 == '' %}<div class="tt-description">{{ item.text2 }}</div>{% endunless %}
      {% unless item.default_carousel %}{% unless item.text3 == '' %}<p>{{ item.text3 }}</p>{% endunless %}{% endunless %}
    </div>{% endif %}
    <div class="tt-product-listing-masonry">
      <div class="tt-product-index-init tt-add-item">
        {%- for product in collection.products limit: length -%}
        {%- if item.doblesize -%}
        {%- capture masonrydoublesize -%}{%- cycle = '', '', 'double-size', '', '', 'double-size', '', '', '', '' -%}{%- endcapture -%}
        {%- capture external_size -%}{%- cycle = '500x', '500x', '1024x', '500x', '500x', '1024x', '500x', '500x', '500x', '500x' -%}{%- endcapture -%}
        {%- else -%}{%- assign external_size = '500x' -%}
        {%- endif -%}
        
        {%- unless settings.products_design == 'hidden' -%}<div class="element-item {{ masonrydoublesize }}">{%- endunless -%}
          {%- include "product-grid-item" -%}
        {%- unless settings.products_design == 'hidden' -%}</div>{%- endunless -%}
        {%- endfor -%}
      </div>
    </div>
  </div>
</div>


{% schema %}
{
  "name": "Products Masonry",
  "class": "index-section",
  "settings": [
      {
        "type": "select",
        "id": "top_offset",
        "label": "Top Offset",
        "default": "normal",
        "options": [
          {
            "value": "none",
            "label": "None"
          },
          {
            "value": "small",
            "label": "Small"
          },
          {
            "value": "normal",
            "label": "Normal"
          }
        ]
      },
      {
        "type": "checkbox",
        "id": "fullwidth",
        "label": "Fullwidth size",
        "default": true
      },
      {
        "type": "checkbox",
        "id": "show_title",
        "label": "Show Title Block",
        "default": true
      },
      {
        "type": "textarea",
        "id": "text1",
        "label": "Title",
        "default": "TRENDING"
      },
      {
        "type": "textarea",
        "id": "text2",
        "label": "Small description",
        "default": "TOP VIEW IN THIS WEEK",
        "info": "If you want delete text from the screen clear field"
      },
      {
        "type": "textarea",
        "id": "text3",
        "label": "Big description",
        "info": "If you want delete text from the screen clear field. Field not work with slider mode"
      },
      {
        "type": "header",
        "content": "Products settings"
      },
      {
        "label": "Collection",
        "id": "collection",
        "type": "collection"
      },
      {
        "type": "checkbox",
        "id": "doblesize",
        "label": "Double size",
        "default": true
      },
      {
        "type": "text",
        "id": "limit",
        "label": "Items Length. Integer",
        "default": "10"
      }
  ],
  "presets": [
    {
      "name": "Products Masonry",
      "category": "Lookbook"
    }
  ]
}
{% endschema %}

Y ahora les dejo el código modificado:

{%- assign slider_mode = true -%}
{%- assign item = section.settings -%}

{%- assign name_collection = item.collection -%}
{%- if name_collection == blank -%}{%- assign name_collection = "all" -%}{%- endif -%}
{%- assign collection = collections[name_collection] -%}
{%- assign length = item.limit | plus: 0 -%}

<div class="{% if item.top_offset == 'none' %}nomargin {% elsif item.top_offset == 'small' %}tt-offset-small {% endif %}container-indent">
  <div class="container{% if item.fullwidth %}-fluid{% endif %}" data-sectionname="index_sectionmasonry_products">
    {% if item.show_title %}<div class="tt-block-title">
      <h2 class="tt-title">{{ item.text1 }}</h2>
      {% unless item.text2 == '' %}<div class="tt-description">{{ item.text2 }}</div>{% endunless %}
      {% unless item.default_carousel %}{% unless item.text3 == '' %}<p>{{ item.text3 }}</p>{% endunless %}{% endunless %}
    </div>{% endif %}
    <div class="tt-product-listing-masonry">
<div class="tt-product-index-init tt-add-item">
  {% assign total_products = collection.products.size %}
  {% assign max_start = total_products | minus: length %}
  {% assign start_index = "now" | date: "%S" | modulo: max_start %}
  {% assign products_shown = 0 %}

  {% for product in collection.products %}
    {% if forloop.index0 >= start_index %}
      {%- if item.doblesize -%}
        {%- capture masonrydoublesize -%}{%- cycle '', '', 'double-size', '', '', 'double-size', '', '', '', '' -%}{%- endcapture -%}
        {%- capture external_size -%}{%- cycle '500x', '500x', '1024x', '500x', '500x', '1024x', '500x', '500x', '500x', '500x' -%}{%- endcapture -%}
      {%- else -%}
        {%- assign external_size = '500x' -%}
      {%- endif -%}

      {%- unless settings.products_design == 'hidden' -%}
        <div class="element-item {{ masonrydoublesize }}">
          {% include "product-grid-item", product: product, image_size: external_size %}
        </div>
      {%- endunless -%}

      {% assign products_shown = products_shown | plus: 1 %}
      {% if products_shown >= length %}{% break %}{% endif %}
    {% endif %}
  {% endfor %}
</div>
    </div>
  </div>
</div>


{% schema %}
{
  "name": "Random Products Masonry",
  "class": "index-section",
  "settings": [
      {
        "type": "select",
        "id": "top_offset",
        "label": "Top Offset",
        "default": "normal",
        "options": [
          {
            "value": "none",
            "label": "None"
          },
          {
            "value": "small",
            "label": "Small"
          },
          {
            "value": "normal",
            "label": "Normal"
          }
        ]
      },
      {
        "type": "checkbox",
        "id": "fullwidth",
        "label": "Fullwidth size",
        "default": true
      },
      {
        "type": "checkbox",
        "id": "show_title",
        "label": "Show Title Block",
        "default": true
      },
      {
        "type": "textarea",
        "id": "text1",
        "label": "Title",
        "default": "TRENDING"
      },
      {
        "type": "textarea",
        "id": "text2",
        "label": "Small description",
        "default": "TOP VIEW IN THIS WEEK",
        "info": "If you want delete text from the screen clear field"
      },
      {
        "type": "textarea",
        "id": "text3",
        "label": "Big description",
        "info": "If you want delete text from the screen clear field. Field not work with slider mode"
      },
      {
        "type": "header",
        "content": "Products settings"
      },
      {
        "label": "Collection",
        "id": "collection",
        "type": "collection"
      },
      {
        "type": "checkbox",
        "id": "doblesize",
        "label": "Double size",
        "default": true
      },
      {
        "type": "text",
        "id": "limit",
        "label": "Items Length. Integer",
        "default": "10"
      }
  ],
  "presets": [
    {
      "name": "Random Products Masonry",
      "category": "Lookbook"
    }
  ]
}
{% endschema %}

La única diferencia entre estos códigos está al interior del div `<div class="tt-product-index-init tt-add-item>` con el código que compartimos al inicio de este post.

Beneficios y consideranciones importantes

Esta técnica no solo añade dinamismo a tu tienda, sino que también es fácil de implementar y no requiere herramientas externas. Sin embargo, ten en cuenta que debido al caché de Shopify, los productos no cambiarán con cada carga de página, pero sí varias veces a lo largo del día, ofreciendo una experiencia nueva a los visitantes regulares.

Incorporar una sección de productos aleatorios en tu tienda Shopify es una excelente manera de mantener tu sitio fresco y atractivo. Sigue esta guía paso a paso y observa cómo mejora la experiencia de tus clientes.

IMPORTANTE: todo el contenido de Mente Digital es gratuito, en algunos post podrás encontrar enlaces auspiciados a plataformas, estos nos sirven para pagar los costos de mantenimiento del sitio pero no influyen en nada en las opiniones que emitimos ni en las recomendaciones que realizamos.