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.

Rating based on reviews:
Total stars received: 0
Total reviews: 0
Average rating: 0
Filed under: User Blog

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 nameTypePurposeMultilingual
processorinputProcessor model (text)Yes, via separate translation fields
raminputAmount of RAM (e.g., "16 GB DDR5")Yes
ssdinputSSD storage capacityYes
screen_sizeinputScreen diagonal (e.g., "15.6")Yes
screen_resolutionselectScreen resolutionVia language files
matrix_typeselectMatrix typeVia language files
gpuinputGraphics card modelYes
weightdoubleLaptop weight (kg)No (number)
osselectPre-installed OSVia language files
warrantyinputWarranty period (e.g., "2 years")Yes
equipmenttextareaPackage contents (multi-line text)Yes
year_of_issuedatetimeModel release yearNo (date)
instruction_filefileInstruction file (PDF)No (file)
battery_healthrangeBattery health (0–100%)No (number)
featureschecklistboxAdditional features (Bluetooth, Wi‑Fi 6, keyboard backlight, fingerprint scanner)Via language files
has_webcamcheckboxHas webcamVia 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)

No comments yet
Only registered users can post new comments

Recommended Products and Services

Extrafields Market Custom

Extrafields Market Custom

This plugin for Cotonti adds extra fields for the «Market PRO v.5» module into its own database
Cotonti CMF: Plugin Installation, Integration, and Adaptation

Cotonti CMF: Plugin Installation, Integration, and Adaptation

professional services for the installation, deep integration and adaptation of plug-ins for Cotonti
Market PRO v.5+ module for Cotonti CMF

Market PRO v.5+ module for Cotonti CMF

Free solution for scalable E-Commerce projects: you can create a showcase of blacksmith's products

Page Discussion in Telegram

Content author

webitproff

Offline

Sodium Carbonate

Last logged: 2026-07-19 01:57

  • Чем могу помочь?

    Оказываю весь спектр услуг по CMF Cotonti. Разработка открытых и закрытых корпоративных интернет порталов, небольших социальных сетей, торговые площадки, маркетплейсы, биржи фриланса, каталоги товаров оптовых поставщиков, интернет-магазин под заказ, чтобы делать совместные покупки и групповые совместные продажи от имени нескольких продавцов.

  • Разработки на GitHub бесплатно
    • Page published: 2026-07-19 00:02
    • Last update: 2026-07-19 01:02
    • Language:

    Связанные статьи

    Recommended forum topics for this article

    Extrafields Market Custom i18n для модуля “Market” плагин Cotonti

    Extrafields Market Custom i18n для модуля “Market” плагин Cotonti

    Отдельный плагин, - а значит отдельная тема поддержки.
    #208 | Постов: 1 | Просмотров: 1948
    Плагин “Custom Extrafields for Pages” - знакомство и поддержка

    Плагин “Custom Extrafields for Pages” - знакомство и поддержка

    Введение в плагин кратко. Исходные сведения для работы с плагином. Обсуждение, вопросы, помощь и
    #205 | Постов: 6 | Просмотров: 4667
    Экстраполя в Cotonti: полное руководство по типу «Список с множественным выбором» (checklistbox)

    Экстраполя в Cotonti: полное руководство по типу «Список с множественным выбором» (checklistbox)

    Данное руководство является продолжением серии статей о дополнительных полях (Extrafields) в Cotonti
    #204 | Постов: 1 | Просмотров: 2177