Документація

Дані сторінок: що доступне шаблону

Змінні, що є на кожній сторінці, та те, що приходить своє на кожен розділ вітрини.

На цій сторінці

Шаблон не звертається до бази даних — магазин віддає йому готові дані. Частина з них є на кожній сторінці, частина приходить своя на кожен розділ вітрини.

Є на кожній сторінці

Змінна Що всередині
$storefront вітрина: назва, домен, мова, валюта, значок вкладки
$theme значення налаштувань теми
$action назва поточного розділу
$seo заголовок, опис і мета-теги для пошукової системи
$shop помічник зі списками магазину
$contacts контакти магазину
$customer покупець або порожньо, якщо він не увійшов
$min_order найменша сума замовлення; 0 — без обмеження
$below_min у кошику є товари, але сума нижча за найменше замовлення
$free_shipping_left скільки додати до безкоштовної доставки; порожньо — додавати не треба
$free_shipping_from з якої суми доставка безкоштовна; 0 — порогу немає
$errors помилки форми після повернення назад
$status повідомлення про успіх
$old введені значення форми після повернення назад
$auth як покупець може увійти: пароль, кнопки соцмереж, капча
$cookies куки, які поставив скрипт теми
$get параметри адреси сторінки
$request те саме, що $cookies і $get, записом виклику

$storefront

{$storefront.name}            назва магазину
{$storefront.storefront_name} службова назва вітрини
{$storefront.domain}
{$storefront.locale}          поточна мова: ru
{$storefront.locales}         мови вітрини
{$storefront.default_locale}
{$storefront.currency}        валюта вітрини: UAH
{$storefront.favicon}

name — це назва магазину із загальних налаштувань, її й показують покупцеві. Службова назва вітрини лежить окремо і потрібна лише магазинам із кількома вітринами.

$theme

Значення налаштувань теми — плоско і за групами:

{$theme.copyright}          {$theme.footer.copyright}
{$theme.per_page}           {$theme.catalog.per_page}
{$theme.assets}             /theme-assets/ім'я-теми
{$theme.colors.primary}     {$theme.colors.accent}
{$theme.colors.bg}          {$theme.colors.text}

Усі поля схеми присутні, навіть незаповнені — вони приходять порожніми, і шаблон на них не падає. Подробиці — на сторінці Файл theme.json.

$action

Назва поточного розділу: default на головній, далі category, product, search, page, checkout/cart. Зручно для класу на <body> і для підсвічування активного пункту меню.

$seo

{$seo.title}        {$seo.h1}          {$seo.description}
{$seo.keywords}     {$seo.robots}      {$seo.indexable}
{$seo.canonical}    {$seo.hreflang}    {$seo.page_type}
{$seo.og.title}     {$seo.og.description} {$seo.og.type}
{$seo.og.url}       {$seo.og.image}    {$seo.og.site_name}
{$seo.og.locale}    {$seo.og.locale_alternates}
{$seo.twitter.card} {$seo.twitter.title} {$seo.twitter.description}
{$seo.twitter.image} {$seo.twitter.site}

Усі ключі присутні завжди, тому {if $seo.og.image} безпечний. Магазин рахує ці значення сам, темі залишається вивести їх у <head> — готовий шматок розмітки є на сторінці Каркас сторінки.

$contacts

{if $contacts.phone}<a href="tel:{$contacts.phone_link}">{$contacts.phone}</a>{/if}
{$contacts.name}  {$contacts.email}  {$contacts.address}

phone_link — телефон, очищений до цифр і +, готовий для href="tel:". Незаповнене поле приходить порожнім рядком, ключ на місці завжди.

Телефон із налаштувань теми перетворюється на посилання модифікатором |tel — він залишає лише цифри та +:

<a href="tel:{$theme.phone_2|tel}">{$theme.phone_2}</a>

$min_order

Найменша сума замовлення з налаштувань оформлення, у валюті вітрини. Вона є на будь-якій сторінці, тож її можна показати в шапці або у висувному кошику:

{if $min_order > 0}
  <div class="cart-min" data-min-order="{$min_order}">
    Мінімальне замовлення — {money amount=$min_order currency=$storefront.currency}
  </div>
{/if}

Скриптам теми та сама сума приходить у window.CartiX.minOrder.

$below_min, $free_shipping_left, $free_shipping_from

Пороги кошика є на будь-якій сторінці, а не лише в кошику: їх показують у шапці, у висувному кошику, на сторінці товару. $below_min каже, що в кошику є товари, але до найменшого замовлення не вистачає. $free_shipping_left — скільки залишилося до безкоштовної доставки (порожньо, якщо поріг пройдено або його немає), $free_shipping_from — сам поріг.

Поріг один для всіх покупців, а $below_min і $free_shipping_left — особисті. Сторінка каталогу лежить у спільному кеші вітрини, і вписати в неї чужий кошик не можна. Тому на такій сторінці $below_min хибне, а $free_shipping_left порожнє, і числа проставляє магазин у браузері. Позначте блоки атрибутами — решту зробить /storefront/cart-sync.js, зокрема після кожної зміни кошика:

<p data-cart-below-min{if !$below_min} hidden{/if}>
  Мінімальна сума замовлення: <b data-cart-min-order></b>
</p>
<p data-cart-free-row{if !$free_shipping_left} hidden{/if}>
  До безкоштовної доставки залишилося <b data-cart-free-left></b>
</p>

Сторінка, яка до спільного кешу не потрапляє (покупець увійшов, кошик, оформлення), отримує числа одразу, і блок видно без затримки.

$customer

Для гостя — порожньо, тому {if $customer} достатньо.

{$customer.id}          {$customer.name}       {$customer.initial}
{$customer.first_name}  {$customer.last_name}  {$customer.middle_name}
{$customer.company}     {$customer.email}      {$customer.phone}
{$customer.member_since}

$errors, $status, $old

Після форми, яку надіслали звичайним POST і яка повернулася з помилкою:

{if $status}<p class="ok">{$status}</p>{/if}

<input name="email" value="{$old.email|default:''}">
{if $errors.email}<span class="err">{$errors.email}</span>{/if}

Помилок немає — $errors порожній список. Подробиці — на сторінці Форми вітрини.

$auth

Способи входу, які власник увімкнув у «Реєстрації та вході» вітрини. Є на кожній сторінці — тому вікно входу можна поставити просто в шапку.

{$auth.password}      вхід за паролем увімкнено
{$auth.registration}  реєстрацію відкрито
{$auth.login_by}      phone — за телефоном, both — за телефоном або поштою
{$auth.subscribe}     пропонувати підписку під час реєстрації
{foreach $auth.socials as $s}
  <a href="{$s.url}">{$s.title}</a>     {$s.code}: google, facebook, telegram
{/foreach}
{$auth.captcha.required} {$auth.captcha.provider} {$auth.captcha.site_key}

Форма входу надсилається на /account/login (поля identifier, password, remember). Додайте поле return з адресою поточної сторінки — після входу покупець залишиться на ній, а не піде в кабінет. Те саме для кнопок соцмереж: {$s.url}?return=/адреса. Приймається лише адреса свого сайту.

$cookies, $get, $request

Куки й параметри адреси — для рішень, які має ухвалити сервер. Приклад: закритий покупцем банер не виводиться взагалі, а не ховається скриптом після завантаження.

{if $cookies.cx_promo_closed != 'header-promo'} …банер… {/if}
{$get.page}                     ?page=2 → 2
{$request->cookie('cx_view')}   {$request->get('sort')}   {$request->path()}

Шаблону видно лише куки, які поставив скрипт у браузері (document.cookie). Куки магазину — сесія, кошик, чат — не видно. Кука, якої немає, читається порожнім рядком. У $get лише прості значення: з адреси ?page[]=1 параметр page прийде порожнім.

Сторінка з прочитаною кукою зберігається в загальному кеші окремою копією на кожне її значення — магазин запам'ятовує, які куки читають шаблони. Тому читайте лише куки вибору покупця (закрив банер, обрав вигляд каталогу), а не унікальні (ідентифікатори аналітики): інакше кеш перетвориться на копію сторінки для кожного відвідувача. Більше двадцяти різних назв магазин не запам'ятовує — такі куки читаються порожніми.

{$smarty.cookies} і {$smarty.get} у шаблонах закриті: у Smarty вони відкриваються разом із {$smarty.server}, а там службові паролі сайту.

Посторінково

Дані сторінки кладуться поверх загальних і можуть перекрити будь-яку з них — не називайте свої змінні product, якщо на сторінці вже є товар.

Сторінка Шаблон Змінні
Головна home.html лише загальні: вміст збирається через $shop
Категорія category.html category, breadcrumbs, landing + набір лістингу
Товар product.html product, breadcrumbs, rec_cross, rec_up, reviews, questions
Сторінка власника page.html page, breadcrumbs
Пошук search.html query, category_id, has_query, corrected + набір лістингу
Бренд brand.html brand, breadcrumbs + набір лістингу
Усі бренди brands.html brands
Мітка tag.html tag, breadcrumbs + набір лістингу
Усі мітки tags.html tags
Добірка product-list.html list, breadcrumbs + набір лістингу
Стрічка блогу blog.html blog, categories, posts, pagination, total, breadcrumbs
Рубрика блогу blog-category.html blog, category, categories, posts, pagination, total, breadcrumbs
Запис блогу blog-post.html blog, post, products, related, breadcrumbs
Мітка блогу blog-tag.html blog, tag, categories, posts, pagination, total, breadcrumbs
Кошик checkout/cart.html items, cart, min_order, below_min, free_shipping_left
Оформлення checkout/layout.html checkout
Замовлення прийнято checkout/success.html order, is_authenticated
Оплата замовлення checkout/pay.html order, order_id, is_paid, is_online, show_offline_note
Помилка оплати checkout/pay-error.html order_id
Обране favorites.html products
Порівняння compare.html колонки товарів і рядки характеристик
Вхід account/login.html auth, captcha
Реєстрація account/register.html auth, captcha, reg_types
Огляд кабінету account/dashboard.html orders, orders_count, bonus
Замовлення account/orders.html orders, pagination, filters
Одне замовлення account/order.html order
Профіль account/profile.html profile
Не знайдено 404.html лише загальні
Магазин зачинено maintenance.html message

Сторінка оплати замовлення

Покупець потрапляє сюди з кабінету і за посиланням з листа чи SMS.

Змінна Що всередині
is_paid замовлення вже оплачене — пропонувати оплату нема чого
is_online спосіб веде на сторінку банку: показуємо кнопку «Оплатити»
show_offline_note чи показувати підпис «це замовлення оплачується при отриманні»

Підпис потрібен не завжди. Оплата за рахунком теж нікуди не веде, але показує на цій самій сторінці кнопку з рахунком — і підпис про оплату кур’єрові прямо їй суперечить. Тому замість {else} пишеться {elseif $show_offline_note}:

{if $is_online}
    <button type="button" data-pay-submit>{trans key="storefront.pay_now"}</button>
{elseif $show_offline_note}
    <p>{trans key="storefront.pay_offline"}</p>
{/if}

Тема, написана раніше й не обізнана з цією змінною, працює як раніше: підпис у ній залишається в усіх способів без сторінки банку.

Набір лістингу

Однаковий у категорії, пошуку, бренда, мітки та добірки — тому список товарів, фільтри і посторінкова навігація пишуться один раз і підключаються до всіх цих сторінок.

Змінна Що всередині
products картки товарів поточної сторінки
pagination посторінкова навігація
total скільки товарів знайшлося всього
filters доступні фільтри
active_filters чипси вибраних умов, у кожного адреса «зняти»
filter_chips чи показувати чипси
selected що вибрано зараз
sort, sort_options поточне сортування і його варіанти
action_url адреса, на яку надсилається форма фільтра
reset_url адреса «скинути все»
keep_params параметри, які потрібно зберегти під час переходу
has_filters, show_filters чи є фільтри і чи показувати панель
lazy_load підвантажувати товари кнопкою «Показати ще»
filter_mode ajax — застосовувати одразу, button — після натискання кнопки
filter_show_counts показувати лічильники біля значень фільтра
image_lazy підвантажувати картинки під час прокручування

pagination

{if $pagination.has_pages}
    {if $pagination.prev_url}<a href="{$pagination.prev_url}">Назад</a>{/if}
    {foreach $pagination.pages as $p}
        {if $p.ellipsis}<span>…</span>
        {else}<a href="{$p.url}"{if $p.active} class="is-active"{/if}>{$p.num}</a>{/if}
    {/foreach}
    {if $pagination.next_url}<a href="{$pagination.next_url}">Вперед</a>{/if}
{/if}

Ще є current, last, from, to, total — для підпису «Показано 1–24 з 137».

filters

Ключ Що всередині
all уся колонка одним списком, за порядком — малюйте фільтри за ним
price min, max, from, to, active
in_stock count, selected, disabled — або порожньо, якщо фільтр вимкнено
discount те саме
warehouses фільтр за складами
features словникові характеристики: колір, матеріал, бренд
ranges розмірні характеристики: довжина, вага, потужність
booleans характеристики «так/ні»

Малюйте фільтри списком за даними, а не за іменами. Набір характеристик у кожного магазину свій: жорстко прописаний перелік «колір, розмір, бренд» у чужому магазині покаже порожнечу.

filters.all — колонка за порядком (з ядра 2.59.0)

Склад і порядок колонки задає власник у налаштуваннях розділу: які фільтри в ньому стоять, чи потрібні ціна, наявність, знижка та склад, що йде першим. Готовий порядок приходить у filters.all — малюйте колонку за ним, інакше розстановка власника до покупця не дійде.

У кожного рядка три поля: kind — що це за фільтр, id — номер характеристики (у ціни, наявності, знижки та складу його немає), data — те саме, що лежить у ключах вище.

kind Що в data
price те саме, що у filters.price
in_stock, discount те саме, що в однойменному ключі
warehouse список складів, як у filters.warehouses
feature характеристика зі списком значень
range числова характеристика (повзунок «від–до»)
boolean характеристика «так/ні»
{foreach $filters.all as $block}
    {if $block.kind == 'feature'}
        <div class="filter-group">
            <div class="filter-group__title">{$block.data.name}</div>
            {foreach $block.data.values as $v}
                <label>
                    <input type="checkbox" name="f[{$block.data.id}][]" value="{$v.id}"
                           {if $v.selected}checked{/if} {if $v.disabled}disabled{/if}>
                    {$v.label}
                </label>
            {/foreach}
        </div>
    {elseif $block.kind == 'price'}
        …
    {/if}
{/foreach}

Окремі ключі (features, ranges, booleans, price та інші) залишилися на місці: тема, написана до 2.59.0, працює як працювала. З ядра 2.107.0 вони теж слухають налаштування розділу: усередині кожного ключа фільтри йдуть у порядку власника, а in_stock, discount і warehouses порожні, якщо власник прибрав їх із розділу. price приходить завжди: старі теми малюють ціну без перевірки. Але кожен вид така тема малює своєю пачкою, тому повзунок «від–до» в ній опиняється під усіма списками, хоч би куди власник його поставив. Порядок повністю дотримує лише filters.all.

Значення, за яким при поточному виборі товарів немає, приходить з ознакою disabled — його показують приглушеним, а не ховають: інакше покупець не розуміє, куди подівся варіант.

active_filters

Чипси вибраних умов. У кожного своя адреса без цієї умови, тому зняття фільтра працює і без скриптів:

{foreach $active_filters as $chip}
    <a href="{$chip.url}" class="chip">{$chip.label} ✕</a>
{/foreach}

Що приходить на окремі сторінки

Категорія завжди отримує landing, навіть на звичайній категорії — там це порожні text_top, text_bottom і related. Зроблено, щоб шаблон писався один раз, без перевірки «а чи є посадкова сторінка».

Пошук при запиті коротшому за дві літери отримує лише query, category_id, has_query (порожньо) і total (нуль) — ні лістингу, ні фільтрів. Окрема гілка «введіть хоча б два символи» в шаблоні потрібна.

Кошик: items — позиції, cart — підсумки, min_order і below_min — мінімальна сума замовлення, free_shipping_left — скільки додати до безкоштовної доставки (порожньо, якщо додавати не потрібно або порога немає).

Оформлення отримує checkout. У порожнього кошика там лише ознака «порожньо» і сам кошик; інакше — settings (які поля увімкнено), prefill, contact_types, recipient_fields, recipient_company_fields, saved_addresses, location_fields, cart, calc і те, що додали доповнення.

Відгуки можуть прийти одним ключем: якщо власник вимкнув відгуки, у $reviews буде лише ознака «вимкнено». Звертатися до $reviews.items без перевірки не можна.

Добірка — сторінка, яку власник вмикає в добірки товарів перемикачем «Зробити окрему сторінку». Крім набору лістингу вона отримує list:

Поле Що всередині
name назва добірки
description текст добірки, готовий HTML — виводиться з nofilter
slug адреса добірки
url шлях сторінки: /list/адреса/ з мовним префіксом вітрини
categories категорії, вибрані в правилах добірки (джерело «На категорії»), з підкатегоріями, якщо позначено «з підкатегоріями»; у добірки іншого виду — порожньо
product_categories категорії, в яких лежать товари добірки: основна категорія товару й ті, до яких він прив’язаний

Обидва списки — у порядку дерева каталогу, лише ввімкнені категорії цієї вітрини. У кожної категорії: id, parent_id, name, url, level (0 — верхній рівень, 1 — підкатегорія і так далі) та count — скільки товарів добірки в ній разом із підкатегоріями. З ядра 2.54.0.

{if $list.categories}
    <nav class="list-cats">
        {foreach $list.categories as $cat}
            <a href="{$cat.url}" style="margin-left: {$cat.level * 16}px">{$cat.name} ({$cat.count})</a>
        {/foreach}
    </nav>
{/if}

Шаблон майже збігається з tag.html: той самий лістинг, інший заголовок. Якщо у вашій темі product-list.html немає, магазин візьме його зі стандартної теми — див. З чого складається тема.

<h1>{$list.name}</h1>
{if $list.description}<div class="cms-body">{$list.description nofilter}</div>{/if}
{foreach $products as $product}
    {include file="partials/product-card.html" product=$product}
{/foreach}
{include file="partials/pagination.html" pagination=$pagination}

Блог

Чотири сторінки блогу отримують однакові частини: blog — сам блог, posts — записи поточної сторінки, categories — рубрики верхнього рівня для меню блогу.

blog і category

Поле Що всередині
id, slug номер і адреса
name назва
summary короткий опис для стрічки й пошукових систем
description текст, готовий HTML — виводиться з nofilter; у меню й картках лише з full
url шлях сторінки
cover, cover_thumb, banner обкладинка, її ескіз і широкий банер; порожньо, якщо не завантажені
icon значок блогу (лише в blog)
parent_id номер батьківської рубрики; порожньо на верхньому рівні (лише в рубрики)
children вкладені рубрики з тими самими полями (лише в рубрики)
parent батьківська рубрика з тими самими полями, без children (лише в category)

Кожен елемент categories — рубрика з усіма полями з цієї таблиці, разом із children. Тому меню блогу можна малювати з обкладинками, банерами й розкривними гілками. Вимкнені рубрики та все, що під ними, до меню не потрапляють.

Повний опис description збирається з текстового редактора разом з усіма вставками, і в рубрики з добіркою статей це помітна робота. Тому сам блог і відкрита рубрика отримують його завжди, а в меню, у картках записів і в списку блогів він порожній, доки тема не попросить повні дані параметром full: $shop->blogCategories($blog.id, true) — меню рубрик з описами, $shop->blogs(true) — блоги з описами, {posts full=true} і $shop->posts(['full' => true]) — записи, у рубрик яких є опис. У батьківської й вкладених рубрик відкритої рубрики (parent, children) і в рубрики запису на його сторінці (post.category) опису теж немає — його беруть із $shop->blogCategories($blog.id, true). Решта полів приходить завжди. На сторінці мітки замість рубрики приходить tag з полями id, slug, name і url.

Запис у стрічці

Так виглядає кожен елемент posts і related, і саме це отримує partials/blog-card.html:

Поле Що всередині
id, slug номер і адреса
title заголовок
summary анонс
url шлях запису
cover, cover_thumb обкладинка повністю та її ескіз для картки
banner широкий банер запису
author автор
reading_time хвилин на читання
views скільки разів прочитали
is_pinned запис закріплено вгорі стрічки
date, date_label, date_iso дата: 2026-09-17, «17 вересня 2026» мовою вітрини, повна для <time datetime>
category головна рубрика з усіма полями рубрики, крім children і parent; порожньо, якщо рубрику вимкнено
categories усі рубрики запису з тими самими полями; вимкнених серед них немає
tags мітки запису: id, slug, name і url
{foreach $posts as $post}
    {include file="partials/blog-card.html" post=$post}
{/foreach}
{include file="partials/pagination.html" pagination=$pagination}

Такий самий запис віддає тег {posts} — ним статті ставлять на головну й у будь-яке інше місце теми. Умови добірки та приклади — на сторінці Теги магазину.

post — сторінка запису

Усе, що є в запису в стрічці, і ще:

Поле Що всередині
content текст статті, готовий HTML — виводиться з nofilter
anchors зміст за заголовками статті: у кожного id і name

Поруч зі статтею приходять products — товари, які власник прив’язав до запису (картки як у каталозі; порожньо, якщо блок вимкнено в налаштуваннях блогу), і related — записи для блоку «читайте також».

<article data-blog-post="{$post.id}">
    <h1>{$post.title}</h1>
    {if $post.anchors}
        <ol>{foreach $post.anchors as $a}<li><a href="#{$a.id}">{$a.name}</a></li>{/foreach}</ol>
    {/if}
    <div class="cms-body">{$post.content nofilter}</div>
</article>

Атрибут data-blog-post обов’язковий: за ним магазин рахує прочитання. Сам скрипт лічильника підключає магазин, у темі його писати не потрібно.

Замовлення покупця в кабінеті

Список замовлень (account/orders.html) отримує orders — рядки замовлень, pagination — сторінки та filters — з чого покупцеві обирати у відборі (shipping, payment, statuses і current — що обрано зараз). Список перемальовується на місці, тому саму таблицю виносять у account/partials/orders-table.html: магазин просить у теми цей самий шматок розмітки і підставляє його назад.

Сторінка одного замовлення (account/order.html) отримує order. Замовлення — знімок: суми, назви способів і дані покупця залишаться такими, якими були в день покупки, навіть якщо магазин потім усе це перейменує.

Рядок замовлення

Ці поля є і в рядка списку, і в картки — верстку можна писати один раз.

Поле Що всередині
number номер, яким його бачить покупець (з оформленням із налаштувань)
number_raw номер для адреси сторінки: в оформленні буває #, і посилання зламалося б
date дата оформлення
status, status_label, status_color код статусу, його назва та колір
total, currency сума та валюта замовлення
items_count скільки позицій
shipping_name, shipping_logo спосіб доставки та його логотип
payment_name, payment_logo спосіб оплати та його логотип
payment_status, payment_status_label стан оплати та його назва
is_paid чи оплачене замовлення повністю
paid_total, due скільки внесено і скільки залишилось заплатити
pay_url адреса сторінки оплати — або порожньо
comment коментар покупця
tracking номер накладної перевізника

Логотип приходить порожнім, якщо власник його не завантажував або спосіб уже видалено — тоді залишається назва, знята із замовлення при оформленні:

{if $order.shipping_logo}<img src="{$order.shipping_logo}" alt="">{/if}
{$order.shipping_name|default:'—'}

pay_url є лише в неоплаченого замовлення і лише у способу, який веде на сторінку банку. У оплати при отриманні та оплати за рахунком його немає і бути не повинно — кнопка вела б у нікуди:

{if $order.pay_url && $order.due > 0}
    <a href="{$order.pay_url}">Сплатити {money amount=$order.due currency=$order.currency}</a>
{/if}

Що додається на сторінці замовлення

Поле Що всередині
placed_at, paid_at коли замовлення оформлене і коли сплачене, з часом
items_total, services_total, discount_total товари, послуги, знижка
shipping_total, tax_total, bonus_total доставка, податок, оплата балами
extra_total усе, що доповнення додало до підсумку понад ці рядки
discounts які правила спрацювали і на скільки
promo_code промокод, якщо покупець його вводив
needs_callback покупець просив передзвонити
items склад замовлення
customer що покупець указав про себе
recipient інший отримувач — або порожньо
address адреса доставки
timeline історія змін статусу

Рядки зобов'язані складатися в підсумок. extra_total саме для цього: у суму замовлення міг увійти пункт, якого в інших рядках немає — наприклад надбавка за спосіб оплати від доповнення. Покажіть його окремим рядком, інакше покупець складе стовпчиком і отримає не ту суму.

items — склад замовлення

Поле Що всередині
name, sku_code назва та артикул на день покупки
image фотографія варіанта — або порожньо
url посилання на товар; порожньо, якщо товару в каталозі більше немає
qty, unit кількість та одиниця продажу
pack packs і rest, якщо товар брали упаковками
price, compare_price ціна та стара ціна
discount_total, total знижка на позицію та її сума
services послуги до цієї позиції: name, price, total

Фотографії може не бути — товар зняли з продажу або її взагалі не завантажували. Ставте на це місце значок, порожня рамка читається як зламане зображення.

customer і recipient — поля замовлення

Обидва приходять списком: code, name, value. Назви — ті самі, якими поля названі в магазині в розділі «Оформлення замовлення», тому малюйте їх циклом, а не за іменами: набір полів у кожного магазину свій, і замовлення компанії несе ще назву та податковий номер.

{foreach $order.customer as $field}
    <p><span>{$field.name|escape}</span> <span>{$field.value|escape}</span></p>
{/foreach}

recipient приходить порожнім, якщо замовлення оформлювали на себе.

address — куди везти

name, phone, email, country, region, city, zip, street (вулиця, будинок і квартира одним рядком), окремо street_name, building, apartment, а також point і point_number — обране відділення або пункт видачі. При доставці у відділення вулиці немає і не буде: магазин навмисно її не заповнює, щоб у документах не опинилися й адреса, й відділення одразу.

timeline — історія замовлення

Зміни статусу по порядку: date, status, status_label і comment менеджера. Внутрішніх позначок співробітників покупцеві не показують — їх у цьому списку немає.

Текст сторінки від власника

Текст, який власник пише внизу головної заради пошуку, лежить не в темі, а в розділі «SEO → SEO-оптимізація» — свій для кожної вітрини та кожної мови. Тема друкує його одним рядком:

{seo_text}

Тег друкує текст тієї сторінки, яка відкрита (на головній — її текст). Потрібен текст іншої сторінки — {seo_text page="home"}. Потрібна власна верстка блоку — покладіть текст у змінну й малюйте самі:

{seo_text assign='seo_page_text'}

{if $seo_page_text|default:'' !== ''}
    <section class="seo-text">{$seo_page_text nofilter}</section>
{/if}

Тексту немає — тег не друкує нічого: порожнього блоку на сторінці бути не має. Доповнення «SEO-оптимізація» може бути не встановлене — тоді тег теж мовчить, і тема працює як раніше. З ядра 2.58.0.

Як подивитися дані на власні очі

{dump}                що взагалі доступне цьому шаблону
{dump var=$product}   одне значення цілком
{dumpc var=$product}  те саме в консоль браузера

Бачить лише співробітник магазину — покупцеві блок не покажеться. Це найшвидший спосіб зрозуміти, що приходить на конкретну сторінку, і він завжди актуальніший за будь-яку таблицю.

Оновлено 13 жовтня 2026