Розробка порівняння товарів для інтернет-магазину

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка порівняння товарів для інтернет-магазину
Середня
~2-3 робочих дні
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розроблення функції порівняння товарів для інтернет-магазину

Функція порівняння товарів на карточці — вбудований механізм додавання в список порівняння, інтегрований у контекст перегляду каталогу та окремих товарів. На відміну від окремої системи порівняння, тут йдеться про UX-компонент: кнопку, плаваючу панель та сторінку порівняння, щільно інтегровані в основний інтерфейс магазину.

Точки входу в порівняння

Користувач може додати товар у порівняння з кількох місць:

Карточка в листингу: невелика кнопка чи іконка поруч з "У корзину". На десктопі — з'являється при наведенні, на мобайлі — завжди видна. Не повинна конкурувати за розмір з основною CTA (кнопкою покупки).

Сторінка товару: кнопка "Порівняти" поруч з розділом характеристик чи в блоку вторинних дій.

Сторінка порівняння: кнопка "Додати ще" — відкриває пошук чи перехід у каталог.

Стан кнопки: додано/не додано — синхронізовано глобально. При додаванні з листингу кнопка на сторінці товару теж відображає стан.

Збереження стану

// Zustand store для списку порівняння
interface CompareStore {
  items: number[];           // масив product_id
  maxItems: number;          // лімітліміт (зазвичай 3–5)
  add: (id: number) => void;
  remove: (id: number) => void;
  clear: () => void;
  has: (id: number) => boolean;
}

const useCompareStore = create<CompareStore>()(
  persist(
    (set, get) => ({
      items: [],
      maxItems: 4,
      add: (id) => {
        const { items, maxItems } = get();
        if (items.length >= maxItems) {
          toast.error(`Можна порівнювати не більше ${maxItems} товарів`);
          return;
        }
        if (!items.includes(id)) set({ items: [...items, id] });
      },
      remove: (id) => set({ items: get().items.filter(i => i !== id) }),
      clear: () => set({ items: [] }),
      has: (id) => get().items.includes(id),
    }),
    { name: 'compare-list' } // зберігаємо в localStorage
  )
);

Плаваюча панель порівняння

Коли користувач листає каталог та додає товари, внизу екрана з'являється fixed-панель з поточним списком.

function CompareBar() {
  const { items, remove, clear } = useCompareStore();

  if (items.length === 0) return null;

  return (
    <div className="fixed bottom-0 left-0 right-0 z-50 bg-white border-t shadow-lg p-4
                    translate-y-0 transition-transform duration-300">
      <div className="max-w-screen-xl mx-auto flex items-center gap-4">
        <span className="text-sm text-gray-500">
          Порівняння: {items.length} товар
        </span>
        <div className="flex gap-2 flex-1">
          {items.map(id => (
            <CompareBarItem key={id} productId={id} onRemove={() => remove(id)} />
          ))}
        </div>
        <Link href={`/compare?ids=${items.join(',')}`}>
          <Button>Порівняти</Button>
        </Link>
        <button onClick={clear} className="text-gray-400 hover:text-gray-600">
          Очистити
        </button>
      </div>
    </div>
  );
}

CompareBarItem — маленьке фото + назва + кнопка видалення. Назва обрізується до 2–3 слів. При додаванні нового товару — анімація (товар «прилітає» у панель).

Сторінка порівняння

Дані товарів завантажуються за масивом ID з URL:

// /compare?ids=42,117,203
const ids = searchParams.get('ids')?.split(',').map(Number) ?? [];
const { data: products } = useSWR(
  ids.length ? `/api/compare?ids=${ids.join(',')}` : null,
  fetcher
);

API-endpoint повертає товари з повним набором атрибутів для порівняння. Важливо: якщо ID не існує чи товар знятий з продажу — повертаємо часткові дані з флагом unavailable, а не помилку.

Таблиця порівняння

Специфіка e-commerce-порівняння (на відміну від окремої системи порівняння): тут користувач зазвичай порівнює 2–4 товари однієї категорії, тому атрибути більш однорідні.

Ключові UX-паттерни:

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

.compare-header {
  position: sticky;
  top: var(--navbar-height);
  z-index: 10;
  background: white;
}

Підсвітлення різниць: строки, де значення різняться — виділяються (фон, bold). Строки з однаковими значеннями — складаються або відображаються приглушено.

Кнопки дій у шапці: "У корзину" / "Видалити з порівняння" прямо під фото кожного товару, без потреби переходити на карточку.

«Додати ще»: остання колонка — placeholder з пошуком. Користувач може додати товар прямо зі сторінки порівняння через inline-пошук.

Порівняння з контекстом: «найкращий вибір»

Опціональна фіча: система помічає «переможця» у кожній характеристиці. Реалізація через флаг highlight_if_best в атрибуті + логіку визначення найкращого значення (min/max для числових).

function CompareCell({ value, isBest, attributeDirection }: Props) {
  return (
    <td className={cn('p-3 text-center', isBest && 'bg-green-50 font-semibold text-green-700')}>
      {value}
      {isBest && <span className="ml-1 text-xs">✓</span>}
    </td>
  );
}

Не застосовувати до атрибутів типу «колір», «матеріал» — для них «найкращого» не існує.

Синхронізація між вкладками

Якщо користувач відкрив кілька вкладок, список порівняння повинен бути одинаковим. localStorage за замовчуванням не сповіщає інші вкладки. Рішення — storage event:

window.addEventListener('storage', event => {
  if (event.key === 'compare-list') {
    useCompareStore.getState().hydrate(JSON.parse(event.newValue ?? '{}'));
  }
});

Zustand з persist-плагіном обробляє це автоматично при правильній налаштуванні.

SEO-аспекти

Сторінки порівняння з конкретними ID (/compare?ids=42,117) — закрити від індексації (noindex). Вони не дають SEO-цінності та створюють дублі. Canonical — нема сенсу проставляти.

Якщо генеруються «популярні порівняння» з редакційним контентом («Порівняння iPhone 15 vs Samsung S24»), такі сторінки — статичні, зі своїм URL та унікальним текстом. Вони індексуються та ранжуються за порівняльними запитами.

Аналітика

  • Які товари чаще всього порівнюють разом — сигнал для «схожих товарів»
  • Конверсія зі сторінки порівняння: з яких пар замовляють, а з яких уходять
  • Який товар частіше «перемагає» в порівняннях (беруть його, а не альтернативу)
-- Пари товарів, які частіше всього порівнюють
SELECT
  LEAST(product_a, product_b) AS p1,
  GREATEST(product_a, product_b) AS p2,
  COUNT(*) AS compare_sessions
FROM compare_sessions
GROUP BY 1, 2
ORDER BY 3 DESC;

Терміни

  • Кнопка + localStorage + плаваюча панель: 3–5 робочих днів
  • Сторінка порівняння з таблицею атрибутів та підсвітленням різниць: 1–2 тижні
  • З «найкращим вибором», inline-додаванням, аналітикою: 2–3 тижні