Skip to main content

Introduction

Define custom fields for your content without touching code.

More information about the module's user interface https://doc.oneentry.cloud/docs/category/attributes


🎯 What does this module do?

The AttributesSets module lets you read the custom-field definitions (attribute sets) used by your content - products, pages, forms, blocks, and more. An attribute set is the schema that describes which fields an entity has and what type each field is; you define these in the OneEntry admin panel and fetch their structure with this module.

Note: attribute sets describe the schema, not the values. Actual values live on the entities themselves (a page, product, etc.) under their attributeValues. The one exception is the timeInterval type, which can carry values - see the examples below.

🚀 Quickstart

Initialize the module from defineOneEntry:


const { AttributesSets } = defineOneEntry(
"your-project-url", {
"token": "your-app-token"
}
);

Fetch the attributes defined in a set and read their markers and types:

// 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);
});

✨ Key Concepts

Attribute, Attribute Set, Value

TermWhat It IsExample
AttributeA single field definition (a marker + a type)price (float)
Attribute SetA collection of attributes - the entity's schema"Product" set
ValueThe data an entity stores for an attribute19.99 on a specific product

An attribute set groups attributes into a reusable schema. The same set can be attached to multiple entities, so changing the set changes the fields available everywhere it is used.

Markers

The marker is the technical identifier you use in code (e.g. product_name). It maps to the human-readable title shown in the admin panel.

product.attributeValues.product_name; // "product_name" is the marker

Marker rules:

  • Must be unique
  • No spaces (use _)
  • Can't start with a number
  • Use lowercase for consistency

✅ Good: product_name, price_usd, main_image — ❌ Bad: product name, 2nd_price, Product Name

📋 What You Need to Know

Shared attribute sets

If an attribute set is used by multiple entities, changes propagate to all of them:

  • Adding an attribute - it appears on every entity using the set; existing content keeps its values and the new field starts empty.
  • Removing an attribute - it is removed from every entity using the set, and existing values are permanently deleted.

You cannot delete an attribute while it is still used in an attribute set.

Validators

Attributes can carry validators to enforce data quality - required fields, min/max length, file-size limits, image pixel dimensions, date ranges, and a default value. Validator config is returned on each attribute under validators.

Click to see validator examples
  • requiredValidator: requires a value to be entered.
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "Currency"
},
"additionalFields": {
"extra": {
"type": "integer",
"value": "10",
"marker": "extra"
}
}
}

  • defaultValueValidator: supplies a default value for the field.
{
"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"
}
}
}

Learn more: See Validators for detailed configuration.

Nested attributes

You can attach extra fields to an attribute via Additional Fields (returned under additionalFields).


📊 Quick Reference Table - Common Methods

MethodWhat It Does
getAttributes()Get all attribute set objects.
getAttributesByMarker()Get all attributes of a set, with data from the attribute set.
getAttributeSetByMarker()Get a single attribute set object by marker.
getSingleAttributeByMarkerSet()Get one attribute (with set data) by set marker and attribute marker.

📚 Available Data Types

Each attribute has a type. Choose the right type for each field.

TypeBest ForExample Use
stringShort text (< 255 chars)Product name, email
textLong formatted textBlog post, description
textWithHeaderText with a titleArticle sections
integerWhole numbersQuantity, age
realHigh-precision decimalsScientific data
floatDecimal numbersPrice, rating
dateJust the dateBirth date, deadline
dateTimeDate + timeEvent start, published at
timeJust the timeOpening hours
fileAny filePDF, document
imageSingle imageAvatar, logo
groupOfImagesMultiple imagesPhoto gallery
radioButtonSingle choiceSize (S/M/L)
listDropdown selectionCountry, category
buttonInteractive actionSubmit form, CTA
spamForm spam protectionAnti-bot honeypot field
entityLink to other contentRelated products
timeIntervalDate/time rangesSchedules, promotion period

Choosing a type

  • Text: string (single line), text (formatted paragraphs), textWithHeader (text with a headline).
  • Numbers: integer (no decimals), float (standard decimals), real (extra precision).
  • Date/time: date, time, dateTime, or timeInterval (ranges/schedules).
  • Files/images: file (any document), image (one picture), groupOfImages (a gallery).
  • Choices: radioButton (pick one), list (dropdown).
  • Advanced: entity (link to other pages/products), button (interactive action), spam (bot protection).

📖 Data Type Examples

Below are technical examples of each data type's structure as returned by the API.

💡 Data returned in the attribute set does not include actual attribute values - those live on specific entities (pages, products, etc.). The only exception is timeInterval, which can carry values when the corresponding box is checked in the admin panel.

Click to see all data type examples

Data Types Reference

  • String: Simple text, for example, "Hello, world!".
{
"type": "string",
"value": {},
"marker": "string",
"position": 1,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"localizeInfos": {
"title": "String"
},
"additionalFields": {
"Extra": {
"type": "integer",
"value": "10",
"marker": "Extra"
}
}
}

  • Text: Longer text, often formatted, for example, an article or a letter.
{
"type": "text",
"value": {},
"marker": "text",
"position": 2,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text"
},
"additionalFields": {}
}

  • Text with Header: Text with a header that can be used to denote a topic or category.
{
"type": "textWithHeader",
"value": {},
"marker": "text_with_header",
"position": 3,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Text With Header"
},
"additionalFields": {}
}

  • Integer: An integer, for example, 5, 100, -2.
{
"type": "integer",
"value": {},
"marker": "integer",
"position": 4,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Integer"
},
"additionalFields": {}
}

  • Real: The same as Float, but with higher precision.
{
"type": "real",
"value": {},
"marker": "real_number",
"position": 5,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Real Number"
},
"additionalFields": {}
}

  • Float: A floating-point number that can have a decimal part, for example, 3.14, 1.5, -0.25.
{
"type": "float",
"value": {},
"marker": "float",
"position": 6,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Float"
},
"additionalFields": {}
}

  • Date and Time: A combination of date and time, for example, 2023-10-27 10:00:00.
{
"type": "dateTime",
"value": {},
"marker": "date_time",
"position": 7,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "DateTime"
},
"additionalFields": {}
}

  • Date: A date, for example, 2023-10-27.
{
"type": "date",
"value": {},
"marker": "date",
"position": 8,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Date"
},
"additionalFields": {}
}

  • Time: A time, for example, 10:00:00.
{
"type": "time",
"value": {},
"marker": "time",
"position": 9,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Time"
},
"additionalFields": {}
}

  • File: Any file, for example, a document, image, music.
{
"type": "file",
"value": {},
"marker": "file",
"position": 10,
"listTitles": [],
"validators": {
"checkingFilesValidator": {
"maxUnits": "kb",
"maxValue": "2000",
"minUnits": "kb",
"minValue": 0,
"extensions": []
}
},
"localizeInfos": {
"title": "File"
},
"additionalFields": {}
}

  • Image: An image, for example, a photograph or drawing.
{
"type": "image",
"value": {},
"marker": "image",
"position": 11,
"listTitles": [],
"validators": {
"sizeInPixelsValidator": {
"maxX": "500",
"maxY": "500"
}
},
"localizeInfos": {
"title": "Image"
},
"additionalFields": {}
}

  • Group of Images: A collection of images, for example, a photo album.
{
"type": "groupOfImages",
"value": {},
"marker": "image_group",
"position": 12,
"listTitles": [],
"validators": {},
"localizeInfos": {
"title": "Image Group"
},
"additionalFields": {}
}

  • Radio Button: A selection from which only one option can be chosen.
{
"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": {}
}

  • List: A list of selectable items, for example, a dropdown.
{
"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": {}
}

  • Entity: A link to another object (page, product, …).
{
"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"
}
}
}

  • Time interval: A flexible calendar with a user-friendly interface for managing time-interval data.
{
"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
}
}

The content-filling interface in the admin panel corresponds to the selected data type for each attribute field.


❓ Common Questions (FAQ)

What's the difference between string and text?

  • string - short text, single line (max ~255 chars). Use for names, titles, emails.
  • text - long text, multiple paragraphs, supports formatting and HTML. Use for descriptions, articles.

When should I use integer, float, or real?

  • integer - whole numbers only (1, 2, 100, -5). Use for quantities, counts, ages.
  • float - decimal numbers (19.99, 4.5). Use for prices, ratings, measurements.
  • real - like float but higher precision. Use for scientific calculations.

Can I reuse the same attribute in different attribute sets?

Attributes are defined within an attribute set's schema (by marker). To reuse a field elsewhere, either create similar attributes with different markers, or reuse the entire attribute set across multiple entities.


What's the "marker" and why is it important?

The marker is the technical identifier you use in code (e.g. product.attributeValues.product_name), as opposed to the human-readable title shown in the admin panel. Markers must be unique, contain no spaces (use _), not start with a number, and are conventionally lowercase.


Can I have nested attributes?

Yes - use Additional Fields (returned under additionalFields).


How do I add validation rules?

In the OneEntry admin panel: open your attribute set, click an attribute, add validators (required, min/max, etc.), and save. Learn more: Validators.


🎓 Best Practices

  • Use descriptive markers (product_price, not pp).
  • Plan attribute types before adding content.
  • Reuse attribute sets across entities when possible.
  • Add validators to enforce data quality.
  • Remember that shared sets propagate changes to every entity that uses them.