Arctic-M — каталог-витрина систем охлаждения ARCTIC
Официальный российский дистрибьютор бренда систем охлаждения для ПК · E-commerce / каталог-витрина, компьютерные комплектующие (системы охлаждения)
Сайт-витрина официального дистрибьютора ARCTIC: покупка идёт на маркетплейсах, задача сайта — показать товар и довести до нужной карточки.
- PHP
- WordPress
- JavaScript
- MySQL
- MariaDB
- SQL
- HTML
- CSS/SCSS
- SCF
- REST API
- Ozon/WB/YM API
- Redis/Valkey
- Nginx
- VPS
- WP-CLI
- адаптивная вёрстка
В цифрах
- ~17 мин
- downtime при hard-cutover миграции на прод arctic-m.com
- 232
- URL-замен (search-replace) при миграции test→prod
- 1.3 GB / 5142 файла
- перенесённые uploads; 53 таблицы БД импортированы
- 7/7
- smoke-тестов пройдено после деплоя (home/catalog/product/admin/REST/sitemap)
- 65
- товаров с отзывами по вариациям по 3 маркетплейсам (v1.4.0)
- ~116 000
- отзывов учтено в Schema.org-рейтинге по всему каталогу
- 2851 / 3119 (91%)
- отзывов в БД привязано к конкретной вариации после пересинка
- ~132 поля / 15 групп
- объём SCF-архитектуры (8 options + 4 CPT + 3 таксономии)
- 138
- коммитов в репозитории темы/сайта (GSD, conventional commits)
- ~80+
- веб-запросов в параллельном research по деплою (Docker vs simple)
Ключевое
- Одна модель кулера живёт в нескольких исполнениях, у каждого своя галерея, свои характеристики и свои отзывы на трёх площадках. Собрал это в единую карточку.
- Написал расширение, которое само забирает отзывы с трёх площадок по расписанию и переживает их недоступность без падения сайта.
- Нашёл скрытую ошибку: при обновлении отзывов каждое следующее исполнение затирало отзывы предыдущего, и до карточки доезжали не все.
- 91% отзывов в базе привязаны к конкретному исполнению товара — 2851 из 3119; в рейтинге для поисковиков учтено около 116 000 отзывов.
- Переезд с тестового сервера на боевой домен занял около 17 минут недоступности, после него 7 проверок из 7 прошли успешно.
Задача
Официальный дистрибьютор ARCTIC в России продаёт системы охлаждения для компьютеров через маркетплейсы. Собственного магазина у компании нет и не планировалось: покупка происходит на площадках, а сайт нужен, чтобы представить бренд и довести покупателя до нужной карточки товара.
Сложность в самом товаре. Одна модель кулера существует в нескольких исполнениях — с подсветкой и без, под разные размеры корпуса, — и у каждого исполнения свои характеристики, своя галерея и свои отзывы на каждой из трёх площадок. Готовая вёрстка сайта у заказчика была, но за ней не стояло ничего: ни каталога, ни редактирования, ни связи с площадками.
Что сделано
- Собрал сайт по готовой вёрстке, не меняя в ней ни одного класса: каталог с фильтрами, карточки товаров с галереей, документами и трёхмерными моделями, новости, раздел дилеров, форма обратной связи. Магазинный движок сознательно не ставил — для витрины без корзины он избыточен.
- Сделал систему исполнений товара двухслойной: менеджер заводит их в привычной форме в админке, а сайт читает из отдельной таблицы, устроенной под быстрый показ. Каждое исполнение несёт свою галерею, свои характеристики и свои ссылки на площадки.
- Написал отдельное расширение, которое по расписанию забирает отзывы с трёх площадок, складывает их у себя и переживает недоступность любой из них без падения сайта. Ключи доступа хранятся зашифрованными.
- Привязал отзывы к конкретному исполнению: покупатель переключает подсветку на карточке — блок отзывов перерисовывается без перезагрузки страницы.
- Нашёл и починил скрытую ошибку: при обновлении отзывов каждое следующее исполнение затирало отзывы предыдущего, и до карточки доезжали не все.
- Перевёз сайт с тестового сервера на боевой домен. Перед этим сравнил два способа развёртывания и выбрал более простой — дальше сайт живёт на обычном хостинге, и чинить его должно быть возможно без меня.
Итог
Сайт работает на arctic-m.com. Переезд с тестового сервера на боевой домен занял около 17 минут недоступности; после него 7 проверок из 7 прошли успешно — главная, каталог, карточка товара, админка, обмен данными и карта сайта.
Отзывы с трёх площадок собираются сами: 91% отзывов в базе привязаны к конкретному исполнению товара — 2851 из 3119, — а в рейтинге, который видят поисковики, учтено около 116 000 отзывов по всему каталогу. 65 товаров показывают отзывы отдельно по каждому исполнению.
Технические детали
Решение и подход
Архитектура каталога. Сознательный отказ от WooCommerce (избыточен для витрины без корзины) в пользу CPT + SCF; фильтрация реализована через кастомные таксономии и tax_query, а не meta_query — выбор обоснован как способ избежать медленных JOIN по wp_postmeta.
Вариации товара (гибрид). SCF-репитер даёт удобное редактирование в админке, а при сохранении хук arctic_sync_variations_to_table (priority 20, после записи метаданных SCF) синхронизирует данные в кастомную таблицу wp_arctic_product_variations с индексами по (product_id, sort_order), (product_id, is_default), (product_id, slug) — для быстрых фронтенд-запросов. Каждая вариация несёт собственную галерею, переопределения характеристик, ссылки и идентификаторы маркетплейсов (ozon_product_id, wb_article, ym_sku). Запись в таблицу — в транзакции, с генерацией уникальных слагов и гарантией единственного default.
Отзывы по вариациям (v1.4.0). Отзывы из Ozon/WB/Я.Маркет складываются в wp_arctic_reviews (UNIQUE (marketplace, external_review_id) для upsert), сводная статистика — по паре «вариация + маркетплейс». На карточке при переключении вариации блок отзывов перезагружается через AJAX (arctic_load_reviews_tab) без перезагрузки страницы, с отменой устаревших запросов при частых кликах, сохранением активной вкладки маркетплейса и переинициализацией галереи/лайтбокса. Schema.org aggregateRating считается как взвешенное среднее по всем вариациям и маркетплейсам — для rich snippets в Google/Яндексе. Особый случай Ozon: API не отдаёт отзывы по конкретной вариации, поэтому забирается вся лента продавца и разбирается по SKU на стороне сайта.
Безопасность. Формы и AJAX — с nonce и проверками; per-IP rate-limit (60 req/min, CGNAT-толерантный) на загрузку отзывов; сквозные sanitize_*/esc_*; API-ключи маркетплейсов хранятся через класс шифрования плагина. Соблюдение WPCS.
Стек и обоснование
- WordPress 6.9.4 + PHP 8.0+/8.4, Classic Theme (Underscores) — максимальный контроль для pixel-perfect переноса; Block Theme/FSE отклонён.
- SCF (Secure Custom Fields) вместо ACF — по требованию заказчика; репитеры/опшн-страницы.
- Без WooCommerce — витрина без корзины; каталог на CPT + кастомных таксономиях.
- Кастомная таблица для вариаций — производительность фронтенд-запросов вместо тяжёлого
meta_query. - Vanilla CSS + нативные ES-модули вместо Vite — осознанный отказ от сборщика (коммит «replace Vite with vanilla asset pipeline») ради принципа «SFTP → сайт работает» и моментальных правок.
- Инфраструктура: тест — VPS (Ubuntu, MariaDB, Redis, nginx/PHP-FPM); прод — shared hostland.ru (MySQL 8.0, PHP 8.4, без Redis), адаптация конфигурации под ограничения тарифа.
- Маркетплейс-API: Ozon Seller API, Wildberries Feedbacks API, Yandex Market Partner API; cron-синхронизация, логирование, graceful degradation на кэш при недоступности API, rate-limit (пауза 0.25 c).
Инженерные вызовы
- Гонка/перезапись отзязей Ozon: при синке товара с несколькими вариациями каждая следующая затирала предыдущую (отзывы хранились на уровне товара, не вариации). Решение: привязка отзыва к SKU вариации, ограничение удаления собственным SKU, отдельная сводная строка на пару «вариация+маркетплейс», временная страховка от удаления на период миграции.
- Мгновенное переключение вариаций без «миганий»: AJAX-перерисовка блока отзывов с отменой устаревших запросов, сохранением вкладки маркетплейса и переинициализацией лайтбоксов.
- Корректный агрегированный рейтинг для SEO: взвешенная формула по всем вариациям и трём маркетплейсам, публикация JSON-LD только при наличии оценок (требование Schema.org).
- Различие сред test↔prod: уход с рут-VPS (Redis, system cron, unix-socket) на shared-хостинг (нестандартный порт БД 127.0.0.1:3308, отсутствие Redis/cron-панели, переключение PHP 7.4→8.4) — точечная адаптация конфигурации, удаление висячих зависимостей плагинов, schema-only перенос таблиц Action Scheduler, атомарный
mv-switch с планом отката (snapshot www_old). - Производительность фильтрации каталога: таксономии +
tax_query+ transient-кэш реестра атрибутов вместо медленных meta-JOIN.
Услуги в проекте
- разработка
- доработка существующего
- аудит
- миграция
- деплой
- 152-ФЗ/ПДн
- SEO
- поддержка