Modular product descriptions are easy!
A practical guide: how to create a standardized modular description of a product or product with SEO optimization using the plug-in of additional fields in the product card.
Practical Guide: Modular Product Descriptions with xtradbrowmarket
The xtradbrowmarket plugin lets you not only add custom fields to products, but also build flexible, structured product descriptions on top of them. In this guide, using an online laptop store as an example, we will show how to turn a set of extra fields into a convenient "modular" view: with tabs, characteristics, multilingual descriptions, and SEO optimization. All examples use the features of version 3.0.0 with multilingual support.
What is a modular description and why is it needed
In a classic product card, the description is often a solid block of text mixing specifications, marketing phrases, and delivery terms. A modular description breaks information into logical blocks – for example, "Specifications", "Package Contents", "Files" – and allows you to display them in a structured way, often with switchable tabs. This approach improves user perception, increases conversion, and, importantly, helps search engines index the page content more accurately.
The xtradbrowmarket plugin is ideal for this task because each characteristic is stored in a separate database field. You can combine them in any order, use different templates for different field types, and even translate values into multiple languages.
Step 1. Designing a set of fields for a laptop
Before we start creating fields in the admin panel, let's decide which characteristics we want to store. For a laptop, these can be fields of different types, each solving its own task. The table below lists all the fields we will use.
| Field name | Type | Purpose | Multilingual |
|---|---|---|---|
| processor | input | Processor model (text) | Yes, via separate translation fields |
| ram | input | Amount of RAM (e.g., "16 GB DDR5") | Yes |
| ssd | input | SSD storage capacity | Yes |
| screen_size | input | Screen diagonal (e.g., "15.6") | Yes |
| screen_resolution | select | Screen resolution | Via language files |
| matrix_type | select | Matrix type | Via language files |
| gpu | input | Graphics card model | Yes |
| weight | double | Laptop weight (kg) | No (number) |
| os | select | Pre-installed OS | Via language files |
| warranty | input | Warranty period (e.g., "2 years") | Yes |
| equipment | textarea | Package contents (multi-line text) | Yes |
| year_of_issue | datetime | Model release year | No (date) |
| instruction_file | file | Instruction file (PDF) | No (file) |
| battery_health | range | Battery health (0–100%) | No (number) |
| features | checklistbox | Additional features (Bluetooth, Wi‑Fi 6, keyboard backlight, fingerprint scanner) | Via language files |
| has_webcam | checkbox | Has webcam | Via language files |
All these fields are created through the standard extra fields management interface (Administration → Extensions → Extra fields → cot_xtradbrowmarket). For fields of type input and textarea, you can enable multilingual support and provide translations into other languages. For select, radio, checklistbox, checkbox, translation is defined via language files ($L keys). Other types (double, datetime, file, range) do not require translation.
Step 2. Product editing form (market.edit.tpl)
So that the administrator can conveniently fill in all characteristics, we will not rely on a group loop (it outputs all fields in bulk), but place the fields individually, grouping them into logical blocks. This will also allow adding fields for multilingual translations where needed. Below is an example of form organization using individual tags and taking all field types into account.
<!-- IF {PHP|cot_plugin_active('xtradbrowmarket')} -->
<div class="card mb-4">
<div class="card-header">
<h4>Laptop Specifications</h4>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<!-- Processor -->
<!-- IF {MARKETEDIT_FORM_XTRA_PROCESSOR} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_PROCESSOR_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_PROCESSOR}
</div>
<!-- ENDIF -->
<!-- RAM -->
<!-- IF {MARKETEDIT_FORM_XTRA_RAM} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_RAM_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_RAM}
</div>
<!-- ENDIF -->
<!-- SSD -->
<!-- IF {MARKETEDIT_FORM_XTRA_SSD} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_SSD_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_SSD}
</div>
<!-- ENDIF -->
<!-- Screen size -->
<!-- IF {MARKETEDIT_FORM_XTRA_SCREEN_SIZE} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_SCREEN_SIZE_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_SCREEN_SIZE}
</div>
<!-- ENDIF -->
<!-- Screen resolution (select) -->
<!-- IF {MARKETEDIT_FORM_XTRA_SCREEN_RESOLUTION} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_SCREEN_RESOLUTION_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_SCREEN_RESOLUTION}
</div>
<!-- ENDIF -->
<!-- Matrix type (select) -->
<!-- IF {MARKETEDIT_FORM_XTRA_MATRIX_TYPE} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_MATRIX_TYPE_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_MATRIX_TYPE}
</div>
<!-- ENDIF -->
</div>
<div class="col-md-6">
<!-- Graphics card -->
<!-- IF {MARKETEDIT_FORM_XTRA_GPU} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_GPU_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_GPU}
</div>
<!-- ENDIF -->
<!-- Weight (double) -->
<!-- IF {MARKETEDIT_FORM_XTRA_WEIGHT} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_WEIGHT_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_WEIGHT}
</div>
<!-- ENDIF -->
<!-- OS (select) -->
<!-- IF {MARKETEDIT_FORM_XTRA_OS} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_OS_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_OS}
</div>
<!-- ENDIF -->
<!-- Release year (datetime) -->
<!-- IF {MARKETEDIT_FORM_XTRA_YEAR_OF_ISSUE} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_YEAR_OF_ISSUE_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_YEAR_OF_ISSUE}
</div>
<!-- ENDIF -->
<!-- Battery health (range) -->
<!-- IF {MARKETEDIT_FORM_XTRA_BATTERY_HEALTH} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_BATTERY_HEALTH_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_BATTERY_HEALTH}
</div>
<!-- ENDIF -->
</div>
</div>
</div>
</div>
<!-- Additional features and files block -->
<div class="card mb-4">
<div class="card-header"><h4>Additional</h4></div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<!-- Features (checklistbox) -->
<!-- IF {MARKETEDIT_FORM_XTRA_FEATURES} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_FEATURES_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_FEATURES}
</div>
<!-- ENDIF -->
<!-- Has webcam (checkbox) -->
<!-- IF {MARKETEDIT_FORM_XTRA_HAS_WEBCAM} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_HAS_WEBCAM_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_HAS_WEBCAM}
</div>
<!-- ENDIF -->
</div>
<div class="col-md-6">
<!-- Instruction file (file) -->
<!-- IF {MARKETEDIT_FORM_XTRA_INSTRUCTION_FILE} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_INSTRUCTION_FILE_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_INSTRUCTION_FILE}
</div>
<!-- ENDIF -->
</div>
</div>
</div>
</div>
<!-- Multilingual translations for text fields (example for processor) -->
<!-- IF {MARKETEDIT_FORM_XTRA_PROCESSOR} -->
<div class="card mb-4">
<div class="card-header"><h4>Translations for Processor</h4></div>
<div class="card-body">
<!-- IF {MARKETEDIT_FORM_XTRA_PROCESSOR_EN} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_PROCESSOR_EN_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_PROCESSOR_EN}
</div>
<!-- ENDIF -->
<!-- IF {MARKETEDIT_FORM_XTRA_PROCESSOR_UA} -->
<div class="mb-3">
<label>{MARKETEDIT_FORM_XTRA_PROCESSOR_UA_TITLE}:</label>
{MARKETEDIT_FORM_XTRA_PROCESSOR_UA}
</div>
<!-- ENDIF -->
</div>
</div>
<!-- ENDIF -->
<!-- Similar blocks for other translatable fields (ram, ssd, screen_size, gpu, warranty, equipment) -->
<!-- ENDIF -->
Note: for each field type we use the corresponding individual tag. We only show multilingual fields for input and textarea, since for other types translation is either not required or provided via language files.
Step 3. Display on the product page (market.tpl) with tabs
Now let's organize the output of characteristics on the public page. We'll use the Bootstrap Tabs component to split the information into tabs: "Specifications", "Description", "Files & Warranty", "Additional". For each field type we apply the appropriate display method.
<!-- IF {PHP|cot_plugin_active('xtradbrowmarket')} -->
<div class="card mb-4">
<div class="card-header">
<h4>About the product</h4>
</div>
<div class="card-body">
<ul class="nav nav-tabs" id="productTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="specs-tab" data-bs-toggle="tab" data-bs-target="#specs" type="button" role="tab">Specifications</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="desc-tab" data-bs-toggle="tab" data-bs-target="#description" type="button" role="tab">Description</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="files-tab" data-bs-toggle="tab" data-bs-target="#files" type="button" role="tab">Files & Warranty</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="extra-tab" data-bs-toggle="tab" data-bs-target="#extra" type="button" role="tab">Additional</button>
</li>
</ul>
<div class="tab-content p-3 border border-top-0 rounded-bottom">
<!-- Specifications tab -->
<div class="tab-pane fade show active" id="specs" role="tabpanel">
<div class="row">
<!-- Processor (input) -->
<!-- IF {MARKET_XTRA_PROCESSOR} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_PROCESSOR_TITLE}:</strong>
<span>{MARKET_XTRA_PROCESSOR}</span>
</div>
<!-- ENDIF -->
<!-- RAM (input) -->
<!-- IF {MARKET_XTRA_RAM} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_RAM_TITLE}:</strong>
<span>{MARKET_XTRA_RAM}</span>
</div>
<!-- ENDIF -->
<!-- SSD (input) -->
<!-- IF {MARKET_XTRA_SSD} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_SSD_TITLE}:</strong>
<span>{MARKET_XTRA_SSD}</span>
</div>
<!-- ENDIF -->
<!-- Screen size (input) -->
<!-- IF {MARKET_XTRA_SCREEN_SIZE} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_SCREEN_SIZE_TITLE}:</strong>
<span>{MARKET_XTRA_SCREEN_SIZE}"</span>
</div>
<!-- ENDIF -->
<!-- Resolution (select) -->
<!-- IF {MARKET_XTRA_SCREEN_RESOLUTION} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_SCREEN_RESOLUTION_TITLE}:</strong>
<span>{MARKET_XTRA_SCREEN_RESOLUTION}</span>
</div>
<!-- ENDIF -->
<!-- Matrix type (select) -->
<!-- IF {MARKET_XTRA_MATRIX_TYPE} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_MATRIX_TYPE_TITLE}:</strong>
<span>{MARKET_XTRA_MATRIX_TYPE}</span>
</div>
<!-- ENDIF -->
<!-- Graphics card (input) -->
<!-- IF {MARKET_XTRA_GPU} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_GPU_TITLE}:</strong>
<span>{MARKET_XTRA_GPU}</span>
</div>
<!-- ENDIF -->
<!-- Weight (double) -->
<!-- IF {MARKET_XTRA_WEIGHT} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_WEIGHT_TITLE}:</strong>
<span>{MARKET_XTRA_WEIGHT} kg</span>
</div>
<!-- ENDIF -->
<!-- OS (select) -->
<!-- IF {MARKET_XTRA_OS} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_OS_TITLE}:</strong>
<span>{MARKET_XTRA_OS}</span>
</div>
<!-- ENDIF -->
<!-- Release year (datetime) -->
<!-- IF {MARKET_XTRA_YEAR_OF_ISSUE} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_YEAR_OF_ISSUE_TITLE}:</strong>
<span>{MARKET_XTRA_YEAR_OF_ISSUE_VALUE|cot_date('Y', $this)}</span>
</div>
<!-- ENDIF -->
<!-- Battery health (range) -->
<!-- IF {MARKET_XTRA_BATTERY_HEALTH} -->
<div class="col-md-6 mb-3">
<strong>{MARKET_XTRA_BATTERY_HEALTH_TITLE}:</strong>
<div class="progress mt-1" style="height:20px;">
<div class="progress-bar bg-success" role="progressbar"
style="width:{MARKET_XTRA_BATTERY_HEALTH_VALUE}%;"
aria-valuenow="{MARKET_XTRA_BATTERY_HEALTH_VALUE}" aria-valuemin="0" aria-valuemax="100">
{MARKET_XTRA_BATTERY_HEALTH_VALUE}%
</div>
</div>
</div>
<!-- ENDIF -->
</div>
</div>
<!-- Description tab -->
<div class="tab-pane fade" id="description" role="tabpanel">
<!-- IF {MARKET_XTRA_EQUIPMENT} -->
<div>{MARKET_XTRA_EQUIPMENT}</div>
<!-- ELSE -->
<p>Description not available.</p>
<!-- ENDIF -->
</div>
<!-- Files & Warranty tab -->
<div class="tab-pane fade" id="files" role="tabpanel">
<!-- Warranty (input) -->
<!-- IF {MARKET_XTRA_WARRANTY} -->
<div class="mb-3">
<strong>{MARKET_XTRA_WARRANTY_TITLE}:</strong>
<span>{MARKET_XTRA_WARRANTY}</span>
</div>
<!-- ENDIF -->
<!-- Instruction file (file) -->
<!-- IF {MARKET_XTRA_INSTRUCTION_FILE} -->
<div class="mb-3">
<strong>{MARKET_XTRA_INSTRUCTION_FILE_TITLE}:</strong>
<a href="{PHP.cfg.mainurl}/datas/exflds/xtradbrowmarket/{MARKET_XTRA_INSTRUCTION_FILE}" target="_blank">
Download instruction
</a>
</div>
<!-- ENDIF -->
</div>
<!-- Additional tab -->
<div class="tab-pane fade" id="extra" role="tabpanel">
<!-- Features (checklistbox) -->
<!-- IF {MARKET_XTRA_FEATURES} -->
<div class="mb-3">
<strong>{MARKET_XTRA_FEATURES_TITLE}:</strong>
<ul>
<!-- Checklistbox values are comma-separated, we output via separator -->
<li>{MARKET_XTRA_FEATURES}</li>
</ul>
</div>
<!-- ENDIF -->
<!-- Has webcam (checkbox) -->
<!-- IF {MARKET_XTRA_HAS_WEBCAM} -->
<div class="mb-3">
<strong>{MARKET_XTRA_HAS_WEBCAM_TITLE}:</strong>
<!-- IF {MARKET_XTRA_HAS_WEBCAM_VALUE} == '1' -->
<span class="text-success">Yes</span>
<!-- ELSE -->
<span class="text-danger">No</span>
<!-- ENDIF -->
</div>
<!-- ENDIF -->
</div>
</div>
</div>
</div>
<!-- ENDIF -->
Here we have selected an appropriate display method for each field type: text fields are output as plain text, select shows the translated value, datetime is formatted using cot_date, range is displayed as a progress bar, file forms a download link, checklistbox displays a list, checkbox shows the state with an icon.
Multilingual features
For fields of type input and textarea (processor, RAM, package contents, etc.), the plugin automatically substitutes the translation if it was entered by the administrator in the corresponding language field. Tags like {MARKET_XTRA_PROCESSOR} already contain the value in the required language. For select, radio, checklistbox, checkbox, translation is set via language files, as usual.
Example fragment of the language file xtradbrowmarket.ru.lang.php:
$L['screen_resolution_1920x1080'] = '1920×1080 (Full HD)';
$L['screen_resolution_2560x1440'] = '2560×1440 (QHD)';
$L['screen_resolution_3840x2160'] = '3840×2160 (4K UHD)';
$L['matrix_type_IPS'] = 'IPS';
$L['matrix_type_OLED'] = 'OLED';
$L['matrix_type_TN'] = 'TN';
$L['features_bluetooth'] = 'Bluetooth';
$L['features_wifi6'] = 'Wi‑Fi 6';
$L['features_backlight'] = 'Keyboard backlight';
$L['features_fingerprint'] = 'Fingerprint scanner';
$L['has_webcam_1'] = 'Yes';
$L['has_webcam_0'] = 'No';
For the English version (xtradbrowmarket.en.lang.php) we add similar strings with translation.
SEO benefits of modular descriptions
By using extra fields for meta tags (via header.tags), you can dynamically generate page titles and descriptions. For example:
<title>{HEADER_TITLE} – laptop with {MARKET_HEADER_XTRA_PROCESSOR}, {MARKET_HEADER_XTRA_RAM} | {MARKET_HEADER_XTRA_SCREEN_SIZE}"</title>
This gives unique, keyword-rich meta data for each product, which positively affects search engine rankings.
Conclusion
The xtradbrowmarket plugin version 3.0.0 with multilingual support opens up wide possibilities for creating detailed, well-structured product cards. Using laptops as an example, we have shown how to design fields, organize the editing form, output characteristics in convenient tabs, and provide automatic translation. The exact same approach can be applied to any other category of products – from smartphones to cars.
All this flexibility is achieved without modifying the Cotonti core, solely through configuration of extra fields and templates. Full documentation for the plugin is available in the main README.
Reviews
No reviews yet
Comments (0)
Recommended Products and Services
Extrafields Market Custom
Cotonti CMF: Plugin Installation, Integration, and Adaptation
Market PRO v.5+ module for Cotonti CMF
Page Discussion in Telegram
Content author
Offline
Sodium Carbonate
Last logged: 2026-07-19 01:57
Чем могу помочь?
Оказываю весь спектр услуг по CMF Cotonti. Разработка открытых и закрытых корпоративных интернет порталов, небольших социальных сетей, торговые площадки, маркетплейсы, биржи фриланса, каталоги товаров оптовых поставщиков, интернет-магазин под заказ, чтобы делать совместные покупки и групповые совместные продажи от имени нескольких продавцов.
Разработки на GitHub бесплатно
Telegram
- Page published: 2026-07-19 00:02
- Last update: 2026-07-19 01:02
- Language:
Связанные статьи
Multilingual Еxtrafields of users in Cotonti
ContentsMultilingual Custom Fields in Cotonti: Overview of the xtradbrowusers Plugin
Bookmark (Закладки) в редакторе CKEditor. Руководство
Инструкция объясняет, как использовать функцию Bookmark в редакторе CKEditor для создания якорей
Фильтрация товаров. Как это работает?
Фильтрация товаров в интернет-магазине: как сделать удобный и эффективный каталог Фильтрация товаров
Recommended forum topics for this article
Extrafields Market Custom i18n для модуля “Market” плагин Cotonti
Плагин “Custom Extrafields for Pages” - знакомство и поддержка
Экстраполя в Cotonti: полное руководство по типу «Список с множественным выбором» (checklistbox)
Русский