Saltar al contenido principal

Referencia de Liquid

Joryio personaliza mensajes con Liquid: escribes marcadores como {{ user.firstName }} y filtros como {{ price | currency }}, que se resuelven por destinatario al enviar. Esta página es la referencia completa de todos los espacios de nombres de variables y filtros personalizados de Joryio, con ejemplos.

¿Es tu primera vez con Liquid en Joryio? Empieza con Plantillas Liquid para conocer lo básico y vuelve aquí cuando necesites más detalle.

Todos los filtros de abajo están registrados en un único motor Liquid compartido que usa cada ruta de renderizado. Por eso, la misma plantilla se renderiza de forma idéntica en email, SMS, WhatsApp, Push, in-app y webhook, tanto en campañas y recorridos como en las vistas previas. Lo que ves en la vista previa es lo que envía cada canal.

Conviene conocer dos comportamientos tolerantes predeterminados:

  • Una variable sin valor se renderiza como texto vacío, nunca como error.
  • Un filtro desconocido devuelve el valor sin modificarlo en vez de fallar.

Variables​

Los espacios de nombres disponibles, de un vistazo. Sigue los enlaces para ver todos los detalles de cada uno.

Espacio de nombresContenidoDetalles
user.firstName, user.lastName, user.email, user.phone, user.id, user.externalId, user.whatsappNameAtributos predeterminados del contactoVariables de mensaje
user.custom.<attribute>Cualquier atributo personalizado del contacto - por ejemplo, user.custom.planVariables de mensaje
trigger.properties.<field>Cómo entró al recorrido: el evento de entrada, fijo durante toda la ejecuciónVariables de mensaje
event.properties.<field>, event.nameLo último que hizo: el evento más reciente que hizo avanzar el recorridoVariables de mensaje
reply.text, reply.type, reply.profile.nameAlias intuitivos para la última respuesta entrante de WhatsApp o SMS del contactoVariables de mensaje
blocks.<slug>Un bloque de contenido reutilizable, renderizado en líneaBloques de contenido
unsubscribe_url, preferences_url, resubscribe_urlEnlaces de suscripción por destinatario - email, SMS y sesión de WhatsAppPlantillas Liquid
cart.items, cart.value, cart.subtotal, cart.currency, cart.checkoutUrlEl carrito de la tienda sincronizado del contacto - artículos con name, quantity, price, total, imageUrl, url, sku value es el total que envió la tienda (puede incluir el envío); subtotal es el subtotal de los artículos, antes de envío e impuestos.Productos
last_order.items, last_order.total, last_order.currency, last_order.placedAt, last_order.orderUrlSu pedido más reciente que no fue cancelado ni reembolsado - los mismos campos de artículo que el carritoProductos
top_productsLos productos que más piden - hasta 5 con name, sku, imageUrl, url, timesOrdered, lastOrderedAt, el más frecuente primeroProductos
Filtros products y entityRegistros de catálogo de productos o entidad personalizada de una selección guardadaFuentes de catálogo, abajo

trigger.*, event.* y reply.* solo se resuelven dentro de un recorrido; el resto funciona en todas partes.

cart, last_order y top_products están vacíos para un contacto sin pedidos en la tienda - envuélvelos en {% if %}.

Filtros​

Encadena filtros con | y pasa argumentos después de :. Por ejemplo:

{{ user.firstName | capitalize | default: "there" }}
{{ order.total | currency: "EUR" }}

Texto​

FiltroFunciónEjemplo → Resultado
capitalizeConvierte en mayúscula la primera letra y en minúscula el resto{{ "mAYA" | capitalize }} → Maya
uppercaseConvierte toda la cadena en mayúsculas{{ "sale" | uppercase }} → SALE
lowercaseConvierte toda la cadena en minúsculas{{ "SALE" | lowercase }} → sale
truncateCorta una cadena a una longitud - 50 de forma predeterminada - y añade un sufijo - ... por defecto. El sufijo se añade después del corte, además de la longitud{{ "The quick brown fox jumps" | truncate: 9 }} → The quick...
strip_htmlElimina etiquetas HTML{{ "<b>Sale</b> today" | strip_html }} → Sale today
url_encodeCodifica una cadena para URL - para crear enlaces{{ "red shoes" | url_encode }} → red%20shoes
pluralizeDado un número, devuelve la palabra singular o plural. El plural es singular + s de forma predeterminada; pasa un tercer argumento para plurales irregulares3 {{ 3 | pluralize: "item" }} → 3 items
defaultValor de reserva cuando el valor es null, no está definido o es una cadena vacía{{ user.firstName | default: "there" }} → there - cuando está vacío
landing_page_urlUn enlace a una página de destino publicada por su slug. Lleva el token del destinatario, así que la página sabe quién llegó; un argumento opcional añade una cadena de consulta. El enlace se construye siempre; un slug no publicado (o inexistente) responde 404 en la redirección. Vacío solo cuando el slug está mal formado o el renderizado no tiene espacio de trabajo{{ "spring-sale" | landing_page_url: "utm_campaign=spring" }} → https://api-eu1.joryio.com/api/p/go/<workspace>/spring-sale?jp=…&utm_campaign=spring

Números y moneda​

FiltroFunciónEjemplo → Resultado
currencyFormatea un número como importe. El código de moneda es USD de forma predeterminada; pasa cualquier código ISO. Usa formato en-US - símbolo primero y miles con coma{{ 1249.5 | currency }} → $1,249.50 · {{ order.total | currency: "EUR" }} → €49.90

Fechas​

FiltroFunciónEjemplo → Resultado
date_formatFormatea una fecha. Estilos: short - predeterminado, long y full. Un estilo desconocido usa short. Los nombres de meses y días están en inglés - en-US. Formatea en la zona horaria del espacio de trabajo, igual en la vista previa que en el envío; un valor solo de fecha, como un cumpleaños (1990-05-01), nunca se desplaza. También acepta un patrón strftime ("%d %b %H:%M"), y un segundo argumento opcional indica otra zona IANA - una zona desconocida vuelve a la zona del espacio de trabajo{{ order.createdAt | date_format }} → Jul 12, 2026 · {{ order.createdAt | date_format: "long" }} → July 12, 2026 · "full" → Sunday, July 12, 2026 · {{ order.createdAt | date_format: "%d %b %H:%M", "America/New_York" }} → 12 Jul 05:30
add_daysAñade N días a una fecha - un número negativo los resta. Devuelve una marca de tiempo ISO; encadena date_format para hacerla legible{{ order.createdAt | add_days: 7 | date_format }} → Jul 19, 2026
time_agoTiempo relativo fácil de entender - granularidad de año, mes, semana, día, hora, minuto y segundo{{ user.custom.lastOrderAt | time_ago }} → 3 days ago

Las fechas y horas del contenido de los mensajes se muestran en la zona horaria del espacio de trabajo, la misma que usa el resto de la aplicación. Se aplica a date_format y al filtro estándar date ({{ order.createdAt | date: "%H:%M" }}); pasa una zona como último argumento para usar otra.

Matrices​

FiltroFunciónEjemplo → Resultado
joinUne los elementos de una matriz en una cadena. El separador predeterminado es , {{ names | join }} → Ana, Ben, Gal · {{ names | join: " / " }} → Ana / Ben / Gal
mapExtrae una propiedad de cada elemento y devuelve una matriz nueva{{ items | map: "name" | join }} → Mug, Tee
firstEl primer elemento{{ items | first }}
lastEl último elemento{{ items | last }}
sizeLongitud de una matriz o cadena - 0 para cualquier otro valor{{ cart.items | size }} → 3
countNúmero de elementos de una matriz - 0 si no es una matriz{{ cart.items | count }} → 3

Agregados y filtrado​

Estos funcionan con matrices de registros - artículos del carrito, pedidos o selecciones de catálogo. Cada argumento field admite rutas de puntos en objetos anidados - por ejemplo, "price.amount".

FiltroFunciónEjemplo → Resultado
sumSuma un campo numérico de toda la matriz - los valores ausentes cuentan como 0{{ orders | sum: "totalAmount" }} → 540
avgCalcula la media de un campo numérico - 0 para una matriz vacía{{ orders | avg: "totalAmount" }} → 180
maxValor numérico mayor de un campo - ignora valores no numéricos; 0 si no hay ninguno{{ products | max: "price" }} → 129.9
minValor numérico menor de un campo{{ products | min: "price" }} → 19.9
whereFiltra la matriz. Tres formas: where: "featured" conserva elementos verdaderos; where: "category", "shoes" conserva elementos iguales; where: "price", "gt", 100 compara con un operador: eq, neq, gt, gte, lt, lte, contains, in. También funcionan las formas simbólicas ==, !=, >, >=, <, <={{ items | where: "category", "shoes" | count }} → 2
sortOrdena por un campo, en orden asc - predeterminado - o desc. Sin campo, ordena los valores mismos{{ products | sort: "price", "desc" | first }} → el producto más caro

Ejemplo desarrollado: los tres pedidos más recientes del destinatario:

{% assign recent = orders | sort: 'createdAt', 'desc' %}
{% for order in recent limit: 3 %}
- {{ order.createdAt | date_format }}: {{ order.totalAmount | currency }}
{% endfor %}
Gasto total: {{ orders | sum: 'totalAmount' | currency }}

Fuentes de catálogo​

Dos filtros incorporan colecciones de registros a un mensaje, cada uno respaldado por una selección guardada del espacio de trabajo. Ambos devuelven una matriz: úsalos en una etiqueta assign y después recórrela.

products: catálogo de productos de la tienda​

Extrae del catálogo de productos sincronizado - Shopify / WooCommerce / Magento - mediante una selección de productos. Hay un único catálogo, por lo que el argumento es el nombre de la selección:

{% assign products = 'featured' | products %}
{% for item in products %}
- {{ item.name }}: {{ item.price | currency }}
{% endfor %}

entity: fuente de entidad personalizada​

Extrae registros de una entidad personalizada. El primer argumento es el nombre de entidad y el segundo - opcional - es el nombre de selección:

{% assign episodes = 'tv_series' | entity: 'latest' %}
{% for item in episodes %}
- {{ item.name }}
{% endfor %}

Puedes pasar variables a una selección de entidad parametrizada; por ejemplo, proporcionarle el evento de entrada del recorrido:

{% assign items = 'products' | entity: 'product_by_id', trigger %}

Notas sobre su comportamiento:

  • Las selecciones que son iguales para todos los destinatarios - sin filtros de atributos de usuario ni contexto - se almacenan en caché - unos 5 minutos en la vista previa del editor, alrededor de un minuto en un envío -; así, los envíos masivos no vuelven a consultar por destinatario. Las selecciones de entidad personalizadas se evalúan de nuevo para cada destinatario.
  • Si no se encuentra la selección de entidad o producto - o falla la consulta, el filtro devuelve una matriz vacía. El bucle for simplemente no renderiza nada; nunca genera un error.
  • Los tres filtros (products, entity y el alias catalog) se ejecutan en todas las rutas de renderizado con los mismos nombres: la vista previa del editor, los envíos de campañas, los envíos de recorridos y todos los workers de canal. Lo que muestra la vista previa es lo que recibe el destinatario.
  • Las opciones Catálogo de productos y Entidad personalizada del selector de personalización crean el fragmento assign por ti. Consulta Variables de mensaje.
En desuso: catalog

El antiguo filtro catalog es un alias en desuso de entity y sigue funcionando, por lo que las plantillas existentes no se rompen. En adelante, usa entity para entidades personalizadas y products para el catálogo de la tienda.

Recomendaciones​

recommendations.<slot> es una lista de productos recomendados para el destinatario, a partir de un modelo de recomendación. El slot es el nombre del modelo como clave (For you pasa a ser for_you); recommendations.default es el modelo predeterminado del espacio de trabajo. Cada artículo tiene name, price (con formato), compareAtPrice, discountPercent, url, image, description e id. Funciona en todos los canales - email (campañas y recorridos), SMS, WhatsApp, Viber, push, in-app y landing pages - y también en las vistas previas del editor y los envíos de prueba:

{% for item in recommendations.for_you limit: 3 %}
{{ item.name }} - {{ item.price }} {{ item.url }}
{% endfor %}

Consulta Slots de Liquid para el nombre de los slots y los campos de cada artículo, y la lista de bloqueo para los productos que nunca se recomiendan.

En qué se diferencia Joryio de Liquid estándar​

Algunos filtros se comportan intencionalmente de forma distinta a sus equivalentes de Shopify/LiquidJS:

  • capitalize también convierte en minúsculas el resto de la cadena: "mAYA" pasa a ser Maya, no MAYA.
  • default trata una cadena vacía como ausente, por lo que {{ user.firstName | default: "there" }} usa el valor de reserva incluso si el atributo existe, pero está vacío.
  • truncate añade el sufijo después de la longitud de corte; Liquid estándar cuenta los puntos suspensivos dentro de la longitud.
  • where y sort son superconjuntos de los integrados: aceptan las formas de llamada estándar y añaden operadores de comparación, dirección de ordenación y campos de ruta de puntos.

Liquid estándar también funciona​

Todo lo anterior se añade a LiquidJS estándar. Las etiquetas integradas - {% if %} / {% elsif %} / {% else %}, {% for %}, {% assign %}, {% case %} y otras - y los filtros integrados - upcase, downcase, date, replace, split, plus, times y muchos más - funcionan en cualquier plantilla de Joryio. Cuando un filtro de Joryio comparte nombre con uno integrado - capitalize, default, where, sort, join, map, first, last, size - se ejecuta la versión de Joryio descrita en esta página. Consulta la lista completa de filtros integrados en liquidjs.com/filters/overview.html.

Contenido relacionado​