Introducción
Define campos personalizados para tu contenido sin tocar el código.
Más información sobre la interfaz de usuario del módulo https://doc.oneentry.cloud/docs/category/attributes
🎯 ¿Qué hace este módulo?
El módulo AttributesSets te permite leer las definiciones de campos personalizados (conjuntos de atributos) utilizados por tu contenido: productos, páginas, formularios, bloques y más. Un conjunto de atributos es el esquema que describe qué campos tiene una entidad y qué tipo es cada campo; los defines en el panel de administración de OneEntry y obtienes su estructura con este módulo.
Nota: los conjuntos de atributos describen el esquema, no los valores. Los valores reales residen en las propias entidades (una página, un producto, etc.) bajo sus
attributeValues. La única excepción es el tipotimeInterval, que puede llevar valores; consulta los ejemplos a continuación.
🚀 Inicio Rápido
Inicializa el módulo desde defineOneEntry:
const { AttributesSets } = defineOneEntry( "your-project-url", { "token": "your-app-token" });
Obtén los atributos definidos en un conjunto y lee sus marcadores y tipos:
// Get every attribute in the "productAttributes" set.
const attributes = await AttributesSets.getAttributesByMarker(
"productAttributes",
"en_US",
);
attributes.forEach((attr) => {
console.log(attr.marker, attr.type, attr.localizeInfos.title);
});
✨ Conceptos Clave
Atributo, Conjunto de Atributos, Valor
| Término | Qué Es | Ejemplo |
|---|---|---|
| Atributo | Una definición de campo único (un marcador + un tipo) | precio (float) |
| Conjunto de Atributos | Una colección de atributos - el esquema de la entidad | conjunto "Producto" |
| Valor | Los datos que una entidad almacena para un atributo | 19.99 en un producto específico |
Un conjunto de atributos agrupa atributos en un esquema reutilizable. El mismo conjunto puede estar adjunto a múltiples entidades, por lo que cambiar el conjunto cambia los campos disponibles en todas partes donde se utiliza.
Marcadores
El marcador es el identificador técnico que usas en el código (por ejemplo, product_name). Se mapea al título legible por humanos que se muestra en el panel de administración.
product.attributeValues.product_name; // "product_name" is the marker
Reglas de Marcador:
- Debe ser único
- Sin espacios (usa
_) - No puede comenzar con un número
- Usa minúsculas para consistencia
✅ Bueno: product_name, price_usd, main_image — ❌ Malo: product name, 2nd_price, Product Name
📋 Lo Que Necesitas Saber
Conjuntos de atributos compartidos
Si un conjunto de atributos es utilizado por múltiples entidades, los cambios se propagan a todas ellas:
- Agregar un atributo - aparece en cada entidad que utiliza el conjunto; el contenido existente mantiene sus valores y el nuevo campo comienza vacío.
- Eliminar un atributo - se elimina de cada entidad que utiliza el conjunto, y los valores existentes se eliminan permanentemente.
No puedes eliminar un atributo mientras aún se utiliza en un conjunto de atributos.
Validadores
Los atributos pueden llevar validadores para hacer cumplir la calidad de los datos: campos requeridos, longitud mínima/máxima, límites de tamaño de archivo, dimensiones de píxeles de imagen, rangos de fechas y un valor predeterminado. La configuración del validador se devuelve en cada atributo bajo validators.
Haz clic para ver ejemplos de validadores
- requiredValidator: requiere que se ingrese un valor.
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "Currency"
},
"additionalFields": {
"extra": {
"type": "integer",
"value": "10",
"marker": "extra"
}
}
}
- defaultValueValidator: proporciona un valor predeterminado para el campo.
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"defaultValueValidator": {
"customErrorText": "Custom error",
"fieldDefaultValue": "usd",
"fieldDefaultValue2": ""
}
},
"localizeInfos": {
"title": "String"
},
"additionalFields": {
"extra": {
"type": "integer",
"value": "10",
"marker": "extra"
}
}
}
Aprende más: Consulta Validadores para una configuración detallada.
Atributos anidados
Puedes adjuntar campos adicionales a un atributo a través de Campos Adicionales (devueltos bajo additionalFields).
📊 Tabla de Referencia Rápida - Métodos Comunes
| Método | Qué Hace |
|---|---|
| getAttributes() | Obtiene todos los objetos de conjunto de atributos. |
| getAttributesByMarker() | Obtiene todos los atributos de un conjunto, con datos del conjunto de atributos. |
| getAttributeSetByMarker() | Obtiene un solo objeto de conjunto de atributos por marcador. |
| getSingleAttributeByMarkerSet() | Obtiene un atributo (con datos del conjunto) por marcador de conjunto y marcador de atributo. |
📚 Tipos de Datos Disponibles
Cada atributo tiene un type. Elige el tipo correcto para cada campo.
| Tipo | Mejor Para | Ejemplo de Uso |
|---|---|---|
| string | Texto corto (< 255 caracteres) | Nombre del producto, correo electrónico |
| text | Texto largo formateado | Publicación de blog, descripción |
| textWithHeader | Texto con un título | Secciones de artículo |
| integer | Números enteros | Cantidad, edad |
| real | Decimales de alta precisión | Datos científicos |
| float | Números decimales | Precio, calificación |
| date | Solo la fecha | Fecha de nacimiento, fecha límite |
| dateTime | Fecha + hora | Inicio del evento, publicado en |
| time | Solo la hora | Horarios de apertura |
| file | Cualquier archivo | PDF, documento |
| image | Imagen única | Avatar, logo |
| groupOfImages | Múltiples imágenes | Galería de fotos |
| radioButton | Opción única | Tamaño (S/M/L) |
| list | Selección desplegable | País, categoría |
| button | Acción interactiva | Enviar formulario, CTA |
| spam | Protección contra spam en formularios | Campo de honeypot anti-bot |
| entity | Enlace a otro contenido | Productos relacionados |
| timeInterval | Rangos de fecha/hora | Horarios, período de promoción |
Elegir un tipo
- Texto:
string(una línea),text(párrafos formateados),textWithHeader(texto con un encabezado). - Números:
integer(sin decimales),float(decimales estándar),real(precisión extra). - Fecha/hora:
date,time,dateTime, otimeInterval(rangos/horarios). - Archivos/imágenes:
file(cualquier documento),image(una imagen),groupOfImages(una galería). - Opciones:
radioButton(elige uno),list(desplegable). - Avanzado:
entity(enlace a otras páginas/productos),button(acción interactiva),spam(protección contra bots).
📖 Ejemplos de Tipos de Datos
A continuación se presentan ejemplos técnicos de la estructura de cada tipo de dato tal como los devuelve la API.
💡 Los datos devueltos en el conjunto de atributos no incluyen los valores reales de los atributos; esos residen en entidades específicas (páginas, productos, etc.). La única excepción es
timeInterval, que puede llevar valores cuando la casilla correspondiente está marcada en el panel de administración.
Haz clic para ver todos los ejemplos de tipos de datos
Referencia de Tipos de Datos
- String: Texto simple, por ejemplo, "¡Hola, mundo!".
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "String"
},
"additionalFields": {
"Extra": {
"type": "integer",
"value": "10",
"marker": "Extra"
}
}
}
- Text: Texto más largo, a menudo formateado, por ejemplo, un artículo o una carta.
{
"type": "text",
"value": {},
"marker": "text",
"position": 2,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text"
},
"additionalFields": {}
}
- Text con Encabezado: Texto con un encabezado que puede usarse para denotar un tema o categoría.
{
"type": "textWithHeader",
"value": {},
"marker": "text_with_header",
"position": 3,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text With Header"
},
"additionalFields": {}
}
- Integer: Un número entero, por ejemplo, 5, 100, -2.
{
"type": "integer",
"value": {},
"marker": "integer",
"position": 4,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Integer"
},
"additionalFields": {}
}
- Real: Lo mismo que Float, pero con mayor precisión.
{
"type": "real",
"value": {},
"marker": "real_number",
"position": 5,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Real Number"
},
"additionalFields": {}
}
- Float: Un número de punto flotante que puede tener una parte decimal, por ejemplo, 3.14, 1.5, -0.25.
{
"type": "float",
"value": {},
"marker": "float",
"position": 6,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Float"
},
"additionalFields": {}
}
- Fecha y Hora: Una combinación de fecha y hora, por ejemplo, 2023-10-27 10:00:00.
{
"type": "dateTime",
"value": {},
"marker": "date_time",
"position": 7,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "DateTime"
},
"additionalFields": {}
}
- Fecha: Una fecha, por ejemplo, 2023-10-27.
{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": {}
}
- Hora: Una hora, por ejemplo, 10:00:00.
{
"type": "time",
"value": {},
"marker": "time",
"position": 9,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Time"
},
"additionalFields": {}
}
- Archivo: Cualquier archivo, por ejemplo, un documento, imagen, música.
{
"type": "file",
"value": {},
"marker": "file",
"position": 10,
"listTitles": [],
"validators": {
"checkingFilesValidator": {
"maxUnits": "kb",
"maxValue": "2000",
"minUnits": "kb",
"minValue": 0,
"extensions": []
}
},
"localizeInfos": {
"title": "File"
},
"additionalFields": {}
}
- Imagen: Una imagen, por ejemplo, una fotografía o un dibujo.
{
"type": "image",
"value": {},
"marker": "image",
"position": 11,
"listTitles": [],
"validators": {
"sizeInPixelsValidator": {
"maxX": "500",
"maxY": "500"
}
},
"localizeInfos": {
"title": "Image"
},
"additionalFields": {}
}
- Grupo de Imágenes: Una colección de imágenes, por ejemplo, un álbum de fotos.
{
"type": "groupOfImages",
"value": {},
"marker": "image_group",
"position": 12,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Image Group"
},
"additionalFields": {}
}
- Botón de Opción: Una selección de la cual solo se puede elegir una opción.
{
"type": "radioButton",
"value": {},
"marker": "radio",
"position": 13,
"listTitles": [
{
"title": "A",
"value": "a",
"extended": {
"type": null,
"value": null
},
"position": 1
},
{
"title": "B",
"value": "b",
"extended": {
"type": null,
"value": null
},
"position": 2
}
],
"validators": {},
"localizeInfos": {
"title": "Radio"
},
"additionalFields": {}
}
- Lista: Una lista de elementos seleccionables, por ejemplo, un desplegable.
{
"type": "list",
"value": {},
"marker": "list",
"position": 14,
"listTitles": [
{
"title": "A",
"value": "a",
"extended": {
"type": null,
"value": null
},
"position": 1
},
{
"title": "B",
"value": "b",
"extended": {
"type": null,
"value": null
},
"position": 2
},
{
"title": "C",
"value": "c",
"extended": {
"type": "string",
"value": "Additional Value"
},
"position": 3
}
],
"validators": {},
"localizeInfos": {
"title": "List"
},
"additionalFields": {}
}
- Entidad: Un enlace a otro objeto (página, producto, …).
{
"type": "entity",
"value": {},
"marker": "entity",
"position": 15,
"listTitles": [
{
"title": "Products",
"value": {
"id": 1,
"depth": 0,
"parentId": null,
"isPinned": false,
"position": 1,
"selected": true
}
},
{
"title": "Normal Page",
"value": {
"id": 4,
"depth": 0,
"parentId": null,
"isPinned": false,
"position": 2,
"selected": true
}
},
{
"title": "Error",
"value": {
"id": 2,
"depth": 0,
"parentId": null,
"isPinned": false,
"position": 3,
"selected": true
}
}
],
"validators": {},
"localizeInfos": {
"title": "Entity"
},
"additionalFields": {
"test_field": {
"type": "string",
"value": "Test Field",
"marker": "test_field"
}
}
}
- Intervalo de tiempo: Un calendario flexible con una interfaz amigable para gestionar datos de intervalos de tiempo.
{
"time_interval": {
"id": 4,
"type": "timeInterval",
"value": [
// Array of value groups, each linked to a specific interval (via intervalId). This array is formed when Receive values is enabled in CMS
{
// Specific time records applicable to the specified dates
"values": [
{
// Unique record identifier
"id": "1dc1787d-acc3-4315-a45d-52166c72e577",
// Date range (inclusive) to which this record applies
"dates": ["2025-11-27T00:00:00.000Z", "2025-11-27T00:00:00.000Z"],
// Array of time slots in format [[start, end], ...]
"times": [
[
// Start of time slot (hours and minutes)
{
"hours": 19,
"minutes": 18
},
// End of time slot
{
"hours": 21,
"minutes": 19
}
]
],
// Reserved (not used in current implementation)
"intervals": [],
// Exceptions — time segments excluded from the schedule on the specified date
"exceptions": [
{
// Exception date
"date": "2025-12-17T17:00:00.000Z",
// Array of excluded time segments
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Reference to interval from the `intervals` array
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
// Flag for weekly recurrence (on the corresponding day of the week)
"inEveryWeek": true
},
{
"id": "cfa187d3-0284-4e0d-8206-7b353cf47110",
"dates": ["2025-12-18T00:00:00.000Z", "2025-12-18T00:00:00.000Z"],
// Array of time slots in format [[start, end], ...]
"times": [
[
{
"hours": 0,
"minutes": 25
},
{
"hours": 0,
"minutes": 27
}
],
[
{
"hours": 19,
"minutes": 18
},
{
"hours": 21,
"minutes": 19
}
]
],
"intervals": [],
"exceptions": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6"
},
{
"id": "474de0f7-595f-49a5-aaa7-65617203ae69",
"dates": ["2025-12-25T00:00:00.000Z", "2025-12-25T00:00:00.000Z"],
// No time slots
"times": [],
// Dynamic rules for schedule expansion
"external": [
{
// Base date for calculating recurring event
"date": "2026-01-15T00:00:00.000Z",
// Event repeats every month on this day
"inEveryMonth": true
}
],
"intervals": [],
"exceptions": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
// Flag for weekly recurrence
"inEveryWeek": true,
// Flag for monthly recurrence
"inEveryMonth": true,
// Flag for yearly recurrence
"inEveryYears": true
}
],
// Reference to interval from the `intervals` array
"intervalId": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6"
},
{
"values": [
{
"id": "2f80dc18-16da-45cb-82c6-e41e1f6ee084",
"dates": ["2025-12-22T00:00:00.000Z", "2025-12-23T00:00:00.000Z"],
"times": [],
"intervals": [],
"exceptions": [],
"intervalId": "918175fd-cc18-4ca5-9bee-c78c61c9415a",
"inEveryWeek": true,
"inEveryMonth": true
}
],
"intervalId": "918175fd-cc18-4ca5-9bee-c78c61c9415a"
}
],
"isPrice": false,
"original": true,
"intervals": [
// Array of time interval templates
{
// Unique identifier of interval template
"id": "0da61a19-49cb-40b1-88e6-1fa3c93a1fa6",
"range": [
// Main range of interval applicability
"2025-11-26T17:00:00.000Z",
"2025-11-26T17:00:00.000Z"
],
// Exceptions at the entire interval level
"external": [
{
"date": "2025-12-17T17:00:00.000Z",
"externalTimes": [
["2025-12-17T17:25:00.000Z", "2025-12-17T17:27:00.000Z"]
]
}
],
// Internal time slots (working/active periods)
"intervals": [
{
"id": "01fea594-9933-47ac-af0a-ec0e0884f618",
// End of time slot
"end": {
"hours": 21,
"minutes": 19
},
// Start of time slot
"start": {
"hours": 19,
"minutes": 18
},
// Duration of repeating block (in minutes); null — no periodicity
"period": null
},
{
"id": "22ba24af-1fae-4422-8c92-0635b684a306",
"end": {
"hours": 0,
"minutes": 29
},
"start": {
"hours": 0,
"minutes": 25
},
// Periodicity: time slots repeat with 2-minute step
"period": 2,
// Exception inside periodic slot
"external": {
// Flag for displaying exception in the interface
"show": false,
// Duration of excluded fragment (in minutes)
"value": 2
}
}
],
"inEveryWeek": true,
"inEveryMonth": true,
"inEveryYears": true
},
{
"id": "918175fd-cc18-4ca5-9bee-c78c61c9415a",
"range": ["2026-01-18T17:00:00.000Z", "2026-01-20T17:00:00.000Z"],
// No exceptions
"external": [],
// No internal time slots
"intervals": [],
"inEveryWeek": true,
"inEveryMonth": true,
"inEveryYears": true
}
],
// Flag for attribute visibility in the interface
"isVisible": true,
"identifier": "time_interval",
"localizeInfos": {
"title": "Time interval"
},
"receiveValues": true
}
}
La interfaz de llenado de contenido en el panel de administración corresponde al tipo de dato seleccionado para cada campo de atributo.
❓ Preguntas Comunes (FAQ)
¿Cuál es la diferencia entre string y text?
- string - texto corto, una línea (máx. ~255 caracteres). Úsalo para nombres, títulos, correos electrónicos.
- text - texto largo, múltiples párrafos, admite formato y HTML. Úsalo para descripciones, artículos.
¿Cuándo debo usar integer, float o real?
- integer - solo números enteros (
1, 2, 100, -5). Úsalo para cantidades, conteos, edades. - float - números decimales (
19.99, 4.5). Úsalo para precios, calificaciones, medidas. - real - como float pero con mayor precisión. Úsalo para cálculos científicos.
¿Puedo reutilizar el mismo atributo en diferentes conjuntos de atributos?
Los atributos se definen dentro del esquema de un conjunto de atributos (por marcador). Para reutilizar un campo en otro lugar, crea atributos similares con diferentes marcadores o reutiliza todo el conjunto de atributos en múltiples entidades.
¿Qué es el "marcador" y por qué es importante?
El marcador es el identificador técnico que usas en el código (por ejemplo, product.attributeValues.product_name), a diferencia del título legible por humanos que se muestra en el panel de administración. Los marcadores deben ser únicos, no contener espacios (usar _), no comenzar con un número y convencionalmente estar en minúsculas.
¿Puedo tener atributos anidados?
Sí - usa Campos Adicionales (devueltos bajo additionalFields).
¿Cómo agrego reglas de validación?
En el panel de administración de OneEntry: abre tu conjunto de atributos, haz clic en un atributo, agrega validadores (requerido, min/max, etc.) y guarda. Aprende más: Validadores.
🎓 Mejores Prácticas
- Usa marcadores descriptivos (
product_price, nopp). - Planifica los tipos de atributos antes de agregar contenido.
- Reutiliza conjuntos de atributos en entidades cuando sea posible.
- Agrega validadores para hacer cumplir la calidad de los datos.
- Recuerda que los conjuntos compartidos propagan cambios a cada entidad que los utiliza.
🔗 Documentación Relacionada
- Módulo de Productos - Utiliza conjuntos de atributos para datos de productos
- Módulo de Páginas - Utiliza conjuntos de atributos para contenido de páginas
- Módulo de Bloques - Utiliza conjuntos de atributos para bloques reutilizables
- Módulo de Formularios - Crea formularios con campos personalizados