Розробка карточки товару для інтернет-магазину
Карточка товару — головна конверсійна сторінка магазину. Тут користувач приймає рішення про покупку, і кожен елемент інтерфейсу або допомагає, або створює тертя. Технічно карточка складніша за те, як вона виглядає: вона збирає дані з кількох джерел, повинна працювати швидко при будь-якому навантаженні та бути SEO-оптимізованою з першим байтом HTML.
Структура даних
Одна сторінка агрегує дані з різних таблиць:
Product
├── Варіанти (sku, ціна, наявність)
├── Зображення (по варіантам та спільні)
├── Атрибути (specs, характеристики)
├── Опис (rich text)
├── Категорія + Breadcrumb
├── Рейтинг (агрегований) + останні відгуки
├── Подібні товари
├── «Часто купують разом»
└── Ціна з історією знижок
Неможливо завантажити всі дані в один запит без N+1. Типова стратегія:
- SSR основного контенту — назва, головне зображення, ціна, кнопка «Купити». Приходить з першим HTML, індексується поисковиком.
- Lazy-load блоків — відгуки, подібні товари, «з цим купують» — завантажуються після DOMContentLoaded через окремі API-запити.
- Кеш карточки — повний HTML сторінки кешується на CDN з інвалідацією при змінені товара.
Вибір варіанту
Якщо товар має варіанти (колір × розмір), інтерфейс вибору — ключовий елемент. Вимоги:
- Недоступні комбінації — візуально заблоковані (зачеркнуті або сірі), не кликабельні
- При виборі варіанту оновлюються: зображення, ціна, наявність, SKU в URL
- Якщо варіант закінчився — показуємо «Немає в наявності» + кнопку «Повідомити про поступлення»
function isAvailable(selection: Record<number, string>, variants: Variant[]): boolean {
return variants.some(v =>
Object.entries(selection).every(([attrId, val]) =>
v.attributes[attrId] === val
) && v.inStock
);
}
URL оновлюється через pushState при виборі: /product/sneakers-air-max?color=black&size=42. Можна поділитися посиланням на конкретний варіант та працює кнопка «Назад».
Блок ціни
Ціна — не просто число. Типичний набір станів:
- Звичайна ціна
- Ціна зі знижкою (зачеркнута стара + нова)
- Діапазон цін для товарів з варіантами («від 2 990 руб.»)
- «Ціна по запиту» для B2B-товарів
- «Увійдіть для перегляду ціни» (оптові клієнти)
Історія ціни: невеликий графік змін ціни за 30–90 днів — сигнал довіри. «Мінімальна ціна за 30 днів: 3 490 руб.» — аналог маркування на WB та Ozon.
Зворотний відлік до кінця акції: якщо discount.ends_at задан, показуємо таймер. Реалізація на клієнті через setInterval, синхронізація з серверним часом при завантаженні сторінки.
Блок наявності та доставки
Користувач хоче знати: коли він отримає товар? Це важливіше за саму кнопку «Купити».
- «Є в наявності: 12 шт.» (або «Мало залишилось: 2 шт.» при qty < 5)
- «Доставка завтра» — якщо оформити до 18:00 (вичисляється за текущим часом + графіком роботи складу)
- «Самовивіз сьогодні» — список найближчих пунктів видачі з наявністю
Розрахунок дати доставки — серверна логіка: робочі дні складу, регіон користувача, тип доставки. Передається як рядок у API-відповіді.
Блок опису
Rich text опис рендериться з HTML або markdown. Вимоги:
- Довгі описи сворачиваются до 5–6 рядків з кнопкою «Читати далі» (CSS
overflow+ JS для toggle) - Таблиці характеристик — окремий блок з групуванням атрибутів
- Вкладки: «Опис» / «Характеристики» / «Відгуки» / «Питання»
Вкладки реалізуються через URL hash (#reviews) або search params (?tab=reviews). Це дозволяє посилатися прямо на блок відгуків — важливо для SEO.
Блок відгуків
Відгуки — елемент конверсії та SEO-контент одночасно.
Структура:
- Агрегований рейтинг (зірочки + розподіл по баллам: гістограма 1–5)
- Кнопка «Написати відгук» (форма з рейтингом, текстом, завантаженням фото)
- Список відгуків з пагінацією (або lazy load)
- Фільтри: «Тільки з фото», «5 зірок», «Останні»
Антиспам для відгуків: дозволяємо тільки авторизованим, тільки тим, хто купив товар (перевірка за orders). Модерація — черга для менеджера.
Schema.org розмітка: AggregateRating з ratingValue, reviewCount. Це впливає на зірочки в результатах пошуку (rich snippets).
CTA — кнопка покупки
Кнопка «Купити» / «В кошик» — головний елемент сторінки. Паттерни:
- «В кошик»: додає в кошик, користувач продовжує перегляд. Підходить для магазинів з частими множинними покупками.
- «Купити зараз»: додає та перенаправляє на чекаут. Скорочує шлях для цільового покупця.
- Sticky CTA: при скролі вниз з'являється фіксована панель з ціною та кнопкою. Утримує елемент конверсії в зоні видимості.
При додаванні в кошик — feedback: анімація іконки кошика, мініпопап або drawer з підтвердженням. Користувач повинен відчути, що дія виконана.
SEO-розмітка
<!-- Open Graph для шарингу в соцсетях -->
<meta property="og:title" content="Ноутбук Apple MacBook Air 13 — Назва магазину">
<meta property="og:image" content="https://cdn.../product-main.jpg">
<meta property="og:type" content="product">
<!-- Schema.org Product -->
<script type="application/ld+json">
{
"@type": "Product",
"name": "Apple MacBook Air 13",
"image": ["https://cdn.../img1.jpg"],
"description": "...",
"brand": { "@type": "Brand", "name": "Apple" },
"offers": {
"@type": "Offer",
"price": "89990",
"priceCurrency": "RUB",
"availability": "https://schema.org/InStock"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"reviewCount": "127"
}
}
</script>
Пов'язані товари
«Подібні товари» та «З цим купують» — різні алгоритми:
- Подібні: товари тієї ж категорії з подібними атрибутами (та ж ціна, той же бренд або атрибути)
- Часто купують разом: коллаборативна фільтрація — аналіз пар товарів в одному замовленні
Продуктивність
-
LCP (головне зображення):
<img loading="eager" fetchpriority="high">, preload у<head>, WebP з fallback -
CLS (сдвиг контенту): зарезервувати місце для зображення через
aspect-ratioабо явніwidth/height -
Кеш: HTML карточки кешується на CDN (Cloudflare) з
s-maxage=300, інвалідація через API при змінені товара
Терміни
- Базова карточка (фото, ціна, варіанти, кнопка, характеристики): 2–3 тижні
- Повнофункціональна карточка (відгуки, подібні товари, sticky CTA, історія ціни, Schema.org, продуктивність): 4–6 тижнів







