Перейти к содержимому
Эльдар Шахвалиев
Обсудить проект
← Все проекты
202602.2026 — наст. времяВ продеполный цикл

Arctic-M — каталог-витрина систем охлаждения ARCTIC

Официальный российский дистрибьютор бренда систем охлаждения для ПК · E-commerce / каталог-витрина, компьютерные комплектующие (системы охлаждения)

Независимый fullstack/backend WordPress-разработчик (единственный исполнитель)

Сайт-витрина официального дистрибьютора 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
  • поддержка