Разработка блока "ранее просмотренные" 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка блока "ранее просмотренные" 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка блока "ранее просмотренные" 1С-Битрикс

«Ранее просмотренные» — блок, который показывает товары, которые пользователь открывал в текущей или прошлой сессии. Классический инструмент удержания: пользователь уходит со страницы, потом возвращается — и не ищет товар заново. Особенно ценен на мобильных устройствах, где история браузера неудобна.

Где хранить историю просмотров

Вариант 1: localStorage (браузер). Максимально простая реализация. JavaScript сохраняет ID просмотренных товаров в localStorage. При загрузке страницы — читает список, отправляет AJAX-запрос с ID, получает актуальные данные о товарах.

Плюсы: работает без авторизации, без нагрузки на сервер. Минусы: история не синхронизируется между устройствами, пропадает при очистке браузера.

Вариант 2: Сервер (база данных). Для авторизованных пользователей история хранится на сервере. Анонимные — в localStorage или через b_sale_fuser (guestID).

Вариант 3: Гибридный. Анонимный пользователь — localStorage + кеш на сервере по fuser_id. После авторизации — история мигрирует в аккаунт. Наиболее полноценный вариант.

Реализация через localStorage (быстрый вариант)

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

// 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]);

Серверное хранение для авторизованных пользователей

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-реализация + AJAX-обработчик 2–3 дня
Серверное хранение для авторизованных 2–3 дня
Миграция истории при авторизации 1 день
Страница истории в личном кабинете 1–2 дня
Тестирование (кросс-браузер, мобайл) 1–2 дня

Итого: 1–1.5 недели для полного варианта. localStorage-only — 3–4 дня.