Користувач знаходить товар, відкриває картку, дивиться характеристики — і йде. Через годину повертається, але не може згадати, який саме товар дивився. Без блоку «раніше переглянуті» ви втрачаєте до 30% повторних візитів. Особливо критично на мобільних пристроях: історія браузера незручна, а вкладки плутаються.
Реалізація блоку раніше переглянутих в 1С-Бітрікс — завдання, яке ми вирішували для 30+ інтернет-магазинів. У цій статті розберемо три підходи до зберігання історії: localStorage, серверне зберігання та гібрид. Ви дізнаєтеся, як реалізувати кожен варіант і уникнути типових помилок. Вартість розробки розраховується індивідуально, а економія на повторній розробці може сягати 30% при правильному виборі підходу. Зв'яжіться з нами для консультації по вашому проекту.
Як реалізувати блок «раніше переглянуті» на Бітріксі?
Блок «раніше переглянуті» — механізм, який запам'ятовує ID товарів, переглянутих користувачем, і виводить їх на сторінці. Є три підходи до зберігання історії: localStorage, серверна база даних та гібридний. Вибір залежить від того, чи потрібна синхронізація між пристроями та робота без авторизації.
localStorage: швидко, але без синхронізації
localStorage — найпростіше рішення. JavaScript зберігає ID переглянутих товарів у браузері. При завантаженні сторінки список передається на сервер через AJAX, сервер повертає актуальні дані (ціна, наявність, знижка). Працює без авторизації та не створює навантаження на базу даних. Недолік — історія прив'язана до одного пристрою та очищається при скиданні браузера.
Серверне зберігання: синхронізація, але тільки для авторизованих
Для авторизованих користувачів історію зберігаємо в MySQL в таблиці custom_user_recently_viewed. Кожен перегляд — запис з user_id, product_id та часом. Це дає синхронізацію між пристроями, але вимагає авторизації. Анонімні користувачі залишаються без історії, якщо не використовувати b_sale_fuser (guestID).
Гібридний підхід: краще з двох світів
Гібрид — анонімні користувачі отримують localStorage, авторизовані — сервер. При авторизації історія мігрує з localStorage в базу. Це повноцінне рішення: і для неавторизованих, і для постійних клієнтів. За нашими даними, гібридний підхід кращий за localStorage у 2–3 рази по утриманню користувачів між пристроями. Замовте розробку блоку під ключ — ми підберемо оптимальну схему.
Чому варто обрати гібридний підхід?
Якщо у вас інтернет-магазин з високим відсотком авторизованих користувачів, гібрид обов'язковий. Він зберігає історію навіть при зміні пристрою. Реалізація складніша, але окупається лояльністю. Згідно документації 1С-Бітрікс, для зберігання історії рекомендується використовувати окрему таблицю з оптимізованими індексами.
Поетапна інструкція: гібридний підхід
- Встановіть JavaScript-трекер на сторінку картки товару для збереження ID в localStorage.
- Створіть AJAX-обробник, що повертає дані товарів за переданими ID.
- Реалізуйте серверне зберігання для авторизованих користувачів з таблицею
custom_user_recently_viewed. - Напишіть скрипт міграції історії з localStorage в базу при авторизації.
- Виведіть блок на сторінці та в особистому кабінеті.
Реалізація: localStorage та AJAX-обробник
- Напишіть JavaScript-трекер, який зберігає ID товару в localStorage.
- Створіть AJAX-обробник на PHP, який повертає дані товарів за переданими ID.
- Виведіть блок на сторінці, приховуючи його при відсутності історії.
JavaScript-трекер
const STORAGE_KEY = 'viewed_products';
const MAX_ITEMS = 20;
// Викликається при завантаженні картки товару
function trackProductView(productId) {
let viewed = getViewedProducts();
// Видаляємо якщо вже є (перемістимо на початок)
viewed = viewed.filter(id => id !== productId);
// Додаємо на початок
viewed.unshift(productId);
// Обмежуємо розмір
if (viewed.length > MAX_ITEMS) {
viewed = viewed.slice(0, MAX_ITEMS);
}
localStorage.setItem(STORAGE_KEY, JSON.stringify(viewed));
}
function getViewedProducts() {
try {
return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
} catch {
return [];
}
}
// Завантаження даних для блоку
function loadRecentlyViewed(currentProductId, containerId, limit = 8) {
const viewed = getViewedProducts()
.filter(id => id !== currentProductId)
.slice(0, limit);
if (viewed.length === 0) {
document.getElementById(containerId).style.display = 'none';
return;
}
fetch('/ajax/recently-viewed/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ ids: viewed }),
})
.then(r => r.json())
.then(data => renderRecentlyViewed(data.products, containerId));
}
AJAX-обробник на PHP
// local/ajax/recently-viewed/index.php
\Bitrix\Main\Loader::includeModule('iblock');
\Bitrix\Main\Loader::includeModule('catalog');
$ids = array_filter(array_map('intval', json_decode(file_get_contents('php://input'), true)['ids'] ?? []));
if (empty($ids) || count($ids) > 20) {
echo json_encode(['products' => []]);
exit;
}
// Зберігаємо порядок з localStorage
$result = [];
$products = [];
$res = \CIBlockElement::GetList(
[],
['ID' => $ids, 'IBLOCK_ID' => CATALOG_IBLOCK_ID, 'ACTIVE' => 'Y'],
false,
false,
['ID', 'NAME', 'DETAIL_PAGE_URL', 'PREVIEW_PICTURE']
);
while ($product = $res->GetNext()) {
$productId = $product['ID'];
$product['PRICE'] = \CPrice::GetBasePrice($productId);
$products[$productId] = $product;
}
// Відновлюємо порядок переглядів
foreach ($ids as $id) {
if (isset($products[$id])) {
$result[] = $products[$id];
}
}
header('Content-Type: application/json');
echo json_encode(['products' => $result]);
Серверне зберігання та міграція історії
Для авторизованих користувачів зберігаємо історію в базі. При авторизації переносимо дані з localStorage.
Схема таблиці
CREATE TABLE custom_user_recently_viewed (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL,
product_id INT NOT NULL,
viewed_at DATETIME DEFAULT NOW(),
UNIQUE KEY uk_user_product (user_id, product_id),
INDEX idx_user (user_id, viewed_at DESC)
);
// При авторизованому перегляді
if ($USER->IsAuthorized()) {
$userId = $USER->GetID();
// INSERT або UPDATE viewed_at
Application::getConnection()->query("
INSERT INTO custom_user_recently_viewed (user_id, product_id, viewed_at)
VALUES ({$userId}, {$productId}, NOW())
ON DUPLICATE KEY UPDATE viewed_at = NOW()
");
// Обмежуємо історію 50 записами
Application::getConnection()->query("
DELETE FROM custom_user_recently_viewed
WHERE user_id = {$userId}
AND id NOT IN (
SELECT id FROM (
SELECT id FROM custom_user_recently_viewed
WHERE user_id = {$userId}
ORDER BY viewed_at DESC
LIMIT 50
) t
)
");
}
Міграція історії при авторизації
Після успішного входу анонімного користувача переносимо історію з localStorage в базу:
// При події успішної авторизації
document.addEventListener('userLoggedIn', function(e) {
const viewed = getViewedProducts();
if (viewed.length === 0) return;
fetch('/ajax/sync-viewed-history/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ ids: viewed, user_id: e.detail.userId }),
});
});
Відображення в особистому кабінеті
Розділ «Історія переглядів» в особистому кабінеті — повний список з можливістю очищення. Показуємо до 100 останніх товарів з пагінацією. Кнопка «Очистити історію» — DELETE з custom_user_recently_viewed по user_id + очищення localStorage.
Порівняння підходів
| Підхід | Синхронізація | Без авторизації | Складність | Рекомендація |
|---|---|---|---|---|
| localStorage | Ні | Так | Низька | Для невеликих проектів |
| Серверне зберігання | Так | Ні | Середня | Для авторизованих користувачів |
| Гібрид | Так | Так | Висока | Для повноцінного досвіду |
Що входить в роботу
- Аналіз поточної архітектури каталогу та користувацьких сесій
- Проектування схеми зберігання (localStorage, БД або гібрид)
- Розробка JavaScript-трекера та AJAX-обробника
- Реалізація серверного зберігання з оптимізацією запитів
- Міграція історії при авторизації
- Сторінка історії в особистому кабінеті
- Тестування: крос-браузерне, мобільне, навантажувальне
- Документація по доробках та інструкція для контент-менеджерів
- Code-review та передача доступів
- Підтримка протягом 2 тижнів після здачі
Терміни орієнтовно
| Етап | Термін |
|---|---|
| localStorage-реалізація + AJAX-обробник | 2–3 дні |
| Серверне зберігання для авторизованих | 2–3 дні |
| Міграція історії при авторизації | 1 день |
| Сторінка історії в особистому кабінеті | 1–2 дні |
| Тестування (крос-браузер, мобайл) | 1–2 дні |
Разом: 1–1.5 тижні для повного варіанту. localStorage-only — 3–4 дні.
Типові помилки при розробці
- Не враховувати ліміт localStorage (5–10 МБ) — при великому каталозі історія обрізається без попередження.
- Виводити поточний товар в блоці — користувач бачить те, що вже дивиться.
- Не кешувати AJAX-запити — при кожному вході на сторінку буде запит, навіть якщо історія не змінилася.
- Не очищати дублікати в localStorage — при частих переходах масив росте безконтрольно.
- Пропускати обробку випадку, коли користувач очистив кеш браузера — код повинен коректно обробляти відсутність даних.
Замовте розробку блоку «раніше переглянуті» під ключ. Оцінимо ваш проект за 1 день та запропонуємо оптимальне рішення. Отримайте консультацію — понад 50 проектів гарантують якість.







