Оптимізація сторінки кошика для зниження покинутих кошиків

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

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, 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

Оптимізація сторінки кошика для зменшення брошених кошиків

За даними Baymard Institute, середній показник брошених кошиків становить 70,19%. Половина цих втрат пов'язана з технічними та UX-проблемами, які вирішуються на рівні розробки. Решта половини пов'язана з намірами (користувач просто порівнював ціни), і тут допомагає email-ретаргетинг.

Основні причини брошених кошиків (дані Baymard)

Причина % користувачів
Непередбачені витрати (доставка, податки) 48%
Обов'язкова реєстрація 26%
Повільне завантаження / технічні помилки 17%
Недовіра при введенні даних карти 19%
Складний процес оформлення 18%

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

Показувати вартість доставки в кошику

Доставка повинна розраховуватися прямо в кошику, до оформлення замовлення. Віджет «Розрахувати доставку» з полем міста/індексу:

const ShippingCalculator: React.FC<{ cartTotal: number }> = ({ cartTotal }) => {
  const [zip, setZip] = useState('');
  const [rates, setRates] = useState<ShippingRate[]>([]);

  const calculate = async () => {
    const result = await api.post('/shipping/rates', {
      zip,
      items: cartItems,
      total: cartTotal,
    });
    setRates(result.data);
  };

  return (
    <div className="shipping-calculator">
      <input
        placeholder="Введіть індекс або місто"
        value={zip}
        onChange={e => setZip(e.target.value)}
        onBlur={calculate}
      />
      {rates.map(rate => (
        <ShippingOption key={rate.id} rate={rate} />
      ))}
      {cartTotal >= FREE_SHIPPING_THRESHOLD && (
        <FreeShippingBadge />
      )}
    </div>
  );
};

Безплатна доставка при сумі X — потужний стимул докупити. Прогрес-бар до порогу:

const threshold = 5000; // гривні
const remaining = threshold - cartTotal;

<div className="free-shipping-progress">
  <progress value={cartTotal} max={threshold} />
  {remaining > 0
    ? <span>До безплатної доставки осталося {remaining} ₴</span>
    : <span>Безплатна доставка!</span>
  }
</div>

Такий прогрес-бар збільшує середній чек на 10–30% у користувачів, які спочатку планували купити менше.

Збереження кошика

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

// Модель Cart (для авторизованих)
class CartItem extends Model {
    protected $fillable = ['cart_id', 'product_id', 'variant_id', 'quantity'];
}

// При вході — merge гостьового кошика з серверним
public function mergeGuestCart(array $guestItems): void {
    foreach ($guestItems as $item) {
        $this->items()->updateOrCreate(
            ['product_id' => $item['product_id'], 'variant_id' => $item['variant_id']],
            ['quantity' => DB::raw("quantity + {$item['quantity']}")],
        );
    }
}

Email-листи брошених кошиків

Електронна пошта через 1 годину після того, як користувач ходив із кошиком — один із найбільш конвертуючих email-тригерів (коефіцієнт відновлення 5–15%).

Тригер: при додаванні в кошик створюємо запис з abandoned_at = NULL. Якщо користувач не завершив замовлення протягом 60 хвилин і остання активність > 60 хвилин тому — помічаємо кошик як брошений.

// Запланована робота (кожні 15 хвилин)
Cart::query()
    ->where('updated_at', '<', now()->subMinutes(60))
    ->whereNull('order_id') // незавершене замовлення
    ->whereNull('abandoned_email_sent_at')
    ->with('user', 'items.product')
    ->chunk(100, function ($carts) {
        foreach ($carts as $cart) {
            SendAbandonedCartEmail::dispatch($cart);
            $cart->update(['abandoned_email_sent_at' => now()]);
        }
    });

Email містить:

  • Список товарів з фото та цінами
  • Кнопку «Повернутися до замовлення» (посилання з UTM-меткою)
  • Соціальний доказ (відгуки про товари з кошика)

Серія писем: через 1 годину, через 24 години, через 72 години. Третій лист може містити знижку — але тільки якщо перші два не спрацювали.

Upsell та cross-sell в кошику

Рекомендації повинні бути релевантними, а не випадковими. Алгоритми:

«Часто купують разом» — на основі співвідношення в історії замовлень:

SELECT
    oi2.product_id,
    COUNT(*) AS together_count
FROM order_items oi1
JOIN order_items oi2 ON oi1.order_id = oi2.order_id AND oi1.product_id != oi2.product_id
WHERE oi1.product_id = $current_product_id
GROUP BY oi2.product_id
ORDER BY together_count DESC
LIMIT 5;

«Улучши комплект» — якщо в кошику бюджетний варіант, пропонуємо преміум з різницею в ціні. Конверсія в апгрейд — 8–15%.

Мінімізація кроків до оформлення

Кнопка «Оформити замовлення» повинна бути видна без прокручування. На мобільних — фіксована панель внизу екрана:

@media (max-width: 768px) {
  .cart-checkout-btn {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 100;
    padding: 16px;
    background: white;
    box-shadow: 0 -2px 8px rgba(0,0,0,0.1);
  }
}

Індикатори наявності товару

Якщо товар закінчується, показуємо це в кошику:

{item.stock_count <= 5 && (
  <span className="low-stock-warning">
    Залишилось {item.stock_count} шт.
  </span>
)}

Це створює м'яке тиснення, не виглядаючи як маніпуляція — просто корисна інформація.

Технічні оптимізації

Optimistic UI при змінені кількості. Користувач клацає «+» — кількість миттєво змінюється в UI, запит до API йде в фоні. Якщо запит падає — откатуємо:

const updateQuantity = async (itemId: number, newQty: number) => {
  const prevQty = item.quantity;
  setItems(prev => prev.map(i => i.id === itemId ? {...i, quantity: newQty} : i));

  try {
    await api.patch(`/cart/items/${itemId}`, { quantity: newQty });
  } catch {
    setItems(prev => prev.map(i => i.id === itemId ? {...i, quantity: prevQty} : i));
    toast.error('Не вдалося оновити кількість');
  }
};

Пересчет итогов в реальном времени без перезагрузки страницы — базовое требование, но важно чтобы он был мгновенным.

Терміни

Завдання Час
Калькулятор доставки + прогрес-бар 1 день
Збереження кошика для гостей 1 день
Email-листи брошених кошиків 1–2 дні
Рекомендації (cross-sell) 1–2 дні

Разом: 3–5 робочих днів.