Інтернет-магазини

Колесо Трейдінг: повне оновлення інтернет-магазину шин

Магазин шин на 17 тисяч позицій: новий інтерфейс, три способи підбору, пришвидшення у п’ять разів і перебудована структура каталогу — без зупинки продажів.

Ніша
Шини
Тип проєкту
Повне оновлення інтернет-магазину шин
Платформа
OpenCart 3
Адреса
koleso-trading.com
Колесо Трейдінг — екран 1
Колесо Трейдінг — екран 2
Колесо Трейдінг — екран 3
01 Завдання

Магазин працював і приносив замовлення, але виріс швидше за свій код. Каталог на 17 тисяч шин оновлювався нічним вивантаженням постачальника, і це вивантаження не вкладалося у відведений час, а за збою в постачальника могло обнулити каталог цілком. Журнал помилок доріс до 6,4 ГБ, база — до 7,3 ГБ, з яких 7,1 ГБ займали прострочені сесії. У карток товарів не було ні людських адрес, ні canonical, і 42 % каталогу перестворювалося за місяць — проіндексовані сторінки постійно відмирали. Карти сайту не було взагалі. Головна відповідала від однієї до шести секунд. Окрема біда — підбір: покупець, який знає лише марку своєї машини, знайти шини не міг, а пошук відділення Нової Пошти не працював зовсім.

02 Рішення

Спершу підняли повну копію магазину з окремою базою — усе робилося на ній, бойовий сайт не зупинявся жодного дня. Тему вирішили не переписувати: у ній 13 власних модулів, і 31 із 39 встановлених патчів зав’язаний на її шаблони. Натомість завели свій шар стилів, що під’єднується останнім, і переписали інтерфейс поверх робочого рушія — картку товару, шапку з мегаменю, фільтр, оформлення замовлення, темну тему й усю адаптацію під телефон. Паралельно переробили те, чого не видно: структуру каталогу, постійні адреси товарів, нічний обмін, кешування та індекси. Перемикання на нову версію зайняло 11 хвилин простою.

03 Результат

Головна відповідає за 0,2 секунди замість шести, нічне оновлення каталогу минає за 74 секунди одним проходом, адреса картки більше не змінюється ніколи, а карта сайту на 35 тисяч адрес перезбирається щоночі. Покупець добирає шини трьома способами — за типорозміром, за автомобілем і різноширокими комплектами, — бачить ціни всіх складів в одній картці й отримує робочу доставку Новою Поштою. Заявки дублюються в Telegram, форми закриті від ботів.

Що зробили

Склад робіт за проєктом

Інтерфейс переписано поверх теми

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

Три способи підбору шин

За типорозміром, за маркою та моделлю автомобіля й окремий підбір різношироких комплектів, якого звичайний фільтр зібрати не може.

Ціни всіх складів у картці

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

Структура каталогу та адреси

Корінь «Шини», чотири типи транспорту, 15 сезонних посадкових сторінок і постійна адреса в кожної картки замість посилання з номером товару.

Пришвидшення у п’ять разів

Індекси, кеш списків і рушія, прогрів після нічного обміну, відкладене завантаження картинок і власні шрифти без звернень до Google.

Нічний обмін переписано

74 секунди замість чотирьох завдань поспіль, захист від порожнього прайсу та відмова від видалення товарів — позиція, що повернулася, отримує попередню адресу.

5,7 → 0,2 с
відповідь головної сторінки
74 с
повне оновлення каталогу
11 хв
простій під час перемикання
~35 000
адрес у карті сайту

Що всередині

  • OpenCart 3
  • PHP
  • MySQL
  • собственный слой стилей
  • ocmod
  • SEO-структура
Початковий стан

З чого починали

Найперше розібрали журнали та базу — ще до жодної правки в коді. Файл помилок займав 6,4 ГБ, і 99,98 % його вмісту виявилися однією повторюваною помилкою в генераторі товарного фіда: близько 1,1 мільйона однакових записів. За нею в лозі ховалося все інше — зокрема помилки добірника шин і Нової Пошти, які саме й ламали покупцеві сценарій замовлення.

У базі 7,1 ГБ із 7,3 займала таблиця сесій із 26,8 мільйонами прострочених рядків. Причина виявилася в одному рядку драйвера: термін життя сесії порівнювався з датою як із числом, тому прибиральник не видаляв нічого й ніколи. З тієї ж причини сесії не спливали взагалі.

Окремо перевірили, що доступне з інтернету. У службовій теці лежав скрипт, який очищає товарні таблиці шістьма запитами, і відкривався він за прямим посиланням ким завгодно. Теку закрили двома рубежами, а самі скрипти навчили запускатися лише з командного рядка.

Що дивилисяБулоСтало
Відповідь головної сторінки1–5,7 секунди0,2 секунди
Вітрина каталогу4,5 секунди1,0 секунди
Сторінка фільтра3,7–5,4 секунди0,4–1,3 секунди
Нічне оновлення каталогуне вкладалося в чотири завдання поспіль74 секунди одним проходом
Журнал помилок6,4 ГБ, 1,1 млн однакових записівпорожній
Таблиця сесій7,1 ГБ, 26,8 млн прострочених рядківчиститься щоночі, вікно 20 днів
Адреса картки товару/shiny?product_id=1530939, без canonical/continental-wintercontact-ts-870p-225-55-r17-97h
Карта сайтубула відсутняблизько 35 000 адрес, збирається щоночі
Сторінки брендів614 порожніх віддавали 200, а 68 робочих — 404порожні ховаються самі, робочі відкриті
Розділи каталогуусі шини в одному розділі, мотошини вимкненічотири типи транспорту та 15 сезонних сторінок
Відділення Нової Поштипошук міста не працював узагаліпрацює
Головна до оновлення
Головна до оновлення
Головна після оновлення
Головна після оновлення
Дизайн та інтерфейс

Новий вигляд поверх працюючого магазину

Переписувати тему з нуля ми не стали, і це було свідоме рішення, а не економія. У темі 13 власних модулів, а 31 із 39 встановлених у магазині патчів править саме її шаблони: заміна теми означала б переробку всього магазину разом і зупинку продажів на тижні.

Натомість завели власний шар стилів, який під’єднується останнім і нічого в темі не затирає. Там, де правки стосувалися шаблонів, вони вносилися і в оригінал, і в зібрану рушієм копію — інакше перше ж натискання «оновити модифікації» в адмінці стерло б усе без жодної помилки в журналі.

Картка товару

Зібрана заново: назва у два рядки — бренд із моделлю й окремо типорозмір, логотип бренду, позначка наявності, характеристики плашками під фотографією, блоки з описом, європейською етикеткою, схожими моделями та відгуками.

Склади й ціни по містах

Замість таблиці — плашки: місто, рік випуску, залишок і країна з прапором у кожної пропозиції. Вони відсортовані за ціною, найкращу позначено, а вибір складу підставляється у форму замовлення, щоб покупка не пішла не з того міста.

Шапка й мегаменю

Пошук із підказками, два номери зі значками операторів, перемикач мови та нічного режиму, плашки ходових діаметрів. У мегаменю — типи транспорту, сезони, бренди й типорозміри одним екраном.

Бічний фільтр

Списки розмірів із пошуком усередині, поділом на ходові та решту й чесними лічильниками. Окрема галочка вмикає режим різношироких шин із двома осями.

Темна тема

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

Адаптив

Нижче 1200 пікселів фільтр іде у висувну панель, а вітрина займає ширину екрана; нижче 992 шапка перебудовується у два рядки. На пристроях без миші мегаменю відкривається натисканням — раніше воно блимало й одразу йшло на сторінку каталогу.

Оформлення замовлення

Односторінкове оформлення приведене до стилю сайту: форми ліворуч, кошик праворуч і їде за прокруткою, поля й кнопки в спільній геометрії, своя нічна тема. На телефоні кошик іде першим.

Єдина система підказок

Один механізм на весь сайт: досить позначити елемент — і підказка з’явиться біля курсора. Написаний без зайвих залежностей і працює на динамічно доданих блоках.

Картка товару: пропозиції всіх складів із цінами, роком випуску та залишком
Картка товару: пропозиції всіх складів із цінами, роком випуску та залишком
Та сама вітрина в нічному режимі
Та сама вітрина в нічному режимі
Функціонал

Як покупець знаходить свій розмір

Шини шукають трьома різними способами, і кожен потребує свого механізму. Хтось переписує розмір із боковини, хтось знає лише марку та рік машини, а в частини автомобілів спереду й ззаду стоять різні шини — такий комплект звичайний фільтр каталогу зібрати не може в принципі, бо умова «у моделі є обидві осі в наявності» стосується моделі, а не товару.

Тому підбір зроблено трьома входами, і всі три доступні з головної, із шапки та з фільтра.

Підбір за типорозміром

Ширина, висота, діаметр плюс бренд, сезон і шипи. Списки пов’язані між собою: обрана ширина залишає лише ті висоти й діаметри, які з нею справді бувають.

Підбір за автомобілем

Марка, модель, рік і двигун. Результат розкладено на заводську комплектацію та варіанти заміни, а якщо в машини різноширокий комплект — його показано однією плашкою з передньою й задньою віссю, а не пласким списком, у якому не розібрати, де перед, а де зад.

Різноширокі комплекти

Окрема сторінка підбору: дві осі зі своїми списками та лічильниками моделей, у результаті — модель з обома осями, цінами й кнопкою купівлі на кожну. Підбір можна перезібрати просто на сторінці.

Європейська етикетка

Витрата пального, зчеплення на мокрій дорозі та шум винесені на картку значками, поруч — вікно з розшифруванням. Самі етикетки перенесені до себе й довантажуються вночі, а не тягнуться з чужого сервера при кожному показі.

Моделі шин як окрема сутність

1220 моделей зі своїми сторінками, адресами й текстами. Тексти зберігаються окремо від товарів, тому нічне вивантаження їх не затирає — це й була головна вимога власника.

Популярні типорозміри

Окрема сторінка та блок на головній: у кожному розмірі — сезони, що є в наявності, і бренди цього розміру.

Сповіщення в Telegram

Нове замовлення, зворотний дзвінок, заявка «знайшли дешевше», повідомлення з форми, відгук, підписка та реєстрація. У замовленні — склад із посиланнями на товари, доставка, оплата й телефон у тому вигляді, який Telegram сам робить клікабельним.

Захист форм від ботів

Після того як у заявки полетів спам, поставили чотири незалежні заслони: невидиме поле-пастку, позначку відкриття форми, обмеження частоти й маску номера. Усі відповідають однаковою помилкою, щоб із відповіді не можна було зрозуміти, який спрацював.

Доставка й оплата

Полагоджено пошук міста та вибір відділення Нової Пошти — він не працював узагалі, покупець завжди бачив «не знайдено». Готівка й термінал доступні лише за самовивозу, способи оплати впорядковані.

Сторінка популярних типорозмірів: сезони в наявності та бренди під кожен розмір
Сторінка популярних типорозмірів: сезони в наявності та бренди під кожен розмір
Продуктивність

Де магазин втрачав секунди

Власник поскаржився на затримку в три-чотири секунди під час переходу на головну. Замір показав розкид від однієї до 5,7 секунди, і причина знайшлася швидко: шість запитів, які наповнюють списки в блоці підбору, виконувалися заново на кожній сторінці, де цей блок є, і разом займали 4,26 секунди. Вони перебирали таблицю атрибутів на 1,17 мільйона рядків.

Лікування виявилося в три кроки: складений індекс на таблицю атрибутів, добовий кеш списків (дані змінюються лише після нічного обміну, тримати їх живими немає потреби) і прогрів кешу наприкінці нічного оновлення — щоб перезбирання не оплачував перший ранковий відвідувач.

Окрема знахідка: кеш самого рушія писався, але не читався — у бібліотеці кешу стояла умова, за якою записи віддавалися лише для довідника міст. Читання повернули, а скидання повісили на кінець нічного обміну. Це й дало основний виграш на всіх сторінках одразу.

  • Нічний обмін переписано: повний прогін за 74 секунди замість чотирьох завдань поспіль, пам’ять 59 МБ замість сотень, пошук товарів усередині прогону — 3 секунди замість 85.
  • Два складені індекси на таблицю товарів: план запиту змінився з перебору 17 тисяч рядків на вибірку одного.
  • Довідник атрибутів перечитувався запитом на кожен атрибут кожного товару — близько 190 тисяч зайвих запитів за прогін. Замінено кешем у пам’яті.
  • Відкладене завантаження картинок проставлене в шаблонах — 57 тегів; на головній відкладається 34 зображення зі 101, і найбільше виграє меню з логотипами брендів.
  • Шрифт перенесено до себе: 10 файлів за мовними підмножинами замість запиту до шрифтів Google, на який чекала кожна сторінка.
  • Нічне чищення сесій порціями по 50 тисяч рядків, із власним індексом і обмеженням за часом — таблиця більше не росте.
СторінкаБулоСтало
Головна1,2 с0,2 с
Вітрина каталогу4,5 с1,0 с
Сторінка фільтра3,7–5,4 с0,4–1,3 с
Картка товару0,9–3,9 с0,37 с
Перше відмальовування в браузері6,3 с1,8 с
Повне завантаження головної8,4 с3,5 с
SEO та технічна частина

Структура, адреси та індексація

Головною SEO-проблемою були не тексти, а адреси. Картка відкривалася як /shiny?product_id=1530939, причому префікс залежав від того, звідки прийшов відвідувач, canonical не було зовсім, а нічний обмін видаляв вибулі товари й заводив ті, що повернулися, заново — з новим номером. За вісім місяців було витрачено близько 623 тисяч номерів при 17 тисячах товарів у каталозі; 42 % каталогу перестворювалося протягом місяця. Проіндексовані сторінки просто відмирали.

Три зміни довелося робити однією зв’язкою, окремо вони не працюють: обмін перестав видаляти товари, адреса стала збиратися з того, що не змінюється, і видана адреса більше не перераховується.

Постійна адреса в картки

Збирається із замороженого слага моделі й типорозміру, а не з назви, яку постачальник править (274 правки за вісім прогонів). Видається один раз і зберігається у власному реєстрі. Старі адреси з номером товару віддають 301 на коротку.

Товари більше не видаляються

Вибула позиція лишається з нульовим залишком і зникає зі списків і фільтрів; повернулася в прайс — повернулася з тією самою адресою. Не з’являлася рік — виводиться з каталогу й віддає 410 Gone: для пошуковика це «сторінки більше не буде».

Структура каталогу

Корінь «Шини», під ним чотири типи транспорту, а сезони — окремі посадкові сторінки зі своїми заголовками й метатегами, 15 штук. Схема обійшлася без правки стороннього модуля фільтра, тому переживе його оновлення.

Білий список індексації

Індексуються корінь, чотири розділи й сезонні сторінки; будь-які інші комбінації фільтрів працюють для покупця, але в індекс не йдуть. Заразом виправлено заборону обходу посилань, через яку робот не діставався до товарів.

Бренди впорядковано

Із 731 бренда товари були в 117: 614 порожніх сторінок віддавали код 200 з порожнім вмістом. Порожні тепер ховаються автоматично, а 68 брендів із товарами, які роками віддавали 404 через відсутній запис у базі, знову відкриваються.

Власна карта сайту

Штатний модуль був вимкнений, а сервер усе одно перенаправляв на нього — звідси порожня відповідь. Написано свій генератор: близько 35 тисяч адрес у кількох файлах, збирання наприкінці нічного обміну.

robots.txt під нову структуру

Каталог, бренди та інформаційні сторінки відкриті; службові маршрути, кошик, оформлення, сортування й посторінкова навігація закриті, як і всі 28 параметрів фільтра.

Редиректи та фід

Усі адреси колишнього сайту прогнані запитами: жодна не йде в 404. У товарному фіді для Google третина позицій не вивантажувалася — причину знайшли й усунули.

Процес

Як ішла робота

Магазин працює і приносить замовлення щодня, тому правила були прості: нічого не перевіряти на бойовому сайті й не зупиняти продажі.

Розбір

Журнали, база, код нічного обміну, структура каталогу й те, що доступне з інтернету. До першої правки стало зрозуміло, що лагодити насамперед, а що лише здається проблемою.

Копія магазину

Повна копія з окремою базою, закрита паролем і забороною індексації, з вимкненою аналітикою та переписаними посиланнями на бойовий домен. Усі роботи йшли на ній.

Ітерації за списками зауважень

Власник дивився копію й надсилав зауваження списками, ми розбирали їх по порядку. Кожна правка перевірялася на живих даних, перед кожною — резервна копія.

Перемикання

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

Доведення після запуску

Повернено аналітику, переписано robots.txt, перевірено всі редиректи, зібрано карту сайту, налаштовано нічне чищення сесій і прогрів кешу. Стару версію збережено окремо й закрито від пошуковиків.

Запитання

Що зазвичай запитують про цей проєкт

Бо в темі магазину 13 власних модулів, а 31 із 39 встановлених патчів править саме її шаблони. Заміна теми означала б переписати магазин цілком і зупинити продажі на тижні. Власний шар стилів і точкові правки дали той самий результат за зовнішнім виглядом, але без простою.

Ні. Усе робилося на повній копії з окремою базою, бойовий сайт продовжував приймати замовлення. Зупинка була одна — 11 хвилин у момент перемикання, під заглушкою з кодом 503, яка пояснює пошуковику, що це тимчасово.

Нічого. Адреса збирається зі слага моделі й типорозміру, видається один раз і більше не перераховується, а вибулі товари не видаляються — вони просто перестають показуватися. Повернулася позиція в прайс — відкривається за попередньою адресою.

Бо поки в них немає текстів. Сутність, адреси, сторінки та розділ адмінки готові, 1220 моделей заведено. Власник наповнює їх описами — після цього сторінки відкриються для індексу й потраплять у карту сайту наступної ж ночі.

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

Так, підхід не залежить від CMS: розбір вузьких місць, копія для робіт, свій шар поверх наявного коду й перемикання з мінімальним простоєм. Ми так само працюємо з WordPress, WooCommerce і самописними каталогами.

Потрібен схожий проєкт?

Розберемо ваше завдання, покажемо варіанти рішення й назвемо терміни з кошторисом. Безкоштовно та без зобов’язань.