[{"data":1,"prerenderedAt":9988},["ShallowReactive",2],{"site-uk":3,"post-uk-core-web-vitals-dlia-vlasnyka-mahazynu":129,"blog-uk":946},{"id":4,"contacts":5,"cta":15,"extension":18,"footer":19,"meta":68,"nav":69,"serviceUi":84,"stem":127,"__hash__":128},"site_uk\u002Fuk\u002Fsite.yml",{"email":6,"telegram":7,"viber":8,"whatsapp":9,"hours":10,"city":11,"linkedin":12,"github":13,"founderLinkedin":14,"founderGithub":14},"hello@tochnodev.com","https:\u002F\u002Ft.me\u002F","viber:\u002F\u002Fchat?number=","https:\u002F\u002Fwa.me\u002F","Пн–Пт 10:00–19:00, Київ","Київ","https:\u002F\u002Fwww.linkedin.com\u002F","https:\u002F\u002Fgithub.com\u002F","",{"label":16,"to":17},"Обговорити проєкт","\u002Fbryf","yml",[20,35,56],{"title":21,"links":22},"Послуги",[23,26,29,32],{"label":24,"to":25},"Розробка сайтів","\u002Fposluhy\u002Frozrobka-saitiv",{"label":27,"to":28},"Інтернет-магазин","\u002Fposluhy\u002Finternet-mahazyn",{"label":30,"to":31},"QA-аудит","\u002Fposluhy\u002Fqa-audyt-internet-mahazynu",{"label":33,"to":34},"Tech Lead","\u002Fposluhy\u002Ftech-lead",{"title":36,"links":37},"Компанія",[38,41,44,47,50,53],{"label":39,"to":40},"Про нас","\u002Fpro-nas",{"label":42,"to":43},"Процес","\u002Fproces",{"label":45,"to":46},"Кейси","\u002Fkeisy",{"label":48,"to":49},"Блог","\u002Fblog",{"label":51,"to":52},"FAQ","\u002Ffaq",{"label":54,"to":55},"Глосарій","\u002Fhlosarii",{"title":57,"links":58},"Юридичне",[59,62,65],{"label":60,"to":61},"Політика конфіденційності","\u002Fpolityka-konfidentsiinosti",{"label":63,"to":64},"Cookies","\u002Fcookies",{"label":66,"to":67},"Умови співпраці","\u002Fumovy",{},[70,72,75,78,79,80,81],{"label":21,"to":71},"\u002Fposluhy",{"label":73,"to":74},"Під ключ","\u002Fpid-kliuch",{"label":76,"to":77},"Ціни","\u002Ftsiny",{"label":45,"to":46},{"label":42,"to":43},{"label":48,"to":49},{"label":82,"to":83},"Контакти","\u002Fkontakty",{"whoFits":85,"whatsIncluded":86,"pricingEyebrow":87,"pricingAnchor":88,"allPrices":89,"sampleResult":90,"process":91,"details":92,"faqEyebrow":51,"faqTitle":93,"related":94,"seeAlso":95,"seeAlsoCases":45,"seeAlsoPosts":96,"price":97,"crumbServices":21,"flagship":98,"ctaLead":116,"ctaSteps":117,"needs":121},"КОМУ ПІДХОДИТЬ","ЩО ВХОДИТЬ","ЦІНИ","Формати і ціни","Усі ціни","ЗРАЗОК РЕЗУЛЬТАТУ","ПРОЦЕС","ДЕТАЛЬНІШЕ","Питання про послугу","РАЗОМ З ЦИМ ЗАМОВЛЯЮТЬ","ДИВІТЬСЯ ТАКОЖ","Статті","ціна",{"crumb":30,"expressCheck":99,"badge":100,"discuss":101,"bookDays":102,"sampleAria":103,"reportTitle":104,"steps":105,"actual":106,"expected":107,"impact":108,"colAction":109,"colExpected":110,"colStatus":111,"top3":112,"screenshot":113,"faqTitle":114,"related":115},"Безкоштовний експрес-чек","ФЛАГМАН","Обговорити","Забронювати дні","Зразок","Так виглядає звіт, який ви отримаєте","КРОКИ","ФАКТИЧНО","ОЧІКУВАНО","ВПЛИВ","ДІЯ","ОЧІКУВАНИЙ РЕЗУЛЬТАТ","СТАТУС","ТОП-3 ДО ВИПРАВЛЕННЯ","скрін звіту","Питання про тестування","ПІСЛЯ АУДИТУ ЗАЗВИЧАЙ ПОТРІБНО","Відповімо за 2 робочі години. Оцінка з вилкою ціни і термінів — за 1 день.",[118,119,120],"Відповідь за 2 години","Дзвінок 20 хвилин","Оцінка за 1 день",[122,27,30,123,33,124,125,126],"Сайт під ключ","Тестування","Дизайн","Розробник у команду","Підтримка","uk\u002Fsite","AZ3xYwhvXjI6pHOp3sjZaJJhSwA1uGWFfKEpVcNpEco",{"id":130,"title":131,"author":132,"body":133,"cover":901,"coverFile":902,"coverLines":903,"coverStat":915,"date":916,"description":139,"excerpt":901,"extension":917,"faq":918,"featured":931,"key":901,"meta":932,"navigation":933,"path":934,"readingTime":935,"seo":936,"seoDescription":937,"seoTitle":938,"slug":939,"stem":940,"tags":941,"updated":944,"__hash__":945},"blog_uk\u002Fuk\u002Fblog\u002Fcore-web-vitals-dlia-vlasnyka-mahazynu.md","Core Web Vitals для власника магазину: що це і як перевірити самому","Євгеній",{"type":134,"value":135,"toc":878},"minimark",[136,140,143,148,151,241,252,255,283,287,290,295,298,319,322,326,329,333,336,353,356,360,363,367,370,374,377,404,408,415,485,489,497,501,508,512,515,518,544,547,561,565,568,571,603,610,685,688,692,695,740,743,755,759,762,776,783,787,795,798,812,816,848,855,859,862,874],[137,138,139],"p",{},"Core Web Vitals — це три метрики Google, які показують, наскільки швидко інтернет-магазин завантажується, відгукується на дії та чи не «стрибає» під час читання: LCP, INP і CLS. Власнику магазину не потрібно вміти їх рахувати. Достатньо знати хороші значення, вміти за 15 хвилин перевірити сайт безкоштовними інструментами і розуміти, про що просити розробника.",[137,141,142],{},"Ми будуємо сайти з орієнтацією на ці метрики, тому нижче — практичний посібник без зайвої теорії: що вимірюється, де дивитися цифри, що найчастіше їх погіршує в магазинах і що з цим робити.",[144,145,147],"h2",{"id":146},"що-таке-core-web-vitals-і-чому-це-важливо-для-магазину","Що таке Core Web Vitals і чому це важливо для магазину",[137,149,150],{},"Google вимірює «досвід сторінки» трьома показниками. Це не абстрактні оцінки, а відображення реальних відчуттів покупця: «довго нічого не з'являється», «кнопка не реагує», «я хотів натиснути одне, а натиснув інше».",[152,153,154,176],"table",{},[155,156,157],"thead",{},[158,159,160,164,167,170,173],"tr",{},[161,162,163],"th",{},"Метрика",[161,165,166],{},"Що означає",[161,168,169],{},"Добре",[161,171,172],{},"Потребує покращення",[161,174,175],{},"Погано",[177,178,179,201,221],"tbody",{},[158,180,181,189,192,195,198],{},[182,183,184,188],"td",{},[185,186,187],"strong",{},"LCP"," (Largest Contentful Paint)",[182,190,191],{},"Коли з'явився найбільший елемент на екрані: зазвичай головне фото або заголовок",[182,193,194],{},"до 2,5 с",[182,196,197],{},"2,5–4 с",[182,199,200],{},"понад 4 с",[158,202,203,209,212,215,218],{},[182,204,205,208],{},[185,206,207],{},"INP"," (Interaction to Next Paint)",[182,210,211],{},"Як швидко сторінка реагує на кліки, дотики, введення",[182,213,214],{},"до 200 мс",[182,216,217],{},"200–500 мс",[182,219,220],{},"понад 500 мс",[158,222,223,229,232,235,238],{},[182,224,225,228],{},[185,226,227],{},"CLS"," (Cumulative Layout Shift)",[182,230,231],{},"Наскільки елементи зміщуються під час завантаження",[182,233,234],{},"до 0,1",[182,236,237],{},"0,1–0,25",[182,239,240],{},"понад 0,25",[137,242,243,244,251],{},"Це порогові значення, які ",[245,246,250],"a",{"href":247,"rel":248},"https:\u002F\u002Fweb.dev\u002Farticles\u002Fvitals",[249],"nofollow","публікує Google"," (перевірено в жовтні 2026). Оцінка вважається за 75-м перцентилем: тобто три чверті відвідувачів мають отримувати «добрий» результат.",[137,253,254],{},"Навіщо це вам як власнику:",[256,257,258,265,271,277],"ul",{},[259,260,261,264],"li",{},[185,262,263],{},"Гроші."," Повільна сторінка каталогу або картки товару втрачає покупців до того, як вони побачили асортимент. Точні цифри залежать від ніші, тому ми не обіцяємо «+20% конверсії», але напрямок очевидний.",[259,266,267,270],{},[185,268,269],{},"SEO."," Core Web Vitals входять до сигналів «досвіду сторінки». Вони не замінюють корисний контент, але за рівної якості швидший сайт має перевагу.",[259,272,273,276],{},[185,274,275],{},"Реклама."," Якщо трафік платний, повільна посадкова сторінка робить кожен клік дорожчим.",[259,278,279,282],{},[185,280,281],{},"Мобільні користувачі."," Більша частина покупців відкриває магазин з телефона, часто через нестабільний мобільний інтернет.",[144,284,286],{"id":285},"як-перевірити-core-web-vitals-самому-за-15-хвилин","Як перевірити Core Web Vitals самому за 15 хвилин",[137,288,289],{},"Вам знадобиться браузер і безкоштовні інструменти Google. Єдине правило: перевіряйте не лише головну, а й типові шаблони — каталог, картку товару, кошик.",[291,292,294],"h3",{"id":293},"крок-1-pagespeed-insights","Крок 1. PageSpeed Insights",[137,296,297],{},"Відкрийте сервіс PageSpeed Insights, вставте адресу сторінки й оберіть вкладку «Мобільні». Ви побачите два блоки.",[299,300,301,313],"ol",{},[259,302,303,306,307,312],{},[185,304,305],{},"Дані з реальних користувачів"," (field data) — вгорі. Це показники відвідувачів за останні 28 днів зі ",[245,308,311],{"href":309,"rel":310},"https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fcrux",[249],"звіту CrUX",". Саме вони важливі для Google. Якщо трафіку мало, цього блоку може не бути.",[259,314,315,318],{},[185,316,317],{},"Діагностика"," (lab data) — внизу. Це симуляція завантаження на слабкому пристрої. Вона показує причини проблем, але не є «офіційною» оцінкою.",[137,320,321],{},"Не гоніться лише за загальним балом Lighthouse. Дивіться на LCP, INP (у lab-режимі замість нього показується TBT) і CLS окремо, а також на список порад «Можливості» й «Діагностика».",[291,323,325],{"id":324},"крок-2-звіт-у-google-search-console","Крок 2. Звіт у Google Search Console",[137,327,328],{},"Якщо сайт підключений до Search Console, відкрийте розділ «Основні веб-показники». Там сторінки згруповані за статусом: хороші, потребують покращення, погані. Групуються вони за типовими шаблонами, тож видно, що «усі картки товарів повільні», а не лише одна сторінка.",[291,330,332],{"id":331},"крок-3-перевірка-на-реальному-телефоні","Крок 3. Перевірка на реальному телефоні",[137,334,335],{},"Відкрийте магазин зі свого смартфона через мобільну мережу, не через домашній Wi-Fi. Дайте собі п'ять запитань:",[256,337,338,341,344,347,350],{},[259,339,340],{},"Через скільки секунд я бачу головне фото товару?",[259,342,343],{},"Чи не зсувається сторінка, коли підвантажуються банери та рекомендації?",[259,345,346],{},"Чи реагує кнопка «Купити» одразу, чи є затримка?",[259,348,349],{},"Чи відкривається фільтр у каталозі без «зависання»?",[259,351,352],{},"Чи не перекриває контент cookie-банер або чат?",[137,354,355],{},"Цей простий тест знаходить половину проблем без жодного інструмента.",[291,357,359],{"id":358},"крок-4-chrome-devtools-для-просунутих","Крок 4. Chrome DevTools (для просунутих)",[137,361,362],{},"У Chrome натисніть F12, відкрийте вкладку Performance або Lighthouse і запустіть аудит у режимі мобільного пристрою із сповільненням мережі. На вкладці Performance видно, які скрипти блокують основний потік. Якщо ви не розробник, можна просто зробити знімок і передати його підряднику як аргумент у розмові.",[144,364,366],{"id":365},"lcp-чому-головний-елемент-зявляється-повільно","LCP: чому головний елемент з'являється повільно",[137,368,369],{},"У магазинах LCP — це майже завжди велика фотографія: банер на головній, фото товару на картці або перше зображення в каталозі. Причини повільності типові.",[291,371,373],{"id":372},"важкі-зображення","Важкі зображення",[137,375,376],{},"Фото на 2–3 МБ у форматі JPEG на мобільному завантажуються секундами. Що зробити:",[256,378,379,382,390,393],{},[259,380,381],{},"віддавати сучасні формати (WebP, AVIF);",[259,383,384,385,389],{},"генерувати кілька розмірів і підставляти відповідний екрану через ",[386,387,388],"code",{},"srcset",";",[259,391,392],{},"стискати без помітної втрати якості;",[259,394,395,396,399,400,403],{},"задавати ",[386,397,398],{},"width"," і ",[386,401,402],{},"height",", щоб браузер зарезервував місце.",[291,405,407],{"id":406},"зображення-яке-лінується-не-тоді-коли-треба","Зображення, яке «лінується» не тоді, коли треба",[137,409,410,411,414],{},"Атрибут ",[386,412,413],{},"loading=\"lazy\""," корисний для картинок нижче першого екрана. Але якщо його поставити на головне фото, браузер відкладе його завантаження. Для LCP-елемента потрібно навпаки:",[416,417,421],"pre",{"className":418,"code":419,"language":420,"meta":14,"style":14},"language-html shiki shiki-themes github-dark-default","\u003Cimg src=\"\u002Fimg\u002Fhero.avif\" width=\"1200\" height=\"600\"\n     fetchpriority=\"high\" alt=\"Нова колекція\">\n","html",[386,422,423,463],{"__ignoreMap":14},[424,425,428,432,436,440,443,447,450,452,455,458,460],"span",{"class":426,"line":427},"line",1,[424,429,431],{"class":430},"sZEs4","\u003C",[424,433,435],{"class":434},"sPWt5","img",[424,437,439],{"class":438},"sFSAA"," src",[424,441,442],{"class":430},"=",[424,444,446],{"class":445},"s9uIt","\"\u002Fimg\u002Fhero.avif\"",[424,448,449],{"class":438}," width",[424,451,442],{"class":430},[424,453,454],{"class":445},"\"1200\"",[424,456,457],{"class":438}," height",[424,459,442],{"class":430},[424,461,462],{"class":445},"\"600\"\n",[424,464,466,469,471,474,477,479,482],{"class":426,"line":465},2,[424,467,468],{"class":438},"     fetchpriority",[424,470,442],{"class":430},[424,472,473],{"class":445},"\"high\"",[424,475,476],{"class":438}," alt",[424,478,442],{"class":430},[424,480,481],{"class":445},"\"Нова колекція\"",[424,483,484],{"class":430},">\n",[291,486,488],{"id":487},"повільна-відповідь-сервера","Повільна відповідь сервера",[137,490,491,492,496],{},"Якщо сервер генерує сторінку по 1,5 секунди, жодні оптимізації картинок цього не виправлять. Для Laravel-магазинів причина часто в N+1 запитах до бази й відсутності кешу: про це ми писали в ",[245,493,495],{"href":494},"\u002Fblog\u002Fshcho-take-tekhnichnyi-audyt-kodu","статті про технічний аудит коду",". Якщо сторінки можна віддавати зі статичного кешу чи prerender, виграш буває найбільшим.",[291,498,500],{"id":499},"блокуючі-шрифти-стилі-та-скрипти","Блокуючі шрифти, стилі та скрипти",[137,502,503,504,507],{},"Шрифти з зовнішнього CDN, багато CSS-файлів і скриптів у ",[386,505,506],{},"\u003Chead>"," затримують перший показ. Рішення: розмістити шрифти на власному домені, підключати лише потрібні накреслення й мови, відкладати непотрібні скрипти.",[144,509,511],{"id":510},"inp-чому-магазин-тупить-після-кліку","INP: чому магазин «тупить» після кліку",[137,513,514],{},"INP — найновіша метрика, яка замінила FID. Вона вимірює затримку між дією користувача і оновленням екрана протягом усього візиту, а не лише першого кліку.",[137,516,517],{},"Що її погіршує:",[256,519,520,526,532,538],{},[259,521,522,525],{},[185,523,524],{},"Надлишок JavaScript."," Бібліотеки для слайдерів, віджети, чати, пікселі, A\u002FB-тести: кожен додає навантаження на основний потік.",[259,527,528,531],{},[185,529,530],{},"Сторонні скрипти аналітики та реклами."," Тег-менеджер із десятком тегів може сповільнити сторінку більше, ніж увесь код магазину.",[259,533,534,537],{},[185,535,536],{},"Важкі обробники подій."," Наприклад, фільтр, який на кожен клік перерисовує весь список із тисяч елементів.",[259,539,540,543],{},[185,541,542],{},"Гідратація великих сторінок"," у SPA-фреймворках, коли сторінка виглядає готовою, але ще не реагує.",[137,545,546],{},"Практичні кроки:",[299,548,549,552,555,558],{},[259,550,551],{},"Складіть список усіх сторонніх скриптів і для кожного запитайте: «Хто цим користується і яке рішення на основі цього приймає?» Те, чим ніхто не користується, видаліть.",[259,553,554],{},"Завантажуйте аналітику та маркетингові пікселі після згоди користувача й з відкладенням. Це ще й вимога конфіденційності.",[259,556,557],{},"Розбивайте довгі завдання: прокрутка, фільтри та кошик мають відповідати першими.",[259,559,560],{},"Для великих каталогів використовуйте пагінацію або віртуалізацію списків.",[144,562,564],{"id":563},"cls-чому-контент-стрибає","CLS: чому контент «стрибає»",[137,566,567],{},"Зміщення макета дратує і шкодить конверсії: людина збирається натиснути «Додати в кошик», а блок рекомендацій з'являється й зсуває кнопку.",[137,569,570],{},"Типові винуватці:",[256,572,573,579,585,591,597],{},[259,574,575,578],{},[185,576,577],{},"Зображення без розмірів."," Браузер не знає висоти й підганяє її після завантаження.",[259,580,581,584],{},[185,582,583],{},"Банери, cookie-панелі та промо-смуги",", які з'являються зверху й виштовхують контент.",[259,586,587,590],{},[185,588,589],{},"Шрифти, що підміняються"," після завантаження і змінюють розміри тексту.",[259,592,593,596],{},[185,594,595],{},"Динамічні блоки:"," відгуки, «разом з цим купують», віджети доставки без зарезервованого місця.",[259,598,599,602],{},[185,600,601],{},"Вбудовування (iframe) без розмірів:"," відео, карти, віджети оплати.",[137,604,605,606,609],{},"Найпростіше правило: для будь-якого елемента, що завантажується пізніше, зарезервуйте місце заздалегідь. Це робиться задаванням розмірів чи ",[386,607,608],{},"aspect-ratio",":",[416,611,615],{"className":612,"code":613,"language":614,"meta":14,"style":14},"language-css shiki shiki-themes github-dark-default",".product-card__image { aspect-ratio: 4 \u002F 5; width: 100%; height: auto; }\n.promo-bar { min-height: 40px; }\n","css",[386,616,617,665],{"__ignoreMap":14},[424,618,619,622,625,627,630,633,636,639,642,644,646,649,653,655,657,659,662],{"class":426,"line":427},[424,620,621],{"class":438},".product-card__image",[424,623,624],{"class":430}," { ",[424,626,608],{"class":438},[424,628,629],{"class":430},": ",[424,631,632],{"class":438},"4",[424,634,635],{"class":430}," \u002F ",[424,637,638],{"class":438},"5",[424,640,641],{"class":430},"; ",[424,643,398],{"class":438},[424,645,629],{"class":430},[424,647,648],{"class":438},"100",[424,650,652],{"class":651},"suJrU","%",[424,654,641],{"class":430},[424,656,402],{"class":438},[424,658,629],{"class":430},[424,660,661],{"class":438},"auto",[424,663,664],{"class":430},"; }\n",[424,666,667,670,672,675,677,680,683],{"class":426,"line":465},[424,668,669],{"class":438},".promo-bar",[424,671,624],{"class":430},[424,673,674],{"class":438},"min-height",[424,676,629],{"class":430},[424,678,679],{"class":438},"40",[424,681,682],{"class":651},"px",[424,684,664],{"class":430},[137,686,687],{},"Для cookie-банера краще робити фіксовану панель знизу, яка не штовхає контент.",[144,689,691],{"id":690},"що-виправляти-першим-порядок-дій","Що виправляти першим: порядок дій",[137,693,694],{},"Не варто одразу переписувати сайт. Дійте за принципом «найбільший ефект — найменша робота».",[299,696,697,706,712,718,728,734],{},[259,698,699,702,703,705],{},[185,700,701],{},"Зображення."," Формати, розміри, ",[386,704,388],{},", правильне lazy-завантаження. Часто це дає найбільший приріст LCP.",[259,707,708,711],{},[185,709,710],{},"Сторонні скрипти."," Аудит і видалення зайвого, відкладене завантаження решти.",[259,713,714,717],{},[185,715,716],{},"Резервування місця"," під банери, зображення та віджети. Зазвичай виправляє CLS за кілька годин.",[259,719,720,723,724,727],{},[185,721,722],{},"Шрифти."," Самостійний хостинг, мінімум накреслень, коректне ",[386,725,726],{},"font-display",".",[259,729,730,733],{},[185,731,732],{},"Кешування й швидкість сервера."," Кеш сторінок, оптимізація запитів до бази, CDN.",[259,735,736,739],{},[185,737,738],{},"Архітектура."," Якщо базові речі виправлені, а показники слабкі, час дивитися на платформу: кількість JavaScript, спосіб рендерингу.",[137,741,742],{},"Після кожної зміни перевіряйте результат у PageSpeed Insights. Field-дані оновлюються з затримкою до 28 днів, тому не панікуйте, якщо Search Console не показує покращення наступного ж дня: орієнтуйтеся на lab-вимірювання, а реальний ефект побачите пізніше.",[744,745,746],"blockquote",{},[137,747,748,751,752,727],{},[185,749,750],{},"Не знаєте, що саме гальмує ваш магазин?"," Ми проведемо експрес-перевірку швидкості та мобільної версії й покажемо 10–15 ключових проблем у PDF за 48 годин. Це безкоштовно, детальніше на сторінці ",[245,753,754],{"href":31},"QA-аудиту інтернет-магазину",[144,756,758],{"id":757},"які-цілі-ставити-розробникам","Які цілі ставити розробникам",[137,760,761],{},"Коли ви замовляєте новий сайт чи оптимізацію, прописуйте вимірювані цілі, а не загальне «щоб швидко». Наші внутрішні вимоги для сайтів, які ми будуємо:",[256,763,764,767,770,773],{},[259,765,766],{},"Lighthouse на мобільному: Performance 95+ на ключових сторінках, SEO та Best Practices — 100;",[259,768,769],{},"LCP до 2,5 с, INP до 200 мс, CLS до 0,1 за польовими даними (75-й перцентиль);",[259,771,772],{},"мінімум JavaScript на головній сторінці, шрифти з власного домену, зображення в сучасних форматах;",[259,774,775],{},"сторонні скрипти лише після згоди користувача.",[137,777,778,779,727],{},"Ці цифри — цілі, а не гарантії для будь-якого проєкту: на показники впливають хостинг, кількість інтеграцій і контент, який додаєте ви. Але домовитися про метод вимірювання й порогові значення можна до початку роботи. Це один із 12 пунктів, які ми радимо перевіряти, ",[245,780,782],{"href":781},"\u002Fblog\u002Fyak-obraty-pidriadnyka-na-rozrobku-saitu","обираючи підрядника на розробку сайту",[144,784,786],{"id":785},"швидкість-і-дизайн-що-вирішується-ще-до-коду","Швидкість і дизайн: що вирішується ще до коду",[137,788,789,790,794],{},"Багато проблем із метриками закладаються на етапі макета. Слайдер із шести великих зображень на першому екрані, відео-фон, три шрифти з десятком накреслень, анімації при прокрутці: усе це гарантовано б'є по LCP та INP. Дизайн, який враховує продуктивність, — це ",[245,791,793],{"href":792},"\u002Fposluhy\u002Fui-ux-dyzain","UI\u002FUX дизайн",", де кожен блок має «ціну» в мілісекундах і обґрунтування.",[137,796,797],{},"Практичні правила для дизайнера та замовника:",[256,799,800,803,806,809],{},[259,801,802],{},"на першому екрані одне головне зображення чи заголовок, а не карусель;",[259,804,805],{},"обмежена кількість шрифтів і накреслень;",[259,807,808],{},"місце під динамічні блоки (відгуки, рекомендації) заплановане в макеті;",[259,810,811],{},"анімація там, де вона допомагає зрозуміти інтерфейс, а не просто прикрашає.",[144,813,815],{"id":814},"типові-помилки-власників-магазинів","Типові помилки власників магазинів",[256,817,818,824,830,836,842],{},[259,819,820,823],{},[185,821,822],{},"Орієнтуватися лише на бал Lighthouse на комп'ютері."," Мобільні результати зазвичай гірші й важливіші.",[259,825,826,829],{},[185,827,828],{},"Перевіряти тільки головну."," Картка товару та каталог часто повільніші.",[259,831,832,835],{},[185,833,834],{},"Додавати плагіни без перевірки наслідків."," Кожен віджет має ціну в мілісекундах.",[259,837,838,841],{},[185,839,840],{},"Вимірювати один раз."," Метрики псуються поступово: нова акція, новий банер, новий піксель.",[259,843,844,847],{},[185,845,846],{},"Вважати швидкість «технічною справою»."," Це частина бізнес-результату, тому вона має бути в чек-листі приймання сайту.",[137,849,850,851,727],{},"Для регулярного контролю достатньо раз на місяць пройтися за кроками 1–3 і зафіксувати цифри в таблиці. Якщо проєкт підтримується окремо, швидкість і регрес варто включити в пакет ",[245,852,854],{"href":853},"\u002Fposluhy\u002Fpidtrymka","підтримки сайту",[144,856,858],{"id":857},"підсумок","Підсумок",[137,860,861],{},"Core Web Vitals — це не про «бали в Google», а про те, чи комфортно покупцеві користуватися вашим магазином. Три метрики, три прості питання: швидко з'являється? швидко відгукується? не стрибає? Перевірити це можна безкоштовно за чверть години, а більшість проблем виправляється зображеннями, сторонніми скриптами та резервуванням місця.",[744,863,864],{},[137,865,866,869,870,873],{},[185,867,868],{},"Хочете магазин, який швидко відкривається на телефонах?"," Ми будуємо сайти з цілями за Core Web Vitals із самого початку. Залиште ",[245,871,872],{"href":17},"бриф"," — оцінимо проєкт за 1 робочий день.",[875,876,877],"style",{},"html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sPWt5, html code.shiki .sPWt5{--shiki-default:#7EE787}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}",{"title":14,"searchDepth":465,"depth":879,"links":880},3,[881,882,888,894,895,896,897,898,899,900],{"id":146,"depth":465,"text":147},{"id":285,"depth":465,"text":286,"children":883},[884,885,886,887],{"id":293,"depth":879,"text":294},{"id":324,"depth":879,"text":325},{"id":331,"depth":879,"text":332},{"id":358,"depth":879,"text":359},{"id":365,"depth":465,"text":366,"children":889},[890,891,892,893],{"id":372,"depth":879,"text":373},{"id":406,"depth":879,"text":407},{"id":487,"depth":879,"text":488},{"id":499,"depth":879,"text":500},{"id":510,"depth":465,"text":511},{"id":563,"depth":465,"text":564},{"id":690,"depth":465,"text":691},{"id":757,"depth":465,"text":758},{"id":785,"depth":465,"text":786},{"id":814,"depth":465,"text":815},{"id":857,"depth":465,"text":858},null,"web-vitals.report",[904,907,909,912],{"marker":905,"text":906},"[PASS]","LCP ≤ 2,5 с",{"marker":905,"text":908},"INP ≤ 200 мс",{"marker":910,"text":911},"[WARN]","CLS 0,14 — банер зсуває контент",{"marker":913,"text":914},"[INFO]","дані з реальних користувачів, 28 днів","3 метрики","2026-10-02","md",[919,922,925,928],{"q":920,"a":921},"Що таке Core Web Vitals простими словами?","Це три метрики Google про досвід на сторінці: LCP показує, як швидко з'являється головний контент, INP — як швидко сторінка реагує на дії, CLS — чи не стрибає макет. Вони впливають на зручність покупки. Перевірити їх можна безкоштовно в PageSpeed Insights.",{"q":923,"a":924},"Де безкоштовно перевірити Core Web Vitals свого сайту?","Найпростіше в PageSpeed Insights: вставте адресу сторінки й дивіться польові дані. Також корисні звіт Core Web Vitals у Google Search Console та Lighthouse у Chrome. Перевіряйте не лише головну, а й категорію, картку товару та checkout, бо вони зазвичай важчі.",{"q":926,"a":927},"Які значення Core Web Vitals вважаються хорошими?","За орієнтирами Google, хороші значення: LCP до 2,5 с, INP до 200 мс і CLS до 0,1. Їх оцінюють за 75-м перцентилем реальних відвідувань. Тому лабораторний тест в одному браузері є лише підказкою, а не остаточною оцінкою.",{"q":929,"a":930},"Чи впливають Core Web Vitals на позиції в Google?","Так, але помірно: це один із сигналів сторінкового досвіду, і він не замінює релевантний контент. Водночас повільний або «стрибучий» магазин втрачає покупців незалежно від позицій. Тому швидкість варто виправляти насамперед заради конверсії, а SEO-ефект вважати бонусом.",false,{},true,"\u002Fuk\u002Fblog\u002Fcore-web-vitals-dlia-vlasnyka-mahazynu",10,{"title":131,"description":139},"Core Web Vitals простими словами: що таке LCP, INP і CLS, які значення вважаються хорошими, як перевірити магазин самому і що виправити першим.","Core Web Vitals для власника магазину — Tochno.","core-web-vitals-dlia-vlasnyka-mahazynu","uk\u002Fblog\u002Fcore-web-vitals-dlia-vlasnyka-mahazynu",[942,943],"ecom","design","2026-10-31","CKMM9OsW3lRD4FKWF5HYQZlH1rCV7p8Iz6jSBXrbs3c",[947,1491,2035,2781,3295,4532,5098,5653,6429,7189,8165,8735,9488],{"id":948,"title":949,"author":132,"body":950,"cover":901,"coverFile":1456,"coverLines":1457,"coverStat":1466,"date":1467,"description":954,"excerpt":901,"extension":917,"faq":1468,"featured":931,"key":901,"meta":1481,"navigation":933,"path":1482,"readingTime":1483,"seo":1484,"seoDescription":1485,"seoTitle":1486,"slug":1487,"stem":1488,"tags":1489,"updated":901,"__hash__":1490},"blog_uk\u002Fuk\u002Fblog\u002Fhoroshop-prom-opencart-chy-kastom.md","Хорошоп, Prom, OpenCart чи кастом: що обрати для магазину у 2026",{"type":134,"value":951,"toc":1440},[952,955,958,962,965,991,999,1003,1006,1009,1023,1026,1029,1033,1036,1039,1043,1228,1231,1235,1241,1250,1253,1263,1269,1280,1284,1287,1319,1326,1330,1333,1337,1351,1354,1358,1369,1372,1376,1387,1391,1408,1411,1415,1418,1429],[137,953,954],{},"Для невеликого магазину з каталогом до кількох тисяч товарів і стандартним оформленням замовлення найчастіше найкраще працює SaaS-конструктор на кшталт Хорошопа: низька абонплата, швидкий старт і нуль комісії з продажів. Prom потрібен, якщо вам важливий готовий трафік маркетплейсу. OpenCart лишається варіантом, коли є власний розробник. Кастомну розробку варто замовляти тоді, коли ліміти платформи вже коштують вам грошей.",[137,956,957],{},"Нижче розбираємо чотири шляхи очима власника: що ви платите щомісяця, які є комісії та ліміти, наскільки ви контролюєте SEO, як працюють Нова Пошта, LiqPay та 1С і що буде, коли захочете піти. Автор, Євгеній, 11 років пише на PHP\u002FLaravel і тестує магазини, тож ми продаємо кастом і маємо очевидну упередженість. Тому прямо кажемо, де він не потрібен.",[144,959,961],{"id":960},"чотири-шляхи-а-не-один-вибір","Чотири шляхи, а не один вибір",[137,963,964],{},"Ці варіанти часто порівнюють так, ніби вони однакові, а це різні моделі.",[256,966,967,973,979,985],{},[259,968,969,972],{},[185,970,971],{},"SaaS-конструктор (Хорошоп та аналоги)."," Ви орендуєте готовий магазин: хостинг, адмінка, оновлення входять в абонплату. Код платформи вам не належить, змінюєте теми й налаштування.",[259,974,975,978],{},[185,976,977],{},"Маркетплейс (Prom)."," Ви продаєте у чужому каталозі з готовим трафіком і платите за пакет та комісію з замовлень. У Prom є й режим окремого сайту, але торгова логіка залишається платформною.",[259,980,981,984],{},[185,982,983],{},"Самостійна CMS (OpenCart)."," Вільне ПЗ: ви самі обираєте хостинг, модулі й розробника та відповідаєте за оновлення й безпеку.",[259,986,987,990],{},[185,988,989],{},"Кастом (Laravel, Nuxt та інше)."," Магазин пишеться під ваші процеси. Код і дані ваші, але старт довший і дорожчий.",[137,992,993,994,998],{},"Тож питання не «що краще», а «хто несе який ризик і за які гроші». Відповідь залежить від каталогу, бюджету та того, чи є в команді людина, яка відповідає за технічну частину. Про самостійні CMS ми писали окремо в порівнянні ",[245,995,997],{"href":996},"\u002Fblog\u002Flaravel-chy-opencart-wordpress-dlia-mahazynu","Laravel, OpenCart і WordPress",", тут не повторюємося, а фокусуємося на SaaS і маркетплейсі.",[144,1000,1002],{"id":1001},"гроші-абонплата-комісії-та-приховані-витрати","Гроші: абонплата, комісії та приховані витрати",[137,1004,1005],{},"У Хорошопа фіксована щомісячна абонплата, яка залежить від кількості товарів і функцій (API, оптові ціни, B2B): орієнтовно від кількох сотень до близько двох тисяч гривень на місяць за річної оплати. Комісії з продажів платформа не бере, хостинг і SSL входять у вартість. Тарифи змінюються, тож перед рішенням звірте актуальні ціни на офіційному сайті horoshop.ua.",[137,1007,1008],{},"Але абонплата не вся вартість. Додайте:",[256,1010,1011,1014,1017,1020],{},[259,1012,1013],{},"налаштування й дизайн (шаблон або робота студії);",[259,1015,1016],{},"платні інтеграції та сервіси, яких немає в базовому пакеті;",[259,1018,1019],{},"комісії платіжних систем: LiqPay та інші еквайринги беруть свій відсоток незалежно від платформи;",[259,1021,1022],{},"контент: фото, описи, імпорт.",[137,1024,1025],{},"Prom працює інакше. За даними support.prom.ua, продавець платить за пакет на рік або базову підписку, а також комісію з виконаних замовлень, і її розмір залежить від категорії та умов пакета. Для сайту з власним доменом існують окремі правила комісії. Точні відсотки Prom змінювалися кілька разів за останні роки, а публічні джерела розходяться між собою, тому конкретних цифр не називаємо: перед стартом порахуйте комісію саме для вашої категорії в кабінеті продавця.",[137,1027,1028],{},"OpenCart безкоштовний як програма, але не як проєкт: потрібні хостинг, платні модулі та теми, робота розробника і регулярні оновлення. Типовий сценарій: перший рік дешево, потім витрати на доробки й виправлення ростуть. Кастом найдорожчий на старті: магазин у Tochno коштує від 150 000 грн і робиться 10–14 тижнів, але далі ви не платите оренду платформі.",[291,1030,1032],{"id":1031},"як-порахувати-вартість-на-три-роки","Як порахувати вартість на три роки",[137,1034,1035],{},"Порівнюйте не місяць, а три роки: саме стільки зазвичай живе перша версія магазину. Припустімо, абонплата становить 800 грн на місяць: за 36 місяців це близько 29 000 грн. Додайте налаштування й дизайн, наприклад ще кілька десятків тисяч гривень, і отримаєте орієнтовно 50–70 тисяч гривень за три роки без комісії платформи. Це умовний приклад нашої арифметики, а не тариф чи пропозиція конкретної студії, тому підставте свої дані.",[137,1037,1038],{},"З кастомом рахунок інший: від 150 000 грн на старті, далі хостинг і підтримка (у нас підтримка від 8 000 грн на місяць, якщо вона вам потрібна). Тобто на горизонті трьох років кастом майже завжди дорожчий за конструктор. Він виграє не ціною, а відсутністю лімітів: коли каталог виріс, потрібні свої правила цін або конструктор змушує вас платити за обхідні шляхи. Якщо ви не можете назвати конкретний ліміт, який вас зупиняє, кастом ще зарано.",[144,1040,1042],{"id":1041},"порівняння-за-критеріями-власника","Порівняння за критеріями власника",[152,1044,1045,1064],{},[155,1046,1047],{},[158,1048,1049,1052,1055,1058,1061],{},[161,1050,1051],{},"Критерій",[161,1053,1054],{},"Хорошоп (SaaS)",[161,1056,1057],{},"Prom",[161,1059,1060],{},"OpenCart",[161,1062,1063],{},"Кастом",[177,1065,1066,1083,1100,1115,1130,1147,1164,1181,1198,1212],{},[158,1067,1068,1071,1074,1077,1080],{},[182,1069,1070],{},"Старт",[182,1072,1073],{},"Дні або тижні",[182,1075,1076],{},"Дні",[182,1078,1079],{},"Тижні",[182,1081,1082],{},"10–14 тижнів",[158,1084,1085,1088,1091,1094,1097],{},[182,1086,1087],{},"Щомісячні витрати",[182,1089,1090],{},"Фіксована абонплата",[182,1092,1093],{},"Пакет і комісія з замовлень",[182,1095,1096],{},"Хостинг, модулі, підтримка",[182,1098,1099],{},"Хостинг і підтримка",[158,1101,1102,1105,1108,1111,1113],{},[182,1103,1104],{},"Комісія з продажів",[182,1106,1107],{},"Немає",[182,1109,1110],{},"Є, залежить від категорії",[182,1112,1107],{},[182,1114,1107],{},[158,1116,1117,1120,1123,1126,1128],{},[182,1118,1119],{},"Власний бренд і база клієнтів",[182,1121,1122],{},"Так",[182,1124,1125],{},"Частково, клієнт у каталозі Prom",[182,1127,1122],{},[182,1129,1122],{},[158,1131,1132,1135,1138,1141,1144],{},[182,1133,1134],{},"SEO-контроль",[182,1136,1137],{},"Середній: стандартні налаштування",[182,1139,1140],{},"Обмежений",[182,1142,1143],{},"Високий, але залежить від налаштування",[182,1145,1146],{},"Повний",[158,1148,1149,1152,1155,1158,1161],{},[182,1150,1151],{},"Нестандартна логіка",[182,1153,1154],{},"Обмежена тарифом",[182,1156,1157],{},"Мінімальна",[182,1159,1160],{},"Через модулі",[182,1162,1163],{},"Без обмежень",[158,1165,1166,1169,1172,1175,1178],{},[182,1167,1168],{},"Нова Пошта, LiqPay",[182,1170,1171],{},"Готові модулі",[182,1173,1174],{},"Вбудовані сервіси Prom",[182,1176,1177],{},"Модулі від різних авторів",[182,1179,1180],{},"Пишемо під ваш процес",[158,1182,1183,1186,1189,1192,1195],{},[182,1184,1185],{},"Інтеграція з 1С",[182,1187,1188],{},"Типова, через обмін",[182,1190,1191],{},"Імпорт і API",[182,1193,1194],{},"Модулі, якість різна",[182,1196,1197],{},"Під вашу схему",[158,1199,1200,1203,1206,1208,1210],{},[182,1201,1202],{},"Володіння кодом",[182,1204,1205],{},"Ні",[182,1207,1205],{},[182,1209,1122],{},[182,1211,1122],{},[158,1213,1214,1217,1220,1223,1226],{},[182,1215,1216],{},"Вихід з платформи",[182,1218,1219],{},"Експорт даних, нові URL",[182,1221,1222],{},"Експорт, клієнт лишається у Prom",[182,1224,1225],{},"Простий",[182,1227,1225],{},[137,1229,1230],{},"Таблиця спрощена. Реальна відмінність залежить від конкретного тарифу, шаблону й виконавця, але напрямок вона показує вірно.",[144,1232,1234],{"id":1233},"ліміти-seo-і-інтеграції-де-болить-найчастіше","Ліміти, SEO і інтеграції: де болить найчастіше",[137,1236,1237,1240],{},[185,1238,1239],{},"Ліміти каталогу й тарифу."," У конструкторах кількість товарів, доступ до API, оптові ціни, мультискладські функції прив'язані до тарифу. Поки ви в межах, це вигідно. Коли зростаєте, переходите на дорожчий пакет, і розрахунок змінюється.",[137,1242,1243,1245,1246,727],{},[185,1244,269],{}," Конструктори вже вміють генерувати мета-теги, sitemap та базову розмітку. Для більшості малих магазинів цього досить. Проблеми з'являються, коли потрібні складні фільтри з індексованими сторінками, власні правила канонічних адрес, нестандартна розмітка або нормальна швидкість на мобільному. У кастомі ви контролюєте все: структуру URL, перелінкування, швидкість, розмітку. Більше про це в статті ",[245,1247,1249],{"href":1248},"\u002Fblog\u002Fcore-web-vitals-dlia-vlasnyka-mahazynu","Core Web Vitals для власника магазину",[137,1251,1252],{},"На Prom ви конкуруєте всередині чужого каталогу, і ваш сайт-візитка там не головне джерело покупців. Це нормально, але не варто чекати, що Prom вирощує ваш бренд у Google.",[137,1254,1255,1258,1259,727],{},[185,1256,1257],{},"Інтеграції."," Нова Пошта та LiqPay є майже скрізь, але «є» і «працює без втрат замовлень» різні речі. Типові проблеми: розбіжність статусів ТТН, повторні списання, зависле замовлення після невдалої оплати. У готових модулях ви залежите від автора модуля, у кастомі від якості тестів. Детальніше про місця, де це ламається, в статті про ",[245,1260,1262],{"href":1261},"\u002Fblog\u002Fintehratsiia-novoi-poshty-ta-oplaty","інтеграцію Нової Пошти та оплати",[137,1264,1265,1268],{},[185,1266,1267],{},"1С та облік."," Якщо склад і ціни живуть в 1С, більшість платформ підтримують обмін файлами. Для складної логіки (кілька складів, спеціальні ціни для клієнтів, часткові відвантаження) конструктор часто стає тісним, і доводиться шукати обхідні шляхи.",[744,1270,1271],{},[137,1272,1273,1276,1277,727],{},[185,1274,1275],{},"Не впевнені, чи вам вистачить конструктора?"," Розкажіть про каталог, інтеграції та плани на рік, і ми чесно скажемо, чи потрібна кастомна розробка. Якщо не потрібна, так і напишемо. ",[245,1278,1279],{"href":17},"Заповнити бриф",[144,1281,1283],{"id":1282},"власність-і-міграція-що-буде-коли-захочете-піти","Власність і міграція: що буде, коли захочете піти",[137,1285,1286],{},"Це питання, про яке згадують запізно. Дані магазину (товари, категорії, клієнти) зазвичай можна вивантажити з будь-якої платформи, а ось усе навколо них переноситься гірше.",[256,1288,1289,1295,1301,1307,1313],{},[259,1290,1291,1294],{},[185,1292,1293],{},"Адреси сторінок."," Нова платформа майже завжди має іншу структуру URL. Без 301-редиректів ви втратите позиції в пошуку, на відновлення яких іде місяці. Це головний ризик міграції.",[259,1296,1297,1300],{},[185,1298,1299],{},"Історія замовлень і клієнти."," Переносяться окремою роботою, і не завжди повністю. Паролі клієнтів перенести не можна, їх доведеться скинути.",[259,1302,1303,1306],{},[185,1304,1305],{},"Відгуки й контент."," Залежать від формату експорту. Інколи простіше забрати з сайту, ніж із системи.",[259,1308,1309,1312],{},[185,1310,1311],{},"Дизайн."," Тема конструктора не переїжджає. Це новий дизайн або нова верстка.",[259,1314,1315,1318],{},[185,1316,1317],{},"Клієнти Prom."," Покупці, які прийшли через маркетплейс, лишаються покупцями Prom. Базу для розсилок у вас буде лише з тих, хто оформлював замовлення на вашому сайті.",[137,1320,1321,1322,1325],{},"Тому, обираючи платформу, одразу питайте: що я зможу забрати і скільки це коштуватиме. Перед міграцією на нову платформу корисно зробити ",[245,1323,1324],{"href":31},"QA-аудит інтернет-магазину"," старого й нового сайтів: перевірити редиректи, мета-теги, форму замовлення, оплату та доставку до перемикання, а не після першої скарги клієнта. Аудит у нас стартує від 6 000 грн.",[144,1327,1329],{"id":1328},"коли-що-обирати-правила-рішення","Коли що обирати: правила рішення",[137,1331,1332],{},"Ось прості правила. Вони не ідеальні, але працюють у більшості ситуацій.",[291,1334,1336],{"id":1335},"обирайте-хорошоп-або-схожий-конструктор-якщо","Обирайте Хорошоп або схожий конструктор, якщо",[256,1338,1339,1342,1345,1348],{},[259,1340,1341],{},"каталог до кількох тисяч товарів і стандартні процеси: кошик, оплата, доставка Новою Поштою;",[259,1343,1344],{},"бюджет обмежений, а запуск потрібен за тижні, а не за місяці;",[259,1346,1347],{},"немає технічної людини, яка підтримуватиме сайт;",[259,1349,1350],{},"ви перевіряєте нішу і ще не знаєте, чи піде продаж.",[137,1352,1353],{},"У цьому випадку кастом за 150 000 грн і вище просто не окупиться, і ми не радимо його замовляти.",[291,1355,1357],{"id":1356},"обирайте-prom-якщо","Обирайте Prom, якщо",[256,1359,1360,1363,1366],{},[259,1361,1362],{},"вам потрібні перші продажі без власного трафіку;",[259,1364,1365],{},"товар легко знаходять за категоріями маркетплейсу;",[259,1367,1368],{},"ви готові закласти комісію в ціну.",[137,1370,1371],{},"Prom добре поєднувати з власним сайтом: маркетплейс дає нових покупців, сайт вирощує повторні продажі без комісії.",[291,1373,1375],{"id":1374},"обирайте-opencart-якщо","Обирайте OpenCart, якщо",[256,1377,1378,1381,1384],{},[259,1379,1380],{},"у вас є свій розробник або довгий контракт на підтримку;",[259,1382,1383],{},"потрібна більша свобода, ніж у конструкторі, але кастом поки зависокий за бюджетом;",[259,1385,1386],{},"ви готові слідкувати за оновленнями й безпекою.",[291,1388,1390],{"id":1389},"обирайте-кастом-якщо","Обирайте кастом, якщо",[256,1392,1393,1396,1399,1402,1405],{},[259,1394,1395],{},"платформа вже обмежує вас: каталог, ціни для груп клієнтів, складна логіка знижок, B2B-кабінет;",[259,1397,1398],{},"потрібні нестандартні інтеграції з 1С, ERP або складом;",[259,1400,1401],{},"швидкість і SEO критичні, а шаблонні рішення не дають результату;",[259,1403,1404],{},"ви рахуєте не перший рік, а три-п'ять років і бачите, що оренда платформи плюс обхідні шляхи дорожчі за власний код;",[259,1406,1407],{},"потрібні автотести оформлення замовлення та контроль якості перед кожним релізом.",[137,1409,1410],{},"Три запитання допоможуть перевірити себе. Чи можу я описати свій процес продажу стандартними кроками? Чи вистачає мені можливостей тарифу вже зараз і через два роки? Чи є в мене людина, яка відповідає за сайт технічно? Якщо на всі три відповідь «так», беріть конструктор.",[144,1412,1414],{"id":1413},"висновок","Висновок",[137,1416,1417],{},"Найдорожче рішення рідко найкраще, а найдешевше часто лише відкладає витрати. Для малого магазину Хорошоп чи подібний конструктор у 2026 році зазвичай розумний вибір, Prom доповнює його трафіком, OpenCart потребує технічного власника, а кастом виграє, коли ліміти платформи вже відчутні в грошах. Перш ніж платити, порахуйте вартість на три роки і перевірте, що саме ви зможете забрати, якщо захочете піти.",[137,1419,1420,1421,1425,1426,727],{},"Орієнтири по вартості кастомної розробки ми розібрали в статті ",[245,1422,1424],{"href":1423},"\u002Fblog\u002Fskilky-koshtuie-rozrobka-internet-mahazynu","скільки коштує розробка інтернет-магазину",", а відкриті ціни Tochno зібрані на сторінці ",[245,1427,1428],{"href":77},"ціни",[744,1430,1431],{},[137,1432,1433,1436,1437,727],{},[185,1434,1435],{},"Обираєте платформу для магазину?"," Опишіть каталог, інтеграції та бюджет, і ми скажемо, що підійде: конструктор чи кастом. Якщо потрібна розробка, дивіться ",[245,1438,1439],{"href":28},"інтернет-магазин від 150 000 грн, 10–14 тижнів",{"title":14,"searchDepth":465,"depth":879,"links":1441},[1442,1443,1446,1447,1448,1449,1455],{"id":960,"depth":465,"text":961},{"id":1001,"depth":465,"text":1002,"children":1444},[1445],{"id":1031,"depth":879,"text":1032},{"id":1041,"depth":465,"text":1042},{"id":1233,"depth":465,"text":1234},{"id":1282,"depth":465,"text":1283},{"id":1328,"depth":465,"text":1329,"children":1450},[1451,1452,1453,1454],{"id":1335,"depth":879,"text":1336},{"id":1356,"depth":879,"text":1357},{"id":1374,"depth":879,"text":1375},{"id":1389,"depth":879,"text":1390},{"id":1413,"depth":465,"text":1414},"platform.choice",[1458,1460,1462,1464],{"marker":905,"text":1459},"Хорошоп: швидкий старт, нуль комісії",{"marker":910,"text":1461},"Prom: трафік є, але клієнт не ваш",{"marker":913,"text":1463},"OpenCart: свобода + самому підтримувати",{"marker":905,"text":1465},"Кастом: коли ліміти вже болять","4 шляхи","2026-10-30",[1469,1472,1475,1478],{"q":1470,"a":1471},"Що обрати для невеликого магазину у 2026: Хорошоп чи Prom?","Якщо хочете власний бренд, сайт у пошуку Google і клієнтську базу, обирайте Хорошоп або схожий конструктор: фіксована абонплата, без комісії з продажів. Prom підходить, коли потрібен готовий трафік маркетплейсу. Часто ці канали поєднують: сайт для постійних клієнтів, Prom для нових покупців.",{"q":1473,"a":1474},"Чи можна перейти з Хорошопа або Prom на власний сайт?","Так. Товари й категорії вивантажуються у файл, але є нюанси: адреси сторінок зміняться, тому потрібні 301-редиректи, а історію замовлень і відгуки доведеться переносити окремо. Правильна міграція займає кілька тижнів і потребує перевірки SEO та оформлення замовлення до перемикання.",{"q":1476,"a":1477},"Скільки коштує кастомний інтернет-магазин порівняно з конструктором?","Конструктор коштує від кількох сотень гривень на місяць плюс налаштування. Кастомний магазин у Tochno починається від 150 000 грн і триває 10–14 тижнів. Різниця окупається не на старті, а коли конструктор обмежує каталог, логіку цін, інтеграції або швидкість.",{"q":1479,"a":1480},"Чи підходить OpenCart у 2026 році?","Підходить для середнього каталогу, якщо у вас є розробник, який оновлює систему й перевіряє сумісність модулів. Сама платформа безкоштовна, але хостинг, безпека, оновлення та доробки лягають на вас. Без технічного супроводу магазин на OpenCart з часом стає повільним і вразливим.",{},"\u002Fuk\u002Fblog\u002Fhoroshop-prom-opencart-chy-kastom",9,{"title":949,"description":954},"Хорошоп, Prom, OpenCart чи кастомний магазин: порівняння за абонплатою, комісіями, SEO, інтеграціями та міграцією. Коли що обирати у 2026.","Хорошоп, Prom чи кастом для магазину у 2026 — Tochno.","horoshop-prom-opencart-chy-kastom","uk\u002Fblog\u002Fhoroshop-prom-opencart-chy-kastom",[942],"1yFoGdQj8WDVwixstrdsNyaBPGZEhz4yX8QydhQiiP4",{"id":1492,"title":1493,"author":132,"body":1494,"cover":901,"coverFile":1999,"coverLines":2000,"coverStat":2010,"date":916,"description":2011,"excerpt":901,"extension":917,"faq":2012,"featured":933,"key":901,"meta":2025,"navigation":933,"path":2026,"readingTime":1483,"seo":2027,"seoDescription":2028,"seoTitle":2029,"slug":2030,"stem":2031,"tags":2032,"updated":1467,"__hash__":2034},"blog_uk\u002Fuk\u002Fblog\u002Fchek-lyst-testuvannia-internet-mahazynu.md","Чек-лист тестування інтернет-магазину перед запуском: 60 пунктів",{"type":134,"value":1495,"toc":1987},[1496,1502,1505,1509,1512,1532,1539,1543,1546,1582,1585,1589,1592,1619,1623,1631,1688,1691,1695,1701,1734,1738,1759,1763,1766,1795,1799,1879,1890,1894,1897,1923,1926,1933,1937,1940,1972,1975],[137,1497,1498,1499,1501],{},"Чек-лист тестування інтернет-магазину потрібен власнику, який збирається запускати або оновлювати сайт і хоче впевнитись, що клієнт зможе знайти товар, покласти його в кошик і заплатити. Нижче 60 пунктів, згрупованих за етапами шляху покупця. Їх можна пройти самостійно за вечір або передати тестувальнику. Ми користуємось саме цим скелетом, коли готуємо ",[245,1500,1324],{"href":31},", тільки на практиці пунктів значно більше: близько 150.",[137,1503,1504],{},"Головна ідея проста. Не все в магазині однаково важливе. Баг у футері коштує вам нерву, баг у кошику коштує вам грошей. Тому перевіряємо в порядку «від грошей»: спершу оплата й checkout, потім кошик і каталог, потім усе інше.",[144,1506,1508],{"id":1507},"як-користуватись-чек-листом","Як користуватись чек-листом",[137,1510,1511],{},"Перед стартом підготуйте три речі.",[256,1513,1514,1520,1526],{},[259,1515,1516,1519],{},[185,1517,1518],{},"Тестове середовище"," (staging), яке максимально схоже на бойове: ті ж версії PHP і бази, ті ж інтеграції, але в режимі sandbox. Тестувати оплату реальною карткою на проді не потрібно.",[259,1521,1522,1525],{},[185,1523,1524],{},"Набір тестових даних:"," кілька товарів з різними станами (є в наявності, закінчується, немає, з варіантами, зі знижкою), 2–3 акаунти, промокоди, тестові картки платіжки.",[259,1527,1528,1531],{},[185,1529,1530],{},"Пристрої:"," мінімум один iPhone з Safari, один Android з Chrome, десктоп з Chrome і Firefox. Емуляція в DevTools корисна, але реальний Safari на iOS ламається інакше.",[137,1533,1534,1535,727],{},"Кожен пункт позначайте так: пройшов, не пройшов, не застосовується. Для кожного провалу фіксуйте кроки відтворення, очікуваний і фактичний результат, пристрій і скріншот чи відео. Приклад якісного опису ми розбирали в статті ",[245,1536,1538],{"href":1537},"\u002Fblog\u002Fyak-my-testuiemo-bah-report-i-test-keis","Як ми тестуємо: приклад баг-репорту та тест-кейсу",[144,1540,1542],{"id":1541},"_1-каталог-і-пошук-10-пунктів","1. Каталог і пошук (10 пунктів)",[137,1544,1545],{},"Каталог формує перше враження і приводить трафік з пошуку, тому тут перевіряємо і функції, і дані.",[299,1547,1548,1551,1554,1557,1560,1563,1570,1573,1576,1579],{},[259,1549,1550],{},"Усі категорії відкриваються, у списку немає порожніх сторінок і 500-х помилок.",[259,1552,1553],{},"Кількість товарів у лічильнику категорії збігається з кількістю на сторінці.",[259,1555,1556],{},"Фільтри працюють поодинці й у комбінації; після застосування змінюється URL, і за посиланням можна повернутись до того ж результату.",[259,1558,1559],{},"Скидання фільтрів повертає повний список, а не «нічого не знайдено».",[259,1561,1562],{},"Сортування за ціною справді сортує числа, а не рядки: 900 не стоїть після 10 000.",[259,1564,1565,1566,1569],{},"Пагінація: остання сторінка, сторінка поза діапазоном (",[386,1567,1568],{},"?page=999",") дають зрозумілу відповідь, а не помилку.",[259,1571,1572],{},"Пошук знаходить товар за назвою, артикулом і з помилкою в одну літеру; кирилиця й латиниця працюють однаково.",[259,1574,1575],{},"Порожній результат пошуку показує підказку і популярні категорії.",[259,1577,1578],{},"Картка товару: фото, ціна, опис, варіанти, наявність відображаються правильно; для товарів без фото є заглушка.",[259,1580,1581],{},"Товар «немає в наявності» не можна купити, але його можна знайти, і є кнопка «повідомити про появу» чи схожі товари.",[137,1583,1584],{},"Окремо перевірте ціни. Ціна в списку, на картці, у кошику й на checkout має бути однаковою до копійки, з урахуванням знижок і округлення.",[144,1586,1588],{"id":1587},"_2-кошик-8-пунктів","2. Кошик (8 пунктів)",[137,1590,1591],{},"Кошик виглядає простим, але в ньому живе найбільше логіки: ціни, залишки, купони.",[299,1593,1595,1598,1601,1604,1607,1610,1613,1616],{"start":1594},11,[259,1596,1597],{},"Додавання товару з картки, зі списку й з «швидкого перегляду» працює однаково.",[259,1599,1600],{},"Зміна кількості перераховує суму миттєво; кількість 0 і від'ємна кількість не ламають кошик.",[259,1602,1603],{},"Не можна додати більше, ніж є на складі, і повідомлення про це зрозуміле.",[259,1605,1606],{},"Видалення товару і повернення «скасувати» не залишають «привидів» у лічильнику на іконці.",[259,1608,1609],{},"Кошик зберігається після оновлення сторінки, закриття вкладки й входу в акаунт (гостьовий кошик зливається з акаунтним).",[259,1611,1612],{},"Промокод: валідний, прострочений, використаний, регістр літер, комбінація з іншою знижкою, мінімальна сума. Помилка пояснює причину.",[259,1614,1615],{},"Безкоштовна доставка від суми: поріг відображається і спрацьовує, коли сума перетинає його і вгору, і вниз.",[259,1617,1618],{},"Якщо ціна або залишок змінились, поки товар лежав у кошику, користувач бачить повідомлення, а не дізнається про це на оплаті.",[144,1620,1622],{"id":1621},"_3-checkout-замовлення-без-реєстрації-12-пунктів","3. Checkout: замовлення без реєстрації (12 пунктів)",[137,1624,1625,1626,1630],{},"Саме тут губляться гроші. Про типові баги цього етапу детально в статті ",[245,1627,1629],{"href":1628},"\u002Fblog\u002Fchomu-hubliatsia-zamovlennia-na-checkout","Чому губляться замовлення на checkout: 7 типових багів",", а тут базовий перелік.",[299,1632,1634,1637,1640,1654,1657,1667,1670,1673,1676,1679,1682,1685],{"start":1633},19,[259,1635,1636],{},"Замовлення можна оформити як гість, без обов'язкової реєстрації.",[259,1638,1639],{},"Валідація полів показується біля поля, а не одним повідомленням угорі; введені дані не зникають після помилки.",[259,1641,1642,1643,1646,1647,1646,1650,1653],{},"Телефон приймає формати ",[386,1644,1645],{},"+380…",", ",[386,1648,1649],{},"380…",[386,1651,1652],{},"0…",", з пробілами й дужками і зберігається в єдиному вигляді.",[259,1655,1656],{},"Email із пробілом наприкінці (типовий результат автозаповнення на телефоні) обробляється, а не відхиляється.",[259,1658,1659,1660,399,1663,1666],{},"Кирилиця, апострофи й лапки в імені та адресі не ламають замовлення (спробуйте ",[386,1661,1662],{},"О'Коннор",[386,1664,1665],{},"Ґанок",").",[259,1668,1669],{},"Вибір доставки змінює вартість і підсумок одразу, без перезавантаження.",[259,1671,1672],{},"Самовивіз показує адресу та години роботи.",[259,1674,1675],{},"Адреса: для кур'єрської доставки обов'язкові потрібні поля, для відділення вони приховані й не блокують відправку.",[259,1677,1678],{},"Подвійне натискання на «Підтвердити замовлення» створює одне замовлення, а не два.",[259,1680,1681],{},"Кнопка «Назад» у браузері не скидає форму і не дублює замовлення.",[259,1683,1684],{},"Після успішного замовлення клієнт бачить сторінку подяки з номером замовлення; оновлення сторінки не створює нового замовлення.",[259,1686,1687],{},"Якщо сесія закінчилась посеред оформлення, користувач не втрачає кошик.",[137,1689,1690],{},"Додайте сюди тест «повільний інтернет»: у DevTools увімкніть Slow 3G і оформіть замовлення. Саме тут вилазять кнопки без індикатора завантаження і подвійні кліки.",[144,1692,1694],{"id":1693},"_4-оплата-й-нова-пошта-10-пунктів","4. Оплата й Нова Пошта (10 пунктів)",[137,1696,1697,1698,727],{},"Інтеграції ламаються на стику систем, тому тестуємо і успіх, і всі види відмов. Окремий розбір цієї теми: ",[245,1699,1700],{"href":1261},"Інтеграція Нової Пошти та оплати: де найчастіше ламається",[299,1702,1704,1707,1710,1713,1716,1719,1722,1725,1728,1731],{"start":1703},31,[259,1705,1706],{},"Успішна оплата карткою в sandbox: замовлення отримує статус «оплачено», клієнт отримує лист.",[259,1708,1709],{},"Відхилена картка: замовлення залишається «очікує оплати», клієнт бачить зрозуміле повідомлення і може спробувати знову.",[259,1711,1712],{},"Клієнт закрив вкладку на сторінці банку: замовлення не зависає, а є механізм повторної оплати за посиланням.",[259,1714,1715],{},"Платіжка надіслала callback двічі: замовлення не оплачується двічі й не дублюються листи (ідемпотентність).",[259,1717,1718],{},"Callback прийшов раніше, ніж клієнт повернувся на сайт: статус все одно правильний.",[259,1720,1721],{},"Оплата при отриманні і накладений платіж мають окремі правила (ліміти, комісія) і правильно відображаються в замовленні.",[259,1723,1724],{},"Нова Пошта: пошук міста за частиною назви, однойменні населені пункти в різних областях розрізняються.",[259,1726,1727],{},"Відділення і поштомати завантажуються, пошук за номером працює, закрите відділення не пропонується.",[259,1729,1730],{},"Вартість доставки і строки відповідають тарифу перевізника, а ТТН створюється з правильними габаритами й вагою.",[259,1732,1733],{},"Помилка API перевізника не блокує замовлення: менеджер бачить, що ТТН не створилась, і може повторити.",[144,1735,1737],{"id":1736},"_5-акаунт-і-листи-6-пунктів","5. Акаунт і листи (6 пунктів)",[299,1739,1741,1744,1747,1750,1753,1756],{"start":1740},41,[259,1742,1743],{},"Реєстрація, вхід, відновлення пароля: лист приходить, посилання працює один раз і має термін дії.",[259,1745,1746],{},"Не можна зареєструвати той самий email двічі, навіть в іншому регістрі.",[259,1748,1749],{},"Історія замовлень показує правильні статуси й суми.",[259,1751,1752],{},"Транзакційні листи (підтвердження, оплата, відправлення) приходять не в спам, коректно виглядають у Gmail на телефоні і містять правильні дані.",[259,1754,1755],{},"Підписка на розсилку і форма зворотного зв'язку працюють, є згода на обробку даних.",[259,1757,1758],{},"У листах для адміністратора немає особистих даних, яким там не місце, а повідомлення в Telegram чи CRM приходять з усіма полями замовлення.",[144,1760,1762],{"id":1761},"_6-мобільна-версія-й-сумісність-6-пунктів","6. Мобільна версія й сумісність (6 пунктів)",[137,1764,1765],{},"Для більшості магазинів понад половина трафіку мобільна, тому це не «додатково».",[299,1767,1769,1772,1783,1786,1789,1792],{"start":1768},47,[259,1770,1771],{},"Перевірте ширини 375, 768 і 1440 пікселів: немає горизонтального скролу і обрізаного тексту.",[259,1773,1774,1775,1778,1779,1782],{},"Кнопки й поля зручні для пальця (орієнтовно від 44 пікселів), поля мають правильний тип клавіатури: ",[386,1776,1777],{},"tel"," для телефону, ",[386,1780,1781],{},"email"," для пошти.",[259,1784,1785],{},"Липка шапка чи банер не перекриває кнопку «Купити» і поле вводу, коли відкрита клавіатура.",[259,1787,1788],{},"Safari на iOS: оформлення, оплата, фільтри, випадаючі списки.",[259,1790,1791],{},"Chrome на Android, Firefox та Edge на десктопі: головний сценарій покупки.",[259,1793,1794],{},"Модальні вікна закриваються, фокус не втікає за них, а сторінка під ними не прокручується.",[144,1796,1798],{"id":1797},"_7-швидкість-seo-і-безпека-8-пунктів","7. Швидкість, SEO і безпека (8 пунктів)",[299,1800,1802,1807,1824,1836,1846,1856,1859,1866],{"start":1801},53,[259,1803,1804,1805,727],{},"Lighthouse на мобільному для головної, категорії й картки товару. Орієнтир: LCP до 2,5 с, CLS до 0,1. Як читати ці метрики без розробника, пояснюємо в статті ",[245,1806,1249],{"href":1248},[259,1808,1809,1810,1646,1813,1816,1817,399,1820,1823],{},"У кожного товару й категорії унікальні ",[386,1811,1812],{},"title",[386,1814,1815],{},"description",", один ",[386,1818,1819],{},"h1",[386,1821,1822],{},"canonical","; фільтровані сторінки не створюють нескінченних дублікатів.",[259,1825,1826,399,1829,1832,1833,1666],{},[386,1827,1828],{},"robots.txt",[386,1830,1831],{},"sitemap.xml"," на місці, а тестове середовище закрите від індексації (і це не переїхало на продакшн разом із ",[386,1834,1835],{},"noindex",[259,1837,1838,1839,399,1842,1845],{},"Є мікророзмітка ",[386,1840,1841],{},"Product",[386,1843,1844],{},"BreadcrumbList"," з правильними ціною та наявністю.",[259,1847,1848,1849,399,1852,1855],{},"Сайт працює по HTTPS без попереджень про змішаний вміст; ",[386,1850,1851],{},"http",[386,1853,1854],{},"www"," перенаправляються на єдину версію.",[259,1857,1858],{},"Сторінка 404 корисна, а старі адреси мають 301-редиректи.",[259,1860,1861,1862,1865],{},"Базова безпека: пароль не передається в URL, адмінка закрита і не лежить за адресою ",[386,1863,1864],{},"\u002Fadmin"," без захисту, форми захищені від спаму.",[259,1867,1868,1869,1646,1872,1646,1875,1878],{},"Аналітика: події ",[386,1870,1871],{},"purchase",[386,1873,1874],{},"add_to_cart",[386,1876,1877],{},"begin_checkout"," доходять, а трекінг не спрацьовує до згоди в cookie-банері.",[744,1880,1881],{},[137,1882,1883,1886,1887,1889],{},[185,1884,1885],{},"Не хочете проходити 60 пунктів самі?"," Ми зробимо безкоштовний експрес-чек за 48 годин: 10–15 ключових проблем з відео і пріоритетами. А повний ",[245,1888,1324],{"href":31}," коштує від 6 000 грн.",[144,1891,1893],{"id":1892},"що-робити-з-результатами","Що робити з результатами",[137,1895,1896],{},"Після проходу чек-листа у вас буде список проблем. Не намагайтесь виправити все одразу, а розкладіть за впливом.",[256,1898,1899,1905,1911,1917],{},[259,1900,1901,1904],{},[185,1902,1903],{},"Блокери:"," клієнт не може купити або оплатити. Виправляємо до запуску, без винятків.",[259,1906,1907,1910],{},[185,1908,1909],{},"Критичні:"," є обхідний шлях, але частина клієнтів піде (баг лише в Safari, не працює промокод).",[259,1912,1913,1916],{},[185,1914,1915],{},"Значущі:"," псують враження чи SEO, але гроші не втрачаються.",[259,1918,1919,1922],{},[185,1920,1921],{},"Косметичні:"," виправляємо, коли є час.",[137,1924,1925],{},"Хороше правило для запуску: нуль блокерів і нуль критичних у шляху «товар → кошик → оплата». Решту можна запускати зі списком відомих проблем і планом виправлення.",[137,1927,1928,1929,727],{},"Ще одна практична порада: після кожного релізу повторюйте хоча б 12–15 ключових пунктів (розділи 2–4). Це називається регресійне тестування. Якщо воно щоразу забирає години ручної роботи, варто подумати про автоматизацію найважливіших сценаріїв. Коли це виправдано, а коли ні, ми розписали в статті ",[245,1930,1932],{"href":1931},"\u002Fblog\u002Fruchne-chy-avtomatyzovane-testuvannia","Ручне vs автоматизоване тестування",[144,1934,1936],{"id":1935},"типові-помилки-тих-хто-тестує-сам","Типові помилки тих, хто тестує сам",[137,1938,1939],{},"З нашого досвіду, власники й розробники, які перевіряють свій магазин, роблять одні й ті самі помилки.",[256,1941,1942,1948,1954,1960,1966],{},[259,1943,1944,1947],{},[185,1945,1946],{},"Тестують «щасливий шлях»."," Клієнти ж роблять усе навпаки: вводять зайві пробіли, тиснуть «Назад», закривають вкладку посеред оплати.",[259,1949,1950,1953],{},[185,1951,1952],{},"Тестують на своєму комп'ютері."," Розробник працює на швидкому ноутбуці з широким екраном, а покупець сидить на старому Android у метро.",[259,1955,1956,1959],{},[185,1957,1958],{},"Не фіксують кроки."," Баг, який не вдається відтворити, ніхто не виправить. Записуйте екран.",[259,1961,1962,1965],{},[185,1963,1964],{},"Не перевіряють після виправлення."," Виправлення одного ламає сусідній функціонал, тому після кожного фікса пройдіть пов'язані пункти.",[259,1967,1968,1971],{},[185,1969,1970],{},"Пропускають листи й повідомлення."," Замовлення створилось, але лист не прийшов, і клієнт вважає, що його проігнорували.",[137,1973,1974],{},"Якщо у вас є розробник, попросіть його додати сторінку-«пісочницю» з усіма станами товару, а ще краще: налаштуйте автоматичні тести на кошик і checkout. Це найдешевша страховка від повторення старих помилок.",[744,1976,1977],{},[137,1978,1979,1982,1983,1986],{},[185,1980,1981],{},"Потрібна друга пара очей перед запуском?"," Опишіть магазин у ",[245,1984,1985],{"href":17},"брифі",", і ми скажемо, скільки часу й коштів піде на перевірку саме вашого проєкту.",{"title":14,"searchDepth":465,"depth":879,"links":1988},[1989,1990,1991,1992,1993,1994,1995,1996,1997,1998],{"id":1507,"depth":465,"text":1508},{"id":1541,"depth":465,"text":1542},{"id":1587,"depth":465,"text":1588},{"id":1621,"depth":465,"text":1622},{"id":1693,"depth":465,"text":1694},{"id":1736,"depth":465,"text":1737},{"id":1761,"depth":465,"text":1762},{"id":1797,"depth":465,"text":1798},{"id":1892,"depth":465,"text":1893},{"id":1935,"depth":465,"text":1936},"checkout.checklist",[2001,2003,2005,2007],{"marker":905,"text":2002},"каталог і фільтри",{"marker":905,"text":2004},"кошик і промокоди",{"marker":910,"text":2006},"оплата: повторний callback",{"marker":2008,"text":2009},"[FAIL]","Нова Пошта: порожнє відділення","60 пунктів","Чек-лист тестування інтернет-магазину потрібен власнику, який збирається запускати або оновлювати сайт і хоче впевнитись, що клієнт зможе знайти товар, покласти його в кошик і заплатити. Нижче 60 пунктів, згрупованих за етапами шляху покупця. Їх можна пройти самостійно за вечір або передати тестувальнику. Ми користуємось саме цим скелетом, коли готуємо QA-аудит інтернет-магазину, тільки на практиці пунктів значно більше: близько 150.",[2013,2016,2019,2022],{"q":2014,"a":2015},"Що тестувати в інтернет-магазині перед запуском?","Перевірте весь шлях покупця: каталог і пошук, кошик, checkout, оплату, доставку, листи й мобільну версію. Найбільше грошей втрачається на checkout і оплаті, тому починайте з них, а вже потім переходьте до другорядних сторінок, швидкості та дрібного оформлення.",{"q":2017,"a":2018},"Скільки часу займає тестування магазину перед запуском?","Самостійно за чек-листом це зазвичай кілька днів, залежно від розміру каталогу й кількості інтеграцій. Повний QA-аудит магазину в нашій студії займає 3–5 днів і коштує від 6 000 грн, а результатом стає звіт із пріоритетами виправлень.",{"q":2020,"a":2021},"Чи можна протестувати магазин самостійно, без QA-інженера?","Так, базові сценарії каталогу, кошика й замовлення можна пройти самому за чек-листом. Але власник знає сайт надто добре й бачить не те, що побачить новий покупець. Складніші випадки, як збої оплати чи різні браузери, краще віддати сторонньому погляду.",{"q":2023,"a":2024},"Які пристрої й браузери перевіряти перед запуском магазину?","Мінімум: актуальні Chrome і Safari на комп'ютері, iPhone із Safari та Android із Chrome. Окремо пройдіть checkout із телефону, бо саме там найчастіше не натискається кнопка чи ламається форма. Якщо є аналітика, орієнтуйтеся на пристрої ваших реальних відвідувачів.",{},"\u002Fuk\u002Fblog\u002Fchek-lyst-testuvannia-internet-mahazynu",{"title":1493,"description":2011},"Чек-лист тестування інтернет-магазину перед запуском: 60 пунктів по каталогу, кошику, checkout, оплаті, мобільній версії та SEO. Використовуйте як є.","Чек-лист тестування інтернет-магазину — Tochno.","chek-lyst-testuvannia-internet-mahazynu","uk\u002Fblog\u002Fchek-lyst-testuvannia-internet-mahazynu",[2033,942],"qa","vD6qSKvB6pnoFL0UOoASFzvHCz1WzHvLJX5ocJrFKsA",{"id":2036,"title":1629,"author":132,"body":2037,"cover":901,"coverFile":2748,"coverLines":2749,"coverStat":2758,"date":916,"description":2041,"excerpt":901,"extension":917,"faq":2759,"featured":931,"key":901,"meta":2772,"navigation":933,"path":2773,"readingTime":1483,"seo":2774,"seoDescription":2775,"seoTitle":2776,"slug":2777,"stem":2778,"tags":2779,"updated":1467,"__hash__":2780},"blog_uk\u002Fuk\u002Fblog\u002Fchomu-hubliatsia-zamovlennia-na-checkout.md",{"type":134,"value":2038,"toc":2736},[2039,2042,2045,2049,2052,2055,2069,2077,2081,2087,2092,2106,2112,2118,2257,2268,2272,2277,2281,2292,2297,2301,2315,2320,2324,2329,2333,2344,2349,2353,2364,2368,2373,2378,2406,2411,2416,2420,2425,2429,2443,2448,2452,2466,2470,2475,2480,2497,2502,2507,2566,2569,2573,2578,2582,2596,2601,2616,2627,2631,2634,2640,2646,2652,2663,2676,2682,2686,2689,2712,2715,2718,2733],[137,2040,2041],{},"Замовлення на checkout губляться через невелику кількість повторюваних причин: подвійні кліки, втрачені відповіді платіжної системи, прострочена сесія, надто сувора валідація полів, збій у залежних сервісах, розбіжність цін і проблеми мобільної версії. Нижче сім типових багів, які ми знаходимо в інтернет-магазинах під час тестування, з кроками відтворення, причиною і способом виправлення. Матеріал корисний і власникам (щоб знати, що питати у розробника), і розробникам (щоб перевірити свій код).",[137,2043,2044],{},"Одразу уточнимо: ми не наводимо чужих кейсів і статистики. Усе нижче це типові сценарії, які легко відтворити на будь-якому магазині. Ми знаходимо їх у роботі як QA, і їх варто перевірити у вас до того, як їх виявить покупець.",[144,2046,2048],{"id":2047},"чому-checkout-це-зона-підвищеного-ризику","Чому checkout це зона підвищеного ризику",[137,2050,2051],{},"Checkout об'єднує найбільше рухомих частин за найменший час: форма з валідацією, розрахунок суми, вибір доставки, зовнішня платіжна система, створення замовлення в базі, листи й повідомлення. Кожна частина може вийти з ладу, а клієнт при цьому нічого не побачить: або отримає незрозумілу помилку, або заплатить і не отримає замовлення.",[137,2053,2054],{},"Особливо небезпечні дві ситуації:",[256,2056,2057,2063],{},[259,2058,2059,2062],{},[185,2060,2061],{},"Клієнт заплатив, а замовлення немає."," Це найгірший сценарій: гроші списано, а магазин нічого не знає.",[259,2064,2065,2068],{},[185,2066,2067],{},"Клієнт не зміг дійти до кінця й пішов."," Ви ніколи не дізнаєтесь про це: у базі нічого немає, а в аналітиці лише «відмова».",[137,2070,2071,2072,2076],{},"Тому тестування checkout потрібне не лише в усіх «щасливих» сценаріях, а й у ненормальних: повільна мережа, подвійні кліки, закрита вкладка, відмова банку. Базовий перелік перевірок ми зібрали в ",[245,2073,2075],{"href":2074},"\u002Fblog\u002Fchek-lyst-testuvannia-internet-mahazynu","чек-листі на 60 пунктів",", а тут розберемо найдорожчі помилки докладно.",[144,2078,2080],{"id":2079},"баг-1-подвійний-клік-створює-два-замовлення-або-жодного","Баг 1. Подвійний клік створює два замовлення (або жодного)",[137,2082,2083,2086],{},[185,2084,2085],{},"Симптом."," Клієнт натискає «Підтвердити замовлення», сторінка думає кілька секунд. Він натискає ще раз. У системі з'являються два однакові замовлення або після другого кліку виникає помилка, і перше замовлення «зависає».",[137,2088,2089],{},[185,2090,2091],{},"Кроки відтворення.",[299,2093,2094,2097,2100,2103],{},[259,2095,2096],{},"Додайте товар у кошик і перейдіть на checkout.",[259,2098,2099],{},"У DevTools увімкніть Slow 3G.",[259,2101,2102],{},"Двічі швидко натисніть кнопку підтвердження.",[259,2104,2105],{},"Перевірте кількість замовлень у адмінці.",[137,2107,2108,2111],{},[185,2109,2110],{},"Причина."," Кнопка не блокується після першого натискання, а сервер не перевіряє, чи це повторний запит.",[137,2113,2114,2117],{},[185,2115,2116],{},"Виправлення."," Потрібні два шари захисту. На клієнті кнопка стає неактивною й показує індикатор. На сервері додається ключ ідемпотентності: клієнт генерує унікальний токен при відкритті форми й передає його із запитом, а сервер відхиляє повторний запит із тим самим токеном.",[416,2119,2123],{"className":2120,"code":2121,"language":2122,"meta":14,"style":14},"language-php shiki shiki-themes github-dark-default","\u002F\u002F Laravel: захист від дубля замовлення за ключем ідемпотентності\n$order = Order::firstOrCreate(\n    ['idempotency_key' => $request->input('idempotency_key')],\n    $orderData\n);\n\nif (! $order->wasRecentlyCreated) {\n    return response()->json(['order_id' => $order->id]); \u002F\u002F той самий результат\n}\n","php",[386,2124,2125,2131,2151,2179,2185,2191,2197,2217,2252],{"__ignoreMap":14},[424,2126,2127],{"class":426,"line":427},[424,2128,2130],{"class":2129},"sH3jZ","\u002F\u002F Laravel: захист від дубля замовлення за ключем ідемпотентності\n",[424,2132,2133,2136,2138,2141,2144,2148],{"class":426,"line":465},[424,2134,2135],{"class":430},"$order ",[424,2137,442],{"class":651},[424,2139,2140],{"class":438}," Order",[424,2142,2143],{"class":651},"::",[424,2145,2147],{"class":2146},"sc3cj","firstOrCreate",[424,2149,2150],{"class":430},"(\n",[424,2152,2153,2156,2159,2162,2165,2168,2171,2174,2176],{"class":426,"line":879},[424,2154,2155],{"class":430},"    [",[424,2157,2158],{"class":445},"'idempotency_key'",[424,2160,2161],{"class":651}," =>",[424,2163,2164],{"class":430}," $request",[424,2166,2167],{"class":651},"->",[424,2169,2170],{"class":2146},"input",[424,2172,2173],{"class":430},"(",[424,2175,2158],{"class":445},[424,2177,2178],{"class":430},")],\n",[424,2180,2182],{"class":426,"line":2181},4,[424,2183,2184],{"class":430},"    $orderData\n",[424,2186,2188],{"class":426,"line":2187},5,[424,2189,2190],{"class":430},");\n",[424,2192,2194],{"class":426,"line":2193},6,[424,2195,2196],{"emptyLinePlaceholder":933},"\n",[424,2198,2200,2203,2206,2209,2212,2214],{"class":426,"line":2199},7,[424,2201,2202],{"class":651},"if",[424,2204,2205],{"class":430}," (",[424,2207,2208],{"class":651},"!",[424,2210,2211],{"class":430}," $order",[424,2213,2167],{"class":651},[424,2215,2216],{"class":430},"wasRecentlyCreated) {\n",[424,2218,2220,2223,2226,2229,2231,2234,2237,2240,2242,2244,2246,2249],{"class":426,"line":2219},8,[424,2221,2222],{"class":651},"    return",[424,2224,2225],{"class":2146}," response",[424,2227,2228],{"class":430},"()",[424,2230,2167],{"class":651},[424,2232,2233],{"class":2146},"json",[424,2235,2236],{"class":430},"([",[424,2238,2239],{"class":445},"'order_id'",[424,2241,2161],{"class":651},[424,2243,2211],{"class":430},[424,2245,2167],{"class":651},[424,2247,2248],{"class":430},"id]); ",[424,2250,2251],{"class":2129},"\u002F\u002F той самий результат\n",[424,2253,2254],{"class":426,"line":1483},[424,2255,2256],{"class":430},"}\n",[137,2258,2259,2260,2263,2264,2267],{},"Для цього в таблиці ",[386,2261,2262],{},"orders"," потрібен унікальний індекс по ",[386,2265,2266],{},"idempotency_key",", інакше при двох майже одночасних запитах гонка все одно створить дубль.",[144,2269,2271],{"id":2270},"баг-2-платіжна-система-повідомила-про-оплату-а-замовлення-не-оновилось","Баг 2. Платіжна система повідомила про оплату, а замовлення не оновилось",[137,2273,2274,2276],{},[185,2275,2085],{}," Клієнт заплатив карткою, банк списав гроші, але замовлення залишилось у статусі «очікує оплати». Менеджер не відправляє товар, клієнт дзвонить розлючений.",[137,2278,2279],{},[185,2280,2091],{},[299,2282,2283,2286,2289],{},[259,2284,2285],{},"Оформіть замовлення з оплатою карткою в sandbox.",[259,2287,2288],{},"Закрийте вкладку відразу після оплати, не повертаючись на сайт.",[259,2290,2291],{},"Перевірте статус замовлення.",[137,2293,2294,2296],{},[185,2295,2110],{}," Магазин оновлює статус лише тоді, коли клієнт повертається на сторінку «Дякуємо». Але клієнт може закрити вкладку або втратити зв'язок. Платіжка надсилає окреме серверне повідомлення (callback, або webhook), і саме воно має бути джерелом істини.",[137,2298,2299],{},[185,2300,2116],{},[256,2302,2303,2306,2309,2312],{},[259,2304,2305],{},"Статус оплати змінюється тільки за серверним callback, перевіреним за підписом.",[259,2307,2308],{},"Повернення клієнта на сайт лише показує стан і не змінює його.",[259,2310,2311],{},"Callback має бути ідемпотентним: платіжка може надіслати його двічі, і друга обробка не має ні дублювати листи, ні змінювати статус назад.",[259,2313,2314],{},"Для замовлень, що довго «висять» в очікуванні, потрібне фонове завдання, яке запитує статус у платіжки напряму.",[137,2316,2317,2318,727],{},"Інтеграції платежів і доставки це окрема велика тема, її ми розбираємо в статті ",[245,2319,1700],{"href":1261},[144,2321,2323],{"id":2322},"баг-3-закінчилась-сесія-і-кошик-зник","Баг 3. Закінчилась сесія, і кошик зник",[137,2325,2326,2328],{},[185,2327,2085],{}," Клієнт заповнює форму 15 хвилин, відволікається, натискає «Оформити», і замість замовлення бачить помилку «419 Page Expired» або порожній кошик.",[137,2330,2331],{},[185,2332,2091],{},[299,2334,2335,2338,2341],{},[259,2336,2337],{},"Додайте товар у кошик, відкрийте checkout.",[259,2339,2340],{},"Залиште сторінку на час, довший за час життя сесії.",[259,2342,2343],{},"Спробуйте відправити форму.",[137,2345,2346,2348],{},[185,2347,2110],{}," Сесія (або CSRF-токен) прострочена, а сайт реагує сухою технічною помилкою й не зберігає введені дані. Особливо часто це трапляється на мобільних: вкладку вивантажує з пам'яті, поки клієнт переходить у банківський застосунок.",[137,2350,2351],{},[185,2352,2116],{},[256,2354,2355,2358,2361],{},[259,2356,2357],{},"Кошик зберігається в базі (прив'язується до гостьового ідентифікатора в cookie), а не лише в сесії.",[259,2359,2360],{},"Токен захисту оновлюється автоматично, а при помилці користувач бачить зрозуміле повідомлення із збереженими даними форми.",[259,2362,2363],{},"Введені поля тимчасово зберігаються на клієнті (без паролів і даних картки) і відновлюються після перезавантаження.",[144,2365,2367],{"id":2366},"баг-4-валідація-відхиляє-нормальні-дані","Баг 4. Валідація відхиляє нормальні дані",[137,2369,2370,2372],{},[185,2371,2085],{}," Клієнт вводить правильні дані, але форма каже «невірний формат» і не пускає далі. Він іде, а ви навіть не бачите, що така спроба була.",[137,2374,2375],{},[185,2376,2377],{},"Типові випадки.",[256,2379,2380,2387,2390,2397,2400],{},[259,2381,2382,2383,2386],{},"Телефон у форматі ",[386,2384,2385],{},"+38 (050) 123-45-67"," проти маски, яка очікує лише цифри.",[259,2388,2389],{},"Email із пробілом наприкінці, який додає автозаповнення смартфона.",[259,2391,2392,2393,2396],{},"Прізвище з апострофом (",[386,2394,2395],{},"Дем'яненко",") або подвійне через дефіс.",[259,2398,2399],{},"Адреса з кирилицею й латинськими літерами в назві вулиці.",[259,2401,2402,2403,1666],{},"Індекс чи будинок із літерою (",[386,2404,2405],{},"12\u002FА",[137,2407,2408,2410],{},[185,2409,2091],{}," Створіть невеликий список проблемних значень і по черзі введіть їх у кожне поле. Окремо перевірте автозаповнення браузера на телефоні.",[137,2412,2413,2415],{},[185,2414,2116],{}," Нормалізуйте введення, а не відхиляйте: видаляйте пробіли з email, зводьте телефон до єдиного формату на сервері, не обмежуйте символи в іменах. Правило: краще прийняти зайве й потім перевірити, ніж не пустити клієнта. Помилка має показуватись біля конкретного поля й пояснювати, що не так.",[144,2417,2419],{"id":2418},"баг-5-нова-пошта-порожній-чи-недоступний-вибір-відділення","Баг 5. Нова Пошта: порожній чи недоступний вибір відділення",[137,2421,2422,2424],{},[185,2423,2085],{}," Клієнт вибирає «Нова Пошта», але список відділень не завантажується, або місто знайдено, а відділень немає, або вибране відділення зникає після зміни кількості товарів.",[137,2426,2427],{},[185,2428,2091],{},[299,2430,2431,2434,2437,2440],{},[259,2432,2433],{},"Виберіть доставку Новою Поштою.",[259,2435,2436],{},"Знайдіть місто за частиною назви, а також населений пункт, що має двійників в інших областях.",[259,2438,2439],{},"Виберіть відділення, потім змініть кількість товару й подивіться, чи не скинувся вибір.",[259,2441,2442],{},"Вимкніть мережу посеред вибору й спробуйте знову.",[137,2444,2445,2447],{},[185,2446,2110],{}," Магазин залежить від зовнішнього API й не має запасного плану. Якщо API повільне чи недоступне, форма застигає. Інший варіант: список відділень кешується занадто довго, і клієнтові пропонують закрите відділення.",[137,2449,2450],{},[185,2451,2116],{},[256,2453,2454,2457,2460,2463],{},[259,2455,2456],{},"Таймаут і повторні спроби для запитів до API, зрозуміле повідомлення при збої.",[259,2458,2459],{},"Кеш довідника міст і відділень із регулярним оновленням у фоні.",[259,2461,2462],{},"Збереження вибору при зміні кошика.",[259,2464,2465],{},"Запасний варіант: поле «адреса вручну» чи можливість оформити замовлення з уточненням доставки менеджером, щоб збій чужого API не блокував продаж.",[144,2467,2469],{"id":2468},"баг-6-ціна-на-checkout-відрізняється-від-ціни-в-каталозі","Баг 6. Ціна на checkout відрізняється від ціни в каталозі",[137,2471,2472,2474],{},[185,2473,2085],{}," У каталозі товар коштує 1 200 грн, у кошику 1 250, на checkout 1 190. Клієнт губиться й іде, або ще гірше: купує за помилковою ціною, і ви працюєте в збиток.",[137,2476,2477],{},[185,2478,2479],{},"Причини.",[256,2481,2482,2485,2488,2491,2494],{},[259,2483,2484],{},"Знижка рахується на різних етапах за різною формулою (до чи після доставки).",[259,2486,2487],{},"Округлення відбувається в різних місцях, і копійки розходяться.",[259,2489,2490],{},"Кеш каталогу показує стару ціну після зміни.",[259,2492,2493],{},"Промокод застосовується до товарів, які не мали б входити в акцію.",[259,2495,2496],{},"Валюта чи ПДВ рахуються не однаково на фронті й на бекенді.",[137,2498,2499,2501],{},[185,2500,2091],{}," Візьміть 3–4 товари з різними знижками й порівняйте ціну в списку, картці, кошику, checkout, листі й адмінці. Виконайте це з промокодом і без. Кожен розрахунок звіряйте з калькулятором.",[137,2503,2504,2506],{},[185,2505,2116],{}," Єдине місце, де рахується ціна. Фронтенд тільки показує те, що повернув сервер. Суму замовлення фіксують у момент створення (знімок цін), щоб подальші зміни каталогу не впливали на вже оформлені замовлення. Гроші зберігають у копійках цілим числом, а не числом із плаваючою комою:",[416,2508,2510],{"className":2120,"code":2509,"language":2122,"meta":14,"style":14},"\u002F\u002F ризикований варіант: float\n$total = 19.99 * 3; \u002F\u002F 59.97, але 59.969999... у деяких випадках\n\n\u002F\u002F надійний варіант: копійки в цілих числах\n$totalMinor = 1999 * 3; \u002F\u002F 5997\n",[386,2511,2512,2517,2538,2542,2547],{"__ignoreMap":14},[424,2513,2514],{"class":426,"line":427},[424,2515,2516],{"class":2129},"\u002F\u002F ризикований варіант: float\n",[424,2518,2519,2522,2524,2527,2530,2533,2535],{"class":426,"line":465},[424,2520,2521],{"class":430},"$total ",[424,2523,442],{"class":651},[424,2525,2526],{"class":438}," 19.99",[424,2528,2529],{"class":651}," *",[424,2531,2532],{"class":438}," 3",[424,2534,641],{"class":430},[424,2536,2537],{"class":2129},"\u002F\u002F 59.97, але 59.969999... у деяких випадках\n",[424,2539,2540],{"class":426,"line":879},[424,2541,2196],{"emptyLinePlaceholder":933},[424,2543,2544],{"class":426,"line":2181},[424,2545,2546],{"class":2129},"\u002F\u002F надійний варіант: копійки в цілих числах\n",[424,2548,2549,2552,2554,2557,2559,2561,2563],{"class":426,"line":2187},[424,2550,2551],{"class":430},"$totalMinor ",[424,2553,442],{"class":651},[424,2555,2556],{"class":438}," 1999",[424,2558,2529],{"class":651},[424,2560,2532],{"class":438},[424,2562,641],{"class":430},[424,2564,2565],{"class":2129},"\u002F\u002F 5997\n",[137,2567,2568],{},"Для магазину це особливо важливо, бо округлення накопичується на великих замовленнях і з'являється як «чомусь не сходиться з бухгалтерією».",[144,2570,2572],{"id":2571},"баг-7-мобільний-checkout-де-не-можна-натиснути-кнопку","Баг 7. Мобільний checkout, де не можна натиснути кнопку",[137,2574,2575,2577],{},[185,2576,2085],{}," На iPhone чи Android клієнт не може завершити замовлення: кнопка перекрита липким банером, клавіатура закриває поле, випадаючий список не відкривається, форма «стрибає».",[137,2579,2580],{},[185,2581,2091],{},[299,2583,2584,2587,2590,2593],{},[259,2585,2586],{},"Відкрийте checkout на реальному телефоні (iPhone із Safari й Android із Chrome), а не лише в емуляторі.",[259,2588,2589],{},"Заповніть форму, перемикаючись між полями.",[259,2591,2592],{},"Подивіться, чи не перекриває щось кнопку підтвердження, коли відкрита клавіатура.",[259,2594,2595],{},"Спробуйте повернути екран і змінити масштаб тексту в системі.",[137,2597,2598,2600],{},[185,2599,2110],{}," Верстку перевіряли на десктопі. Мобільні браузери по-різному обробляють висоту екрана, фіксовані елементи й автозуми в полях вводу. У Safari поле з розміром шрифту менше 16 пікселів автоматично збільшується при фокусі, що ламає макет.",[137,2602,2603,2605,2606,1646,2609,1646,2612,2615],{},[185,2604,2116],{}," Шрифт полів від 16 пікселів, правильні типи полів (",[386,2607,2608],{},"type=\"tel\"",[386,2610,2611],{},"inputmode",[386,2613,2614],{},"autocomplete","), кнопка завершення не фіксується там, де може бути закрита клавіатурою, а перевірка проводиться на реальних пристроях. Мобільний трафік у більшості магазинів складає більшу частину відвідувань, тож цей баг особливо дорогий.",[744,2617,2618],{},[137,2619,2620,2623,2624,2626],{},[185,2621,2622],{},"Хочете знати, де губляться замовлення саме у вашому магазині?"," Наш безкоштовний експрес-чек за 48 годин покаже 10–15 ключових проблем: перевіряємо checkout, мобільну версію й швидкість. Якщо проблем багато, ми запропонуємо ",[245,2625,1324],{"href":31}," від 6 000 грн.",[144,2628,2630],{"id":2629},"як-знайти-такі-баги-до-клієнта","Як знайти такі баги до клієнта",[137,2632,2633],{},"Усі сім багів об'єднує одне: їх не видно на «щасливому шляху». Розробник пройшов checkout один раз, усе спрацювало, і задачу закрито. Щоб ловити такі проблеми системно, потрібен підхід.",[137,2635,2636,2639],{},[185,2637,2638],{},"Тестуйте негативні сценарії."," Для кожного кроку питайте: «Що буде, якщо це не спрацює?». Помилка платіжки, відсутність мережі, подвійний клік, закінчення сесії, повторний запит.",[137,2641,2642,2645],{},[185,2643,2644],{},"Використовуйте тестові середовища сервісів."," Усі популярні платіжки й Нова Пошта мають sandbox. Тестова картка з успішною оплатою, відхиленням і відмовою 3-D Secure це мінімум.",[137,2647,2648,2651],{},[185,2649,2650],{},"Логуйте й моніторьте."," Якщо замовлення губляться, ви маєте про це знати до дзвінка клієнта. Налаштуйте:",[256,2653,2654,2657,2660],{},[259,2655,2656],{},"запис усіх callback платіжки з тілом і підписом;",[259,2658,2659],{},"сповіщення (у Telegram чи пошту) про замовлення, що «висять» в очікуванні понад 30 хвилин;",[259,2661,2662],{},"метрики воронки: скільки людей дійшло до checkout і скільки завершили. Різкий провал це сигнал.",[137,2664,2665,2668,2669,2673,2674,727],{},[185,2666,2667],{},"Автоматизуйте критичний шлях."," Найважливіший сценарій «товар → кошик → оплата → замовлення» варто покрити автотестом, який запускається на кожен реліз. Ми використовуємо Playwright і запускаємо тести в CI; детальніше про ",[245,2670,2672],{"href":2671},"\u002Fposluhy\u002Favtomatyzatsiia-testuvannia","автоматизацію тестування"," і про те, що автоматизувати спершу, у статті ",[245,2675,1932],{"href":1931},[137,2677,2678,2681],{},[185,2679,2680],{},"Повторюйте регрес після змін."," Кожне оновлення модуля, зміна ціноутворення чи нова доставка можуть зламати те, що працювало. Перед релізом проганяйте ключові пункти, а не лише нову функцію.",[144,2683,2685],{"id":2684},"короткий-підсумок","Короткий підсумок",[137,2687,2688],{},"Сім типових причин, чому губляться замовлення на checkout:",[299,2690,2691,2694,2697,2700,2703,2706,2709],{},[259,2692,2693],{},"Подвійний клік без ідемпотентності.",[259,2695,2696],{},"Статус оплати залежить від повернення клієнта, а не від callback.",[259,2698,2699],{},"Сесія й токени закінчуються без збереження кошика.",[259,2701,2702],{},"Валідація відхиляє нормальні дані.",[259,2704,2705],{},"Залежність від API Нової Пошти без запасного плану.",[259,2707,2708],{},"Розбіжності цін між етапами.",[259,2710,2711],{},"Непридатний до використання мобільний checkout.",[137,2713,2714],{},"Жоден із цих багів не потребує складної технології для виправлення, лише уваги до негативних сценаріїв і тестування на реальних пристроях. Ціна ж їх у прямих втратах: кожне загублене замовлення це не лише втрачений продаж, а й втрачений клієнт.",[137,2716,2717],{},"Почніть із двох речей уже сьогодні. По-перше, самі пройдіть checkout на телефоні зі слабким інтернетом, двічі натискаючи кнопки. По-друге, переконайтесь, що у вас є сповіщення про замовлення, які не завершились оплатою. Це займе годину, а може врятувати тижні виручки.",[744,2719,2720],{},[137,2721,2722,1982,2725,2727,2728,2732],{},[185,2723,2724],{},"Потрібна перевірка checkout від людей, які це роблять щодня?",[245,2726,1985],{"href":17}," або подивіться, як проходить ",[245,2729,2731],{"href":2730},"\u002Fposluhy\u002Ftestuvannia-saitiv","тестування сайтів і магазинів",": регрес, кросбраузерність, звіт із відео й пріоритетами.",[875,2734,2735],{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":14,"searchDepth":465,"depth":879,"links":2737},[2738,2739,2740,2741,2742,2743,2744,2745,2746,2747],{"id":2047,"depth":465,"text":2048},{"id":2079,"depth":465,"text":2080},{"id":2270,"depth":465,"text":2271},{"id":2322,"depth":465,"text":2323},{"id":2366,"depth":465,"text":2367},{"id":2418,"depth":465,"text":2419},{"id":2468,"depth":465,"text":2469},{"id":2571,"depth":465,"text":2572},{"id":2629,"depth":465,"text":2630},{"id":2684,"depth":465,"text":2685},"checkout.bugs",[2750,2752,2754,2756],{"marker":2008,"text":2751},"подвійний клік: два замовлення",{"marker":2008,"text":2753},"callback оплати втрачено",{"marker":910,"text":2755},"телефон з пробілами не проходить",{"marker":913,"text":2757},"перевірено на 12 пристроях","7 багів",[2760,2763,2766,2769],{"q":2761,"a":2762},"Чому клієнт оплатив, а замовлення в адмінці не з'явилось?","Найчастіше колбек від платіжної системи не дійшов або не був коректно опрацьований, тому статус замовлення не оновився. Перевірте логи колбеків і порівняйте їх із випискою платіжної системи. Обробка колбеків має бути надійною та стійкою до повторних викликів.",{"q":2764,"a":2765},"Як зрозуміти, що саме на checkout втрачаються замовлення?","Порівняйте в аналітиці кількість початих оформлень із завершеними й подивіться журнал помилок сервера. Різкий провал на одному кроці вказує на проблему. Корисно також самому пройти замовлення з різних пристроїв і способів оплати та опитати службу підтримки про скарги клієнтів.",{"q":2767,"a":2768},"Чому ціна на checkout може відрізнятися від ціни в каталозі?","Зазвичай через кеш цін, різне округлення або знижки й купони, які рахуються в різних місцях коду. Остаточну суму має обчислювати один серверний розрахунок. Перевірте акційні товари, купони та зміну кількості в кошику. Такі розбіжності підривають довіру й призводять до відмов саме перед оплатою.",{"q":2770,"a":2771},"Як часто потрібно тестувати checkout?","Після кожного релізу, що зачіпає кошик, оплату, доставку чи форми, а також після оновлення CMS і плагінів. Для критичного шляху покупки корисно мати короткий набір регресійних перевірок. Якщо проблем накопичилось багато, допоможе разовий QA-аудит від 6 000 грн.",{},"\u002Fuk\u002Fblog\u002Fchomu-hubliatsia-zamovlennia-na-checkout",{"title":1629,"description":2041},"Чому губляться замовлення на checkout: 7 типових багів інтернет-магазину з прикладами, кроками відтворення і способами виправлення та перевірки.","Чому губляться замовлення на checkout — Tochno.","chomu-hubliatsia-zamovlennia-na-checkout","uk\u002Fblog\u002Fchomu-hubliatsia-zamovlennia-na-checkout",[942,2033],"Jj7DAVybK_mnYfmPcj46ovCAPuFoCyNGoxW55MV4-iY",{"id":130,"title":131,"author":132,"body":2782,"cover":901,"coverFile":902,"coverLines":3282,"coverStat":915,"date":916,"description":139,"excerpt":901,"extension":917,"faq":3287,"featured":931,"key":901,"meta":3292,"navigation":933,"path":934,"readingTime":935,"seo":3293,"seoDescription":937,"seoTitle":938,"slug":939,"stem":940,"tags":3294,"updated":944,"__hash__":945},{"type":134,"value":2783,"toc":3260},[2784,2786,2788,2790,2792,2852,2857,2859,2877,2879,2881,2883,2885,2898,2900,2902,2904,2906,2908,2920,2922,2924,2926,2928,2930,2932,2934,2950,2952,2956,3000,3002,3006,3008,3012,3014,3016,3018,3036,3038,3048,3050,3052,3054,3076,3080,3136,3138,3140,3142,3172,3174,3182,3184,3186,3196,3200,3202,3206,3208,3218,3220,3242,3246,3248,3250,3258],[137,2785,139],{},[137,2787,142],{},[144,2789,147],{"id":146},[137,2791,150],{},[152,2793,2794,2808],{},[155,2795,2796],{},[158,2797,2798,2800,2802,2804,2806],{},[161,2799,163],{},[161,2801,166],{},[161,2803,169],{},[161,2805,172],{},[161,2807,175],{},[177,2809,2810,2824,2838],{},[158,2811,2812,2816,2818,2820,2822],{},[182,2813,2814,188],{},[185,2815,187],{},[182,2817,191],{},[182,2819,194],{},[182,2821,197],{},[182,2823,200],{},[158,2825,2826,2830,2832,2834,2836],{},[182,2827,2828,208],{},[185,2829,207],{},[182,2831,211],{},[182,2833,214],{},[182,2835,217],{},[182,2837,220],{},[158,2839,2840,2844,2846,2848,2850],{},[182,2841,2842,228],{},[185,2843,227],{},[182,2845,231],{},[182,2847,234],{},[182,2849,237],{},[182,2851,240],{},[137,2853,243,2854,251],{},[245,2855,250],{"href":247,"rel":2856},[249],[137,2858,254],{},[256,2860,2861,2865,2869,2873],{},[259,2862,2863,264],{},[185,2864,263],{},[259,2866,2867,270],{},[185,2868,269],{},[259,2870,2871,276],{},[185,2872,275],{},[259,2874,2875,282],{},[185,2876,281],{},[144,2878,286],{"id":285},[137,2880,289],{},[291,2882,294],{"id":293},[137,2884,297],{},[299,2886,2887,2894],{},[259,2888,2889,306,2891,312],{},[185,2890,305],{},[245,2892,311],{"href":309,"rel":2893},[249],[259,2895,2896,318],{},[185,2897,317],{},[137,2899,321],{},[291,2901,325],{"id":324},[137,2903,328],{},[291,2905,332],{"id":331},[137,2907,335],{},[256,2909,2910,2912,2914,2916,2918],{},[259,2911,340],{},[259,2913,343],{},[259,2915,346],{},[259,2917,349],{},[259,2919,352],{},[137,2921,355],{},[291,2923,359],{"id":358},[137,2925,362],{},[144,2927,366],{"id":365},[137,2929,369],{},[291,2931,373],{"id":372},[137,2933,376],{},[256,2935,2936,2938,2942,2944],{},[259,2937,381],{},[259,2939,384,2940,389],{},[386,2941,388],{},[259,2943,392],{},[259,2945,395,2946,399,2948,403],{},[386,2947,398],{},[386,2949,402],{},[291,2951,407],{"id":406},[137,2953,410,2954,414],{},[386,2955,413],{},[416,2957,2958],{"className":418,"code":419,"language":420,"meta":14,"style":14},[386,2959,2960,2984],{"__ignoreMap":14},[424,2961,2962,2964,2966,2968,2970,2972,2974,2976,2978,2980,2982],{"class":426,"line":427},[424,2963,431],{"class":430},[424,2965,435],{"class":434},[424,2967,439],{"class":438},[424,2969,442],{"class":430},[424,2971,446],{"class":445},[424,2973,449],{"class":438},[424,2975,442],{"class":430},[424,2977,454],{"class":445},[424,2979,457],{"class":438},[424,2981,442],{"class":430},[424,2983,462],{"class":445},[424,2985,2986,2988,2990,2992,2994,2996,2998],{"class":426,"line":465},[424,2987,468],{"class":438},[424,2989,442],{"class":430},[424,2991,473],{"class":445},[424,2993,476],{"class":438},[424,2995,442],{"class":430},[424,2997,481],{"class":445},[424,2999,484],{"class":430},[291,3001,488],{"id":487},[137,3003,491,3004,496],{},[245,3005,495],{"href":494},[291,3007,500],{"id":499},[137,3009,503,3010,507],{},[386,3011,506],{},[144,3013,511],{"id":510},[137,3015,514],{},[137,3017,517],{},[256,3019,3020,3024,3028,3032],{},[259,3021,3022,525],{},[185,3023,524],{},[259,3025,3026,531],{},[185,3027,530],{},[259,3029,3030,537],{},[185,3031,536],{},[259,3033,3034,543],{},[185,3035,542],{},[137,3037,546],{},[299,3039,3040,3042,3044,3046],{},[259,3041,551],{},[259,3043,554],{},[259,3045,557],{},[259,3047,560],{},[144,3049,564],{"id":563},[137,3051,567],{},[137,3053,570],{},[256,3055,3056,3060,3064,3068,3072],{},[259,3057,3058,578],{},[185,3059,577],{},[259,3061,3062,584],{},[185,3063,583],{},[259,3065,3066,590],{},[185,3067,589],{},[259,3069,3070,596],{},[185,3071,595],{},[259,3073,3074,602],{},[185,3075,601],{},[137,3077,605,3078,609],{},[386,3079,608],{},[416,3081,3082],{"className":612,"code":613,"language":614,"meta":14,"style":14},[386,3083,3084,3120],{"__ignoreMap":14},[424,3085,3086,3088,3090,3092,3094,3096,3098,3100,3102,3104,3106,3108,3110,3112,3114,3116,3118],{"class":426,"line":427},[424,3087,621],{"class":438},[424,3089,624],{"class":430},[424,3091,608],{"class":438},[424,3093,629],{"class":430},[424,3095,632],{"class":438},[424,3097,635],{"class":430},[424,3099,638],{"class":438},[424,3101,641],{"class":430},[424,3103,398],{"class":438},[424,3105,629],{"class":430},[424,3107,648],{"class":438},[424,3109,652],{"class":651},[424,3111,641],{"class":430},[424,3113,402],{"class":438},[424,3115,629],{"class":430},[424,3117,661],{"class":438},[424,3119,664],{"class":430},[424,3121,3122,3124,3126,3128,3130,3132,3134],{"class":426,"line":465},[424,3123,669],{"class":438},[424,3125,624],{"class":430},[424,3127,674],{"class":438},[424,3129,629],{"class":430},[424,3131,679],{"class":438},[424,3133,682],{"class":651},[424,3135,664],{"class":430},[137,3137,687],{},[144,3139,691],{"id":690},[137,3141,694],{},[299,3143,3144,3150,3154,3158,3164,3168],{},[259,3145,3146,702,3148,705],{},[185,3147,701],{},[386,3149,388],{},[259,3151,3152,711],{},[185,3153,710],{},[259,3155,3156,717],{},[185,3157,716],{},[259,3159,3160,723,3162,727],{},[185,3161,722],{},[386,3163,726],{},[259,3165,3166,733],{},[185,3167,732],{},[259,3169,3170,739],{},[185,3171,738],{},[137,3173,742],{},[744,3175,3176],{},[137,3177,3178,751,3180,727],{},[185,3179,750],{},[245,3181,754],{"href":31},[144,3183,758],{"id":757},[137,3185,761],{},[256,3187,3188,3190,3192,3194],{},[259,3189,766],{},[259,3191,769],{},[259,3193,772],{},[259,3195,775],{},[137,3197,778,3198,727],{},[245,3199,782],{"href":781},[144,3201,786],{"id":785},[137,3203,789,3204,794],{},[245,3205,793],{"href":792},[137,3207,797],{},[256,3209,3210,3212,3214,3216],{},[259,3211,802],{},[259,3213,805],{},[259,3215,808],{},[259,3217,811],{},[144,3219,815],{"id":814},[256,3221,3222,3226,3230,3234,3238],{},[259,3223,3224,823],{},[185,3225,822],{},[259,3227,3228,829],{},[185,3229,828],{},[259,3231,3232,835],{},[185,3233,834],{},[259,3235,3236,841],{},[185,3237,840],{},[259,3239,3240,847],{},[185,3241,846],{},[137,3243,850,3244,727],{},[245,3245,854],{"href":853},[144,3247,858],{"id":857},[137,3249,861],{},[744,3251,3252],{},[137,3253,3254,869,3256,873],{},[185,3255,868],{},[245,3257,872],{"href":17},[875,3259,877],{},{"title":14,"searchDepth":465,"depth":879,"links":3261},[3262,3263,3269,3275,3276,3277,3278,3279,3280,3281],{"id":146,"depth":465,"text":147},{"id":285,"depth":465,"text":286,"children":3264},[3265,3266,3267,3268],{"id":293,"depth":879,"text":294},{"id":324,"depth":879,"text":325},{"id":331,"depth":879,"text":332},{"id":358,"depth":879,"text":359},{"id":365,"depth":465,"text":366,"children":3270},[3271,3272,3273,3274],{"id":372,"depth":879,"text":373},{"id":406,"depth":879,"text":407},{"id":487,"depth":879,"text":488},{"id":499,"depth":879,"text":500},{"id":510,"depth":465,"text":511},{"id":563,"depth":465,"text":564},{"id":690,"depth":465,"text":691},{"id":757,"depth":465,"text":758},{"id":785,"depth":465,"text":786},{"id":814,"depth":465,"text":815},{"id":857,"depth":465,"text":858},[3283,3284,3285,3286],{"marker":905,"text":906},{"marker":905,"text":908},{"marker":910,"text":911},{"marker":913,"text":914},[3288,3289,3290,3291],{"q":920,"a":921},{"q":923,"a":924},{"q":926,"a":927},{"q":929,"a":930},{},{"title":131,"description":139},[942,943],{"id":3296,"title":1700,"author":132,"body":3297,"cover":901,"coverFile":4498,"coverLines":4499,"coverStat":4508,"date":916,"description":3301,"excerpt":901,"extension":917,"faq":4509,"featured":931,"key":901,"meta":4522,"navigation":933,"path":4523,"readingTime":1483,"seo":4524,"seoDescription":4525,"seoTitle":4526,"slug":4527,"stem":4528,"tags":4529,"updated":1467,"__hash__":4531},"blog_uk\u002Fuk\u002Fblog\u002Fintehratsiia-novoi-poshty-ta-oplaty.md",{"type":134,"value":3298,"toc":4476},[3299,3302,3305,3309,3312,3315,3322,3326,3330,3333,3336,3355,3359,3362,3365,3368,3372,3383,3386,3390,3394,3401,3404,3421,3424,3803,3810,3814,3817,3828,3831,3835,3838,3841,3856,3859,3863,3867,3874,3881,3885,3888,3891,4244,4251,4255,4262,4265,4311,4314,4318,4321,4324,4336,4340,4343,4387,4397,4407,4411,4414,4428,4431,4435,4438,4455,4463,4473],[137,3300,3301],{},"Інтеграція Нової Пошти та онлайн-оплати ламається не там, де її чекають. Сам виклик API зазвичай працює з першого разу. Проблеми починаються на межах: коли відділення зникло з довідника, колбек платіжки прийшов двічі, а ТТН створилася на неправильну вагу. Ця стаття для власників магазинів і розробників на Laravel: 10 найчастіших місць поломок і те, як ми їх перевіряємо.",[137,3303,3304],{},"Нижче все базується на практиці Laravel-проєктів з доставкою Новою Поштою і оплатою через LiqPay або схожі сервіси. Конкретні назви полів перевіряйте за актуальною документацією провайдера: API змінюються, а принципи ні.",[144,3306,3308],{"id":3307},"чому-саме-ці-інтеграції-створюють-найбільше-проблем","Чому саме ці інтеграції створюють найбільше проблем",[137,3310,3311],{},"Доставка й оплата живуть поза вашим кодом. Ви не контролюєте їхню доступність, формат відповідей і час реакції. До того ж обидві інтеграції стосуються грошей: помилка у відображенні банера не коштує нічого, а помилка в оплаті коштує замовлення і довіри клієнта.",[137,3313,3314],{},"Є ще одна причина. Ці інтеграції рідко тестують на повному шляху. Розробник перевіряє «happy path» у sandbox, замовник клікає один раз у тестовому режимі, і все виглядає добре. Реальні клієнти роблять інше: закривають вкладку під час 3-D Secure, обирають поштомат для посилки на 30 кг, вводять номер телефону з пробілами.",[137,3316,3317,3318,3321],{},"Якщо ви замовляєте ",[245,3319,3320],{"href":28},"розробку інтернет-магазину",", запитайте підрядника, як саме він перевіряє ці сценарії. Відповідь «ми тестували в sandbox» недостатня.",[144,3323,3325],{"id":3324},"нова-пошта-довідники-та-вибір-відділення","Нова Пошта: довідники та вибір відділення",[291,3327,3329],{"id":3328},"_1-застарілі-довідники-міст-і-відділень","1. Застарілі довідники міст і відділень",[137,3331,3332],{},"Типова помилка: розробник один раз завантажує список відділень у базу і забуває про нього. Відділення відкриваються, закриваються, переїжджають, тимчасово не працюють. Клієнт обирає відділення, якого вже немає, а ТТН не створюється.",[137,3334,3335],{},"Що робити:",[256,3337,3338,3345,3352],{},[259,3339,3340,3341,3344],{},"Оновлюйте довідник за розкладом (",[386,3342,3343],{},"php artisan schedule","), а не вручну. Для невеликого магазину достатньо раз на добу вночі.",[259,3346,3347,3348,3351],{},"Зберігайте в замовленні не лише ",[386,3349,3350],{},"warehouse_ref",", а й текстовий знімок: місто, номер відділення, адресу. Через місяць відділення може змінитися, а менеджеру треба бачити, що вибрав клієнт.",[259,3353,3354],{},"Позначайте відділення, що зникли з довідника, а не видаляйте. Інакше старі замовлення втратять зв'язок.",[291,3356,3358],{"id":3357},"_2-обмеження-за-вагою-та-габаритами","2. Обмеження за вагою та габаритами",[137,3360,3361],{},"Не кожне відділення приймає вантаж будь-якої ваги. Поштомати мають жорсткі обмеження за розміром і вагою посилки, а частина відділень не приймає великогабаритні вантажі. У довіднику відділень є поля з максимальною вагою і габаритами, і їх треба використовувати.",[137,3363,3364],{},"Класичний баг: у кошику важкий товар, у чекауті пропонуються всі відділення, клієнт обирає поштомат, а менеджер потім телефонує і просить змінити відділення. Це втрачений час і частина замовлень, які клієнт просто скасує.",[137,3366,3367],{},"Правильна поведінка: порахувати сумарну вагу кошика, відфільтрувати відділення за обмеженнями, а якщо жодне не підходить, показати зрозуміле повідомлення. Для цього в товарів мають бути заповнені вага й габарити. Це вимога до контенту, а не лише до коду.",[291,3369,3371],{"id":3370},"_3-пошук-міста-та-населені-пункти-з-однаковою-назвою","3. Пошук міста та населені пункти з однаковою назвою",[137,3373,3374,3375,3378,3379,3382],{},"В Україні багато населених пунктів з однаковими назвами в різних областях. Пошук по тексту без уточнення області повертає не те село. Використовуйте метод пошуку населених пунктів (",[386,3376,3377],{},"Address\u002FsearchSettlements",") і зберігайте ",[386,3380,3381],{},"Ref",", а не назву. У випадаючому списку показуйте область і район, щоб клієнт бачив, яке саме «Лісове» він обирає.",[137,3384,3385],{},"Окремо перевіряйте введення з помилками: «Днепр» замість «Дніпро», зайві пробіли, апостроф у «Кам'янське» (є три різні символи апострофа). Автокомпліт має це переживати.",[144,3387,3389],{"id":3388},"створення-накладної-ттн","Створення накладної (ТТН)",[291,3391,3393],{"id":3392},"_4-помилки-валідації-при-створенні-ттн","4. Помилки валідації при створенні ТТН",[137,3395,3396,3397,3400],{},"Накладна створюється методом ",[386,3398,3399],{},"InternetDocument\u002Fsave",", і тут найбільше «дрібних» відмов: телефон отримувача у неправильному форматі, не заповнене прізвище, оголошена вартість нуль, вага менша за допустиму мінімальну. Якщо ваш код створює ТТН прямо в момент оформлення замовлення, клієнт бачить помилку, якої не розуміє.",[137,3402,3403],{},"Наша практика така:",[299,3405,3406,3412,3415,3418],{},[259,3407,3408,3409,727],{},"Нормалізуйте телефон при введенні: приберіть пробіли, дужки, дефіси, приведіть до формату ",[386,3410,3411],{},"380XXXXXXXXX",[259,3413,3414],{},"Створюйте ТТН не в HTTP-запиті клієнта, а у фоновому завданні (queue job).",[259,3416,3417],{},"Якщо API повернув помилку, зберігайте текст помилки в замовленні й показуйте менеджеру в адмінці. Не ковтайте виняток.",[259,3419,3420],{},"Додайте кнопку «Створити ТТН повторно» для менеджера.",[137,3422,3423],{},"Приклад каркаса завдання:",[416,3425,3427],{"className":2120,"code":3426,"language":2122,"meta":14,"style":14},"class CreateShipmentJob implements ShouldQueue\n{\n    public int $tries = 5;\n    public array $backoff = [30, 120, 600, 1800];\n\n    public function __construct(public int $orderId) {}\n\n    public function handle(NovaPoshtaClient $np): void\n    {\n        $order = Order::findOrFail($this->orderId);\n\n        \u002F\u002F Idempotency: do not create a second waybill for the same order\n        if ($order->ttn_number) {\n            return;\n        }\n\n        $response = $np->createWaybill($order);\n\n        if (! $response['success']) {\n            $order->update(['shipment_error' => json_encode($response['errors'], JSON_UNESCAPED_UNICODE)]);\n            throw new ShipmentFailed($response['errors']);\n        }\n\n        $order->update([\n            'ttn_number' => $response['data'][0]['IntDocNumber'],\n            'shipment_error' => null,\n        ]);\n    }\n}\n",[386,3428,3429,3444,3449,3468,3504,3508,3528,3532,3554,3559,3583,3587,3593,3607,3615,3621,3626,3645,3650,3667,3703,3722,3727,3732,3745,3772,3786,3792,3798],{"__ignoreMap":14},[424,3430,3431,3434,3438,3441],{"class":426,"line":427},[424,3432,3433],{"class":651},"class",[424,3435,3437],{"class":3436},"sQhOw"," CreateShipmentJob",[424,3439,3440],{"class":651}," implements",[424,3442,3443],{"class":438}," ShouldQueue\n",[424,3445,3446],{"class":426,"line":465},[424,3447,3448],{"class":430},"{\n",[424,3450,3451,3454,3457,3460,3462,3465],{"class":426,"line":879},[424,3452,3453],{"class":651},"    public",[424,3455,3456],{"class":651}," int",[424,3458,3459],{"class":430}," $tries ",[424,3461,442],{"class":651},[424,3463,3464],{"class":438}," 5",[424,3466,3467],{"class":430},";\n",[424,3469,3470,3472,3475,3478,3480,3483,3486,3488,3491,3493,3496,3498,3501],{"class":426,"line":2181},[424,3471,3453],{"class":651},[424,3473,3474],{"class":651}," array",[424,3476,3477],{"class":430}," $backoff ",[424,3479,442],{"class":651},[424,3481,3482],{"class":430}," [",[424,3484,3485],{"class":438},"30",[424,3487,1646],{"class":430},[424,3489,3490],{"class":438},"120",[424,3492,1646],{"class":430},[424,3494,3495],{"class":438},"600",[424,3497,1646],{"class":430},[424,3499,3500],{"class":438},"1800",[424,3502,3503],{"class":430},"];\n",[424,3505,3506],{"class":426,"line":2187},[424,3507,2196],{"emptyLinePlaceholder":933},[424,3509,3510,3512,3515,3518,3520,3523,3525],{"class":426,"line":2193},[424,3511,3453],{"class":651},[424,3513,3514],{"class":651}," function",[424,3516,3517],{"class":438}," __construct",[424,3519,2173],{"class":430},[424,3521,3522],{"class":651},"public",[424,3524,3456],{"class":651},[424,3526,3527],{"class":430}," $orderId) {}\n",[424,3529,3530],{"class":426,"line":2199},[424,3531,2196],{"emptyLinePlaceholder":933},[424,3533,3534,3536,3538,3541,3543,3546,3549,3551],{"class":426,"line":2219},[424,3535,3453],{"class":651},[424,3537,3514],{"class":651},[424,3539,3540],{"class":2146}," handle",[424,3542,2173],{"class":430},[424,3544,3545],{"class":438},"NovaPoshtaClient",[424,3547,3548],{"class":430}," $np)",[424,3550,609],{"class":651},[424,3552,3553],{"class":651}," void\n",[424,3555,3556],{"class":426,"line":1483},[424,3557,3558],{"class":430},"    {\n",[424,3560,3561,3564,3566,3568,3570,3573,3575,3578,3580],{"class":426,"line":935},[424,3562,3563],{"class":430},"        $order ",[424,3565,442],{"class":651},[424,3567,2140],{"class":438},[424,3569,2143],{"class":651},[424,3571,3572],{"class":2146},"findOrFail",[424,3574,2173],{"class":430},[424,3576,3577],{"class":438},"$this",[424,3579,2167],{"class":651},[424,3581,3582],{"class":430},"orderId);\n",[424,3584,3585],{"class":426,"line":1594},[424,3586,2196],{"emptyLinePlaceholder":933},[424,3588,3590],{"class":426,"line":3589},12,[424,3591,3592],{"class":2129},"        \u002F\u002F Idempotency: do not create a second waybill for the same order\n",[424,3594,3596,3599,3602,3604],{"class":426,"line":3595},13,[424,3597,3598],{"class":651},"        if",[424,3600,3601],{"class":430}," ($order",[424,3603,2167],{"class":651},[424,3605,3606],{"class":430},"ttn_number) {\n",[424,3608,3610,3613],{"class":426,"line":3609},14,[424,3611,3612],{"class":651},"            return",[424,3614,3467],{"class":430},[424,3616,3618],{"class":426,"line":3617},15,[424,3619,3620],{"class":430},"        }\n",[424,3622,3624],{"class":426,"line":3623},16,[424,3625,2196],{"emptyLinePlaceholder":933},[424,3627,3629,3632,3634,3637,3639,3642],{"class":426,"line":3628},17,[424,3630,3631],{"class":430},"        $response ",[424,3633,442],{"class":651},[424,3635,3636],{"class":430}," $np",[424,3638,2167],{"class":651},[424,3640,3641],{"class":2146},"createWaybill",[424,3643,3644],{"class":430},"($order);\n",[424,3646,3648],{"class":426,"line":3647},18,[424,3649,2196],{"emptyLinePlaceholder":933},[424,3651,3652,3654,3656,3658,3661,3664],{"class":426,"line":1633},[424,3653,3598],{"class":651},[424,3655,2205],{"class":430},[424,3657,2208],{"class":651},[424,3659,3660],{"class":430}," $response[",[424,3662,3663],{"class":445},"'success'",[424,3665,3666],{"class":430},"]) {\n",[424,3668,3670,3673,3675,3678,3680,3683,3685,3688,3691,3694,3697,3700],{"class":426,"line":3669},20,[424,3671,3672],{"class":430},"            $order",[424,3674,2167],{"class":651},[424,3676,3677],{"class":2146},"update",[424,3679,2236],{"class":430},[424,3681,3682],{"class":445},"'shipment_error'",[424,3684,2161],{"class":651},[424,3686,3687],{"class":438}," json_encode",[424,3689,3690],{"class":430},"($response[",[424,3692,3693],{"class":445},"'errors'",[424,3695,3696],{"class":430},"], ",[424,3698,3699],{"class":438},"JSON_UNESCAPED_UNICODE",[424,3701,3702],{"class":430},")]);\n",[424,3704,3706,3709,3712,3715,3717,3719],{"class":426,"line":3705},21,[424,3707,3708],{"class":651},"            throw",[424,3710,3711],{"class":651}," new",[424,3713,3714],{"class":438}," ShipmentFailed",[424,3716,3690],{"class":430},[424,3718,3693],{"class":445},[424,3720,3721],{"class":430},"]);\n",[424,3723,3725],{"class":426,"line":3724},22,[424,3726,3620],{"class":430},[424,3728,3730],{"class":426,"line":3729},23,[424,3731,2196],{"emptyLinePlaceholder":933},[424,3733,3735,3738,3740,3742],{"class":426,"line":3734},24,[424,3736,3737],{"class":430},"        $order",[424,3739,2167],{"class":651},[424,3741,3677],{"class":2146},[424,3743,3744],{"class":430},"([\n",[424,3746,3748,3751,3753,3755,3758,3761,3764,3766,3769],{"class":426,"line":3747},25,[424,3749,3750],{"class":445},"            'ttn_number'",[424,3752,2161],{"class":651},[424,3754,3660],{"class":430},[424,3756,3757],{"class":445},"'data'",[424,3759,3760],{"class":430},"][",[424,3762,3763],{"class":438},"0",[424,3765,3760],{"class":430},[424,3767,3768],{"class":445},"'IntDocNumber'",[424,3770,3771],{"class":430},"],\n",[424,3773,3775,3778,3780,3783],{"class":426,"line":3774},26,[424,3776,3777],{"class":445},"            'shipment_error'",[424,3779,2161],{"class":651},[424,3781,3782],{"class":438}," null",[424,3784,3785],{"class":430},",\n",[424,3787,3789],{"class":426,"line":3788},27,[424,3790,3791],{"class":430},"        ]);\n",[424,3793,3795],{"class":426,"line":3794},28,[424,3796,3797],{"class":430},"    }\n",[424,3799,3801],{"class":426,"line":3800},29,[424,3802,2256],{"class":430},[137,3804,3805,3806,3809],{},"Ключове тут не синтаксис, а перевірка ",[386,3807,3808],{},"ttn_number"," на початку. Без неї повторний запуск завдання створить другу накладну і ви заплатите за дві.",[291,3811,3813],{"id":3812},"_5-накладений-платіж-і-зворотна-доставка-грошей","5. Накладений платіж і зворотна доставка грошей",[137,3815,3816],{},"Накладений платіж додає складність: сума зворотної доставки має збігатися із сумою замовлення мінус уже сплачена частина. Типові баги:",[256,3818,3819,3822,3825],{},[259,3820,3821],{},"клієнт оплатив частково (знижка, промокод, бонуси), а ТТН створена з повною сумою накладеного платежу;",[259,3823,3824],{},"сума округлена по-різному в магазині і в накладній, і виникає розбіжність у копійки, яку бухгалтерія потім шукає тижнями;",[259,3826,3827],{},"для замовлень, оплачених карткою, накладений платіж взагалі не має створюватися, але через умову в коді все одно створюється.",[137,3829,3830],{},"Тестуйте комбінації: передоплата повна, передоплата частина, накладений платіж, промокод плюс накладений платіж. Це десять хвилин ручної перевірки, яка рятує від скарг.",[291,3832,3834],{"id":3833},"_6-недоступність-api-та-таймаути","6. Недоступність API та таймаути",[137,3836,3837],{},"API Нової Пошти буває повільним, іноді недоступним, іноді повертає помилку лише на певні запити. Якщо пошук відділень у чекауті йде прямо в API без кешу й обмеження часу очікування, повільна відповідь зависає всю форму.",[137,3839,3840],{},"Мінімум, який варто мати:",[256,3842,3843,3850,3853],{},[259,3844,3845,3846,3849],{},"явний таймаут HTTP-клієнта (у Laravel ",[386,3847,3848],{},"Http::timeout(8)->retry(2, 200)",");",[259,3851,3852],{},"кеш довідників, щоб чекаут не залежав від API під час пошуку;",[259,3854,3855],{},"запасний сценарій: якщо довідник недоступний, дозволити ввести адресу вручну й передати замовлення менеджеру на уточнення.",[137,3857,3858],{},"Це рішення про бізнес, а не лише про код: що важливіше, не втратити замовлення чи отримати ідеальні дані. Для магазину майже завжди першим є замовлення.",[144,3860,3862],{"id":3861},"онлайн-оплата-колбеки-статуси-дублі","Онлайн-оплата: колбеки, статуси, дублі",[291,3864,3866],{"id":3865},"_7-довіра-до-сторінки-повернення-замість-серверного-колбеку","7. Довіра до сторінки повернення замість серверного колбеку",[137,3868,3869,3870,3873],{},"Найнебезпечніша помилка в оплаті. Після платежу клієнт повертається на сторінку «Дякуємо за замовлення» (",[386,3871,3872],{},"result_url","). Якщо ви позначаєте замовлення оплаченим саме тут, то ризикуєте двічі: клієнт може закрити вкладку до повернення, і оплата не зафіксується, а зловмисник може відкрити цю адресу вручну і вдати оплату.",[137,3875,3876,3877,3880],{},"Правильна схема така: статус замовлення змінює лише серверний колбек платіжної системи (",[386,3878,3879],{},"server_url"," у LiqPay), а сторінка повернення тільки показує поточний статус і за потреби опитує його.",[291,3882,3884],{"id":3883},"_8-непідтверджений-підпис-і-повторні-колбеки","8. Непідтверджений підпис і повторні колбеки",[137,3886,3887],{},"Платіжна система надсилає колбек із підписом. Якщо ви його не перевіряєте, будь-хто може надіслати POST-запит і позначити замовлення оплаченим. У LiqPay підпис розраховується від приватного ключа і даних запиту; формула є в документації, і її треба реалізувати та покрити тестом.",[137,3889,3890],{},"Платіжні системи також повторюють колбеки, якщо ваш сервер відповів не 200 або не відповів вчасно. Тому обробник має бути ідемпотентним: повторний колбек з тим самим статусом не повинен ні створювати друге замовлення, ні списувати двічі залишки, ні надсилати другого листа.",[416,3892,3894],{"className":2120,"code":3893,"language":2122,"meta":14,"style":14},"public function handle(Request $request): Response\n{\n    $data = $request->input('data');\n    $signature = $request->input('signature');\n\n    if (! hash_equals($this->sign($data), $signature)) {\n        abort(403);\n    }\n\n    $payload = json_decode(base64_decode($data), true);\n\n    DB::transaction(function () use ($payload) {\n        $order = Order::where('public_id', $payload['order_id'])\n            ->lockForUpdate()\n            ->firstOrFail();\n\n        \u002F\u002F Terminal state reached already: ignore repeated callbacks\n        if ($order->payment_status === 'paid') {\n            return;\n        }\n\n        if ($payload['status'] === 'success' && (float) $payload['amount'] === (float) $order->total) {\n            $order->markPaid($payload['payment_id']);\n        }\n    });\n\n    return response('OK');\n}\n",[386,3895,3896,3917,3921,3940,3960,3964,3988,4000,4004,4008,4031,4035,4059,4085,4096,4106,4110,4115,4135,4141,4145,4149,4197,4214,4218,4223,4227,4240],{"__ignoreMap":14},[424,3897,3898,3900,3902,3904,3906,3909,3912,3914],{"class":426,"line":427},[424,3899,3522],{"class":651},[424,3901,3514],{"class":651},[424,3903,3540],{"class":2146},[424,3905,2173],{"class":430},[424,3907,3908],{"class":438},"Request",[424,3910,3911],{"class":430}," $request)",[424,3913,609],{"class":651},[424,3915,3916],{"class":438}," Response\n",[424,3918,3919],{"class":426,"line":465},[424,3920,3448],{"class":430},[424,3922,3923,3926,3928,3930,3932,3934,3936,3938],{"class":426,"line":879},[424,3924,3925],{"class":430},"    $data ",[424,3927,442],{"class":651},[424,3929,2164],{"class":430},[424,3931,2167],{"class":651},[424,3933,2170],{"class":2146},[424,3935,2173],{"class":430},[424,3937,3757],{"class":445},[424,3939,2190],{"class":430},[424,3941,3942,3945,3947,3949,3951,3953,3955,3958],{"class":426,"line":2181},[424,3943,3944],{"class":430},"    $signature ",[424,3946,442],{"class":651},[424,3948,2164],{"class":430},[424,3950,2167],{"class":651},[424,3952,2170],{"class":2146},[424,3954,2173],{"class":430},[424,3956,3957],{"class":445},"'signature'",[424,3959,2190],{"class":430},[424,3961,3962],{"class":426,"line":2187},[424,3963,2196],{"emptyLinePlaceholder":933},[424,3965,3966,3969,3971,3973,3976,3978,3980,3982,3985],{"class":426,"line":2193},[424,3967,3968],{"class":651},"    if",[424,3970,2205],{"class":430},[424,3972,2208],{"class":651},[424,3974,3975],{"class":438}," hash_equals",[424,3977,2173],{"class":430},[424,3979,3577],{"class":438},[424,3981,2167],{"class":651},[424,3983,3984],{"class":2146},"sign",[424,3986,3987],{"class":430},"($data), $signature)) {\n",[424,3989,3990,3993,3995,3998],{"class":426,"line":2199},[424,3991,3992],{"class":2146},"        abort",[424,3994,2173],{"class":430},[424,3996,3997],{"class":438},"403",[424,3999,2190],{"class":430},[424,4001,4002],{"class":426,"line":2219},[424,4003,3797],{"class":430},[424,4005,4006],{"class":426,"line":1483},[424,4007,2196],{"emptyLinePlaceholder":933},[424,4009,4010,4013,4015,4018,4020,4023,4026,4029],{"class":426,"line":935},[424,4011,4012],{"class":430},"    $payload ",[424,4014,442],{"class":651},[424,4016,4017],{"class":438}," json_decode",[424,4019,2173],{"class":430},[424,4021,4022],{"class":438},"base64_decode",[424,4024,4025],{"class":430},"($data), ",[424,4027,4028],{"class":438},"true",[424,4030,2190],{"class":430},[424,4032,4033],{"class":426,"line":1594},[424,4034,2196],{"emptyLinePlaceholder":933},[424,4036,4037,4040,4042,4045,4047,4050,4053,4056],{"class":426,"line":3589},[424,4038,4039],{"class":438},"    DB",[424,4041,2143],{"class":651},[424,4043,4044],{"class":2146},"transaction",[424,4046,2173],{"class":430},[424,4048,4049],{"class":651},"function",[424,4051,4052],{"class":430}," () ",[424,4054,4055],{"class":651},"use",[424,4057,4058],{"class":430}," ($payload) {\n",[424,4060,4061,4063,4065,4067,4069,4072,4074,4077,4080,4082],{"class":426,"line":3595},[424,4062,3563],{"class":430},[424,4064,442],{"class":651},[424,4066,2140],{"class":438},[424,4068,2143],{"class":651},[424,4070,4071],{"class":2146},"where",[424,4073,2173],{"class":430},[424,4075,4076],{"class":445},"'public_id'",[424,4078,4079],{"class":430},", $payload[",[424,4081,2239],{"class":445},[424,4083,4084],{"class":430},"])\n",[424,4086,4087,4090,4093],{"class":426,"line":3609},[424,4088,4089],{"class":651},"            ->",[424,4091,4092],{"class":2146},"lockForUpdate",[424,4094,4095],{"class":430},"()\n",[424,4097,4098,4100,4103],{"class":426,"line":3617},[424,4099,4089],{"class":651},[424,4101,4102],{"class":2146},"firstOrFail",[424,4104,4105],{"class":430},"();\n",[424,4107,4108],{"class":426,"line":3623},[424,4109,2196],{"emptyLinePlaceholder":933},[424,4111,4112],{"class":426,"line":3628},[424,4113,4114],{"class":2129},"        \u002F\u002F Terminal state reached already: ignore repeated callbacks\n",[424,4116,4117,4119,4121,4123,4126,4129,4132],{"class":426,"line":3647},[424,4118,3598],{"class":651},[424,4120,3601],{"class":430},[424,4122,2167],{"class":651},[424,4124,4125],{"class":430},"payment_status ",[424,4127,4128],{"class":651},"===",[424,4130,4131],{"class":445}," 'paid'",[424,4133,4134],{"class":430},") {\n",[424,4136,4137,4139],{"class":426,"line":1633},[424,4138,3612],{"class":651},[424,4140,3467],{"class":430},[424,4142,4143],{"class":426,"line":3669},[424,4144,3620],{"class":430},[424,4146,4147],{"class":426,"line":3705},[424,4148,2196],{"emptyLinePlaceholder":933},[424,4150,4151,4153,4156,4159,4162,4164,4167,4170,4172,4175,4178,4181,4183,4185,4187,4189,4192,4194],{"class":426,"line":3724},[424,4152,3598],{"class":651},[424,4154,4155],{"class":430}," ($payload[",[424,4157,4158],{"class":445},"'status'",[424,4160,4161],{"class":430},"] ",[424,4163,4128],{"class":651},[424,4165,4166],{"class":445}," 'success'",[424,4168,4169],{"class":651}," &&",[424,4171,2205],{"class":430},[424,4173,4174],{"class":651},"float",[424,4176,4177],{"class":430},") $payload[",[424,4179,4180],{"class":445},"'amount'",[424,4182,4161],{"class":430},[424,4184,4128],{"class":651},[424,4186,2205],{"class":430},[424,4188,4174],{"class":651},[424,4190,4191],{"class":430},") $order",[424,4193,2167],{"class":651},[424,4195,4196],{"class":430},"total) {\n",[424,4198,4199,4201,4203,4206,4209,4212],{"class":426,"line":3729},[424,4200,3672],{"class":430},[424,4202,2167],{"class":651},[424,4204,4205],{"class":2146},"markPaid",[424,4207,4208],{"class":430},"($payload[",[424,4210,4211],{"class":445},"'payment_id'",[424,4213,3721],{"class":430},[424,4215,4216],{"class":426,"line":3734},[424,4217,3620],{"class":430},[424,4219,4220],{"class":426,"line":3747},[424,4221,4222],{"class":430},"    });\n",[424,4224,4225],{"class":426,"line":3774},[424,4226,2196],{"emptyLinePlaceholder":933},[424,4228,4229,4231,4233,4235,4238],{"class":426,"line":3788},[424,4230,2222],{"class":651},[424,4232,2225],{"class":2146},[424,4234,2173],{"class":430},[424,4236,4237],{"class":445},"'OK'",[424,4239,2190],{"class":430},[424,4241,4242],{"class":426,"line":3794},[424,4243,2256],{"class":430},[137,4245,4246,4247,4250],{},"Зверніть увагу на дві речі: ",[386,4248,4249],{},"lockForUpdate()"," не дає двом одночасним колбекам обробити замовлення паралельно, а порівняння суми захищає від підміни. Про суму кажуть рідко, а марно: клієнт, який змінив параметри на стороні браузера, має отримати відмову.",[291,4252,4254],{"id":4253},"_9-не-оброблені-проміжні-та-невдалі-статуси","9. Не оброблені проміжні та невдалі статуси",[137,4256,4257,4258,4261],{},"Платіж має більше станів, ніж «успіх» і «помилка». Є очікування підтвердження, 3-D Secure, обробка, повернення, відхилення банком. Якщо код знає лише ",[386,4259,4260],{},"success",", то все інше зависає в невизначеності: клієнт заплатив, але замовлення «очікує оплати», або навпаки.",[137,4263,4264],{},"Для кожного статусу прийміть рішення і запишіть його в тест:",[152,4266,4267,4277],{},[155,4268,4269],{},[158,4270,4271,4274],{},[161,4272,4273],{},"Статус платежу",[161,4275,4276],{},"Що робимо із замовленням",[177,4278,4279,4287,4295,4303],{},[158,4280,4281,4284],{},[182,4282,4283],{},"успіх",[182,4285,4286],{},"позначаємо оплаченим, резервуємо товар, шлемо підтвердження",[158,4288,4289,4292],{},[182,4290,4291],{},"очікування \u002F обробка",[182,4293,4294],{},"залишаємо «в обробці», не скасовуємо за таймером занадто рано",[158,4296,4297,4300],{},[182,4298,4299],{},"відхилено \u002F помилка",[182,4301,4302],{},"даємо клієнту повторити оплату тим самим замовленням",[158,4304,4305,4308],{},[182,4306,4307],{},"повернення коштів",[182,4309,4310],{},"повертаємо залишки, оновлюємо статус, повідомляємо менеджера",[137,4312,4313],{},"Окремий випадок: клієнт заплатив, а колбек не дійшов. Нехай раз на кілька хвилин працює завдання, яке перевіряє «зависшим» замовленням статус у платіжній системі. Це дешевше, ніж розбиратися вручну за виписками.",[291,4315,4317],{"id":4316},"_10-розбіжність-між-замовленням-і-платежем","10. Розбіжність між замовленням і платежем",[137,4319,4320],{},"Коли клієнт змінює кошик після відкриття сторінки оплати, або менеджер редагує замовлення вже після створення платежу, сума в платіжній системі й у магазині розходиться. Результат: оплачено 1 200, замовлення на 1 450, бухгалтерія в паніці.",[137,4322,4323],{},"Рішення: після створення платежу замовлення блокується для змін суми. Якщо зміна потрібна, створюйте новий платіж, а старий анулюйте. Також додайте звірку: щодня порівнюйте оплачені замовлення з реєстром платежів провайдера.",[744,4325,4326],{},[137,4327,4328,4331,4332,4335],{},[185,4329,4330],{},"Хочете, щоб інтеграції пройшли перевірку до запуску?"," Ми проганяємо checkout із доставкою й оплатою на реальних сценаріях і повертаємо баг-репорти з відео. ",[245,4333,4334],{"href":31},"Замовити QA-аудит інтернет-магазину",", від 6 000 грн.",[144,4337,4339],{"id":4338},"як-тестувати-такі-інтеграції","Як тестувати такі інтеграції",[137,4341,4342],{},"Окремий список, який ми використовуємо як мінімум перед запуском магазину:",[299,4344,4345,4351,4357,4363,4369,4375,4381],{},[259,4346,4347,4350],{},[185,4348,4349],{},"Sandbox-режим усіх провайдерів",": тестові картки, тестові ТТН. Перевірте, що тестовий режим не залишився увімкненим на проді (це трапляється частіше, ніж хочеться).",[259,4352,4353,4356],{},[185,4354,4355],{},"Негативні сценарії",": відмова банку, закрита вкладка на 3-D Secure, недостатньо коштів, закінчений термін картки.",[259,4358,4359,4362],{},[185,4360,4361],{},"Повторні колбеки",": надішліть той самий колбек двічі вручну (curl або Postman) і переконайтеся, що нічого не задвоїлося.",[259,4364,4365,4368],{},[185,4366,4367],{},"Підроблений колбек",": змініть суму або підпис і переконайтеся, що отримали відмову.",[259,4370,4371,4374],{},[185,4372,4373],{},"Недоступний API",": вимкніть мережу для API Нової Пошти в тесті й подивіться, що бачить клієнт.",[259,4376,4377,4380],{},[185,4378,4379],{},"Різні пристрої",": оплата і вибір відділення на iOS Safari й Android Chrome. Рекламні вбудовані браузери (Instagram, Telegram) нерідко ведуть себе інакше.",[259,4382,4383,4386],{},[185,4384,4385],{},"Автотести",": підпис колбеку, ідемпотентність і розрахунок накладеного платежу легко покрити тестами на Pest\u002FPHPUnit, а повний шлях checkout автоматизувати на Playwright.",[137,4388,4389,4390,4393,4394,727],{},"Для Laravel зручно фіксувати відповіді зовнішніх API через ",[386,4391,4392],{},"Http::fake()",": тест стає швидким і не залежить від мережі, а ви перевіряєте саме вашу логіку, а не чужий сервер. Про автоматизацію ключових шляхів докладніше на сторінці ",[245,4395,4396],{"href":2671},"автоматизації тестування",[137,4398,4399,4400,4403,4404,727],{},"Про те, чому замовлення губляться ще до оплати, ми писали окремо: ",[245,4401,4402],{"href":1628},"7 типових багів checkout",". А повний перелік перевірок перед релізом зібраний у ",[245,4405,4406],{"href":2074},"чек-листі тестування інтернет-магазину",[144,4408,4410],{"id":4409},"моніторинг-після-запуску","Моніторинг після запуску",[137,4412,4413],{},"Інтеграція не закінчується релізом. Зовнішні API змінюються, ключі закінчуються, ліміти запитів вичерпуються. Мінімум, який варто налаштувати:",[256,4415,4416,4419,4422,4425],{},[259,4417,4418],{},"сповіщення в Telegram чи на пошту, коли завдання створення ТТН провалилося після всіх повторів;",[259,4420,4421],{},"щоденний звіт: кількість замовлень без ТТН і кількість оплат без підтвердженого колбеку;",[259,4423,4424],{},"логування запитів і відповідей до платіжки та Нової Пошти (без повних номерів карток і приватних ключів) із прив'язкою до номера замовлення;",[259,4426,4427],{},"нагадування про закінчення дії ключів і токенів.",[137,4429,4430],{},"Це дрібниці, але саме вони перетворюють «ми дізналися від клієнта» на «ми виправили до того, як клієнт помітив».",[144,4432,4434],{"id":4433},"підсумок-що-перевірити-сьогодні","Підсумок: що перевірити сьогодні",[137,4436,4437],{},"Якщо магазин уже працює, є п'ять швидких перевірок:",[256,4439,4440,4443,4446,4449,4452],{},[259,4441,4442],{},"Чи оновлюється довідник відділень автоматично, і коли востаннє?",[259,4444,4445],{},"Чи змінює статус оплати лише серверний колбек, і чи перевіряється підпис?",[259,4447,4448],{},"Що станеться, якщо той самий колбек прийде двічі?",[259,4450,4451],{},"Чи видно менеджеру помилку створення ТТН, чи вона лише в логах?",[259,4453,4454],{},"Чи збігається сума накладеного платежу із залишком до сплати при знижках?",[137,4456,4457,4458,4462],{},"Якщо хоча б на одне питання відповідь «не знаємо», це привід для перевірки. Саме такі місця ми розбираємо в ",[245,4459,4461],{"href":4460},"\u002Fposluhy\u002Ftekhnichnyi-audyt","технічному аудиті коду",", коли магазин уже живий і треба зрозуміти, де втрачаються гроші.",[744,4464,4465],{},[137,4466,4467,4470,4471,727],{},[185,4468,4469],{},"Магазин працює, а замовлення губляться?"," Опишіть проблему в брифі, і ми скажемо, з чого почати перевірку, безкоштовно й без зобов'язань. ",[245,4472,1279],{"href":17},[875,4474,4475],{},"html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":14,"searchDepth":465,"depth":879,"links":4477},[4478,4479,4484,4489,4495,4496,4497],{"id":3307,"depth":465,"text":3308},{"id":3324,"depth":465,"text":3325,"children":4480},[4481,4482,4483],{"id":3328,"depth":879,"text":3329},{"id":3357,"depth":879,"text":3358},{"id":3370,"depth":879,"text":3371},{"id":3388,"depth":465,"text":3389,"children":4485},[4486,4487,4488],{"id":3392,"depth":879,"text":3393},{"id":3812,"depth":879,"text":3813},{"id":3833,"depth":879,"text":3834},{"id":3861,"depth":465,"text":3862,"children":4490},[4491,4492,4493,4494],{"id":3865,"depth":879,"text":3866},{"id":3883,"depth":879,"text":3884},{"id":4253,"depth":879,"text":4254},{"id":4316,"depth":879,"text":4317},{"id":4338,"depth":465,"text":4339},{"id":4409,"depth":465,"text":4410},{"id":4433,"depth":465,"text":4434},"integrations.log",[4500,4502,4504,4506],{"marker":905,"text":4501},"callback підпис перевірено",{"marker":910,"text":4503},"відділення закрито, адреса в замовленні",{"marker":2008,"text":4505},"дубль замовлення після повторного колбеку",{"marker":913,"text":4507},"таймаут API 8 с, черга повторів","10 точок",[4510,4513,4516,4519],{"q":4511,"a":4512},"Чому на сайті не завантажуються відділення Нової Пошти?","Найчастіше довідник відділень не оновлюється або запит до API Нової Пошти падає без обробки помилки. Зберігайте локальну копію довідника й оновлюйте її за розкладом, а при збої API показуйте запасний варіант вибору. Також перевірте, чи чинний ключ API.",{"q":4514,"a":4515},"Чому оплата пройшла, а замовлення залишилось неоплаченим?","Платіжна система повідомляє про результат окремим запитом-колбеком, і якщо його не прийнято або не підтверджено підпис, статус не оновиться. Колбек має бути ідемпотентним: повторний виклик не повинен створювати дубль. Регулярно звіряйте замовлення з виписками платіжної системи.",{"q":4517,"a":4518},"Як уникнути дублів накладних ТТН у Новій Пошті?","Перед створенням накладної перевіряйте, чи вона вже існує для цього замовлення, і блокуйте повторні запити на сервері. Зберігайте номер ТТН і статус одразу після відповіді API. Так повторний клік чи повторне виконання завдання в черзі не створить другу накладну.",{"q":4520,"a":4521},"Як протестувати інтеграцію з оплатою без реальних грошей?","Використовуйте тестовий режим платіжної системи: більшість провайдерів дають тестові картки та sandbox для успішних і відхилених платежів. Окремо перевірте збій, затримку й повторний колбек. Перед запуском зробіть один реальний платіж на мінімальну суму. Так ви побачите, як сайт поводиться в реальних умовах.",{},"\u002Fuk\u002Fblog\u002Fintehratsiia-novoi-poshty-ta-oplaty",{"title":1700,"description":3301},"Інтеграція Нової Пошти та онлайн-оплати в інтернет-магазині на Laravel: 10 місць, де ламається, з прикладами коду, тестами й чек-листом перед запуском.","Інтеграція Нової Пошти та оплати: де ламається — Tochno.","intehratsiia-novoi-poshty-ta-oplaty","uk\u002Fblog\u002Fintehratsiia-novoi-poshty-ta-oplaty",[942,4530],"laravel","wIIbZocfGsE8DpqQQRHuAsmihf_id0R43Ii_vS_1Dv8",{"id":4533,"title":4534,"author":132,"body":4535,"cover":901,"coverFile":5065,"coverLines":5066,"coverStat":5075,"date":916,"description":4539,"excerpt":901,"extension":917,"faq":5076,"featured":931,"key":901,"meta":5089,"navigation":933,"path":5090,"readingTime":1483,"seo":5091,"seoDescription":5092,"seoTitle":5093,"slug":5094,"stem":5095,"tags":5096,"updated":1467,"__hash__":5097},"blog_uk\u002Fuk\u002Fblog\u002Fkoly-potriben-tekh-lid.md","Коли потрібен тех-лід, а коли достатньо розробника",{"type":134,"value":4536,"toc":5047},[4537,4540,4543,4547,4550,4621,4624,4627,4631,4634,4677,4681,4684,4734,4737,4741,4744,4761,4764,4768,4771,4775,4778,4782,4792,4796,4802,4806,4809,4813,4816,4820,4823,4884,4899,4902,4914,4918,4921,4941,4944,4948,4951,4989,4992,4996,5028,5030,5033,5036],[137,4538,4539],{},"Тех-лід потрібен, коли проблема проєкту вже не в окремих задачах, а в рішеннях: яка архітектура, хто відповідає за якість коду, як оцінювати й планувати, що робити з технічним боргом. Якщо ж задача зрозуміла, стек відомий, а команда працює без конфліктів, вистачить хорошого розробника. Нижче розбираємо різницю на практиці й даємо перелік ознак, за якими можна зрозуміти, що вам потрібен тех-лід, а не ще одна пара рук.",[137,4541,4542],{},"Це текст людини, яка 11 років пише на PHP та Laravel і знає обидві ролі зсередини, тому багато прикладів нижче типові для проєктів на Laravel, але логіка застосовна до будь-якого стеку.",[144,4544,4546],{"id":4545},"хто-такий-тех-лід-і-чим-він-відрізняється-від-розробника","Хто такий тех-лід і чим він відрізняється від розробника",[137,4548,4549],{},"Розробник вирішує задачу: зробити функцію, виправити баг, інтегрувати API. Тех-лід відповідає за те, щоб набір таких задач складався в працюючий, підтримуваний продукт.",[152,4551,4552,4564],{},[155,4553,4554],{},[158,4555,4556,4558,4561],{},[161,4557],{},[161,4559,4560],{},"Розробник",[161,4562,4563],{},"Тех-лід",[177,4565,4566,4577,4588,4599,4610],{},[158,4567,4568,4571,4574],{},[182,4569,4570],{},"Фокус",[182,4572,4573],{},"задача чи фіча",[182,4575,4576],{},"система й команда",[158,4578,4579,4582,4585],{},[182,4580,4581],{},"Питання",[182,4583,4584],{},"«як це зробити?»",[182,4586,4587],{},"«чи треба це робити і як воно впишеться?»",[158,4589,4590,4593,4596],{},[182,4591,4592],{},"Результат",[182,4594,4595],{},"працюючий код",[182,4597,4598],{},"архітектурні рішення, стандарти, прогнозованість",[158,4600,4601,4604,4607],{},[182,4602,4603],{},"Відповідальність",[182,4605,4606],{},"якість свого коду",[182,4608,4609],{},"якість підсумкового продукту й узгодженість команди",[158,4611,4612,4615,4618],{},[182,4613,4614],{},"Комунікація",[182,4616,4617],{},"з тімлідом і колегами",[182,4619,4620],{},"з замовником, продактом, бізнесом, підрядниками",[137,4622,4623],{},"Не плутайте з senior-розробником. Senior пише складний код швидко й надійно. Тех-лід теж пише код, але витрачає значну частину часу на рев'ю, рішення, оцінку ризиків і пояснення замовнику, що можна зробити за ці гроші й терміни. Сильний senior не обов'язково хоче чи вміє бути тех-лідом, і це нормально.",[137,4625,4626],{},"Також тех-лід не те саме, що тімлід чи проєкт-менеджер. Тімлід відповідає за людей і процеси, PM за терміни й бюджет, тех-лід за технічні рішення. У малих командах ці ролі часто поєднуються в одній людині, але відповідальності різні.",[144,4628,4630],{"id":4629},"що-саме-робить-тех-лід","Що саме робить тех-лід",[137,4632,4633],{},"Конкретні задачі, а не загальні слова:",[256,4635,4636,4641,4647,4653,4659,4665,4671],{},[259,4637,4638,4640],{},[185,4639,738],{}," Вибір структури застосунку, меж модулів, способу зберігання даних, кешування, черг. Фіксація рішень у коротких документах (ADR): що вирішили, чому, які були альтернативи.",[259,4642,4643,4646],{},[185,4644,4645],{},"Код-рев'ю."," Перевірка змін перед злиттям: коректність, безпека, продуктивність, відповідність домовленостям. Рев'ю також навчає команду.",[259,4648,4649,4652],{},[185,4650,4651],{},"Стандарти й автоматизація."," Лінтери, статичний аналіз (наприклад, PHPStan або Larastan), правила гілок, CI з тестами. Це робиться раз і далі працює без нагадувань.",[259,4654,4655,4658],{},[185,4656,4657],{},"Оцінка й планування."," Розбиття функціоналу на задачі, виявлення ризиків і залежностей, чесна оцінка термінів із вказанням невизначеності.",[259,4660,4661,4664],{},[185,4662,4663],{},"Технічний борг."," Рішення, що виправляти зараз, а що лишити, з розрахунком вартості відкладення.",[259,4666,4667,4670],{},[185,4668,4669],{},"Вибір і перевірка підрядників та технологій."," Оцінка чужих пропозицій, чужого коду, виявлення завищених кошторисів і ненадійних рішень.",[259,4672,4673,4676],{},[185,4674,4675],{},"Міст до бізнесу."," Переклад із мови вимог на мову технічних компромісів і навпаки.",[144,4678,4680],{"id":4679},"ознаки-що-вам-потрібен-тех-лід","Ознаки, що вам потрібен тех-лід",[137,4682,4683],{},"Перелік не академічний, ми бачимо ці симптоми у реальних проєктах. Якщо збігається три і більше, варто задуматися.",[299,4685,4686,4692,4698,4704,4710,4716,4722,4728],{},[259,4687,4688,4691],{},[185,4689,4690],{},"Кожен реліз ламає щось сусіднє."," Це сигнал, що немає тестів і меж між модулями, і ніхто не відповідає за цілісність.",[259,4693,4694,4697],{},[185,4695,4696],{},"Оцінки постійно зриваються."," Задачі «на два дні» тривають тиждень. Причина часто не в лінощах, а в прихованій складності, яку ніхто не розібрав заздалегідь.",[259,4699,4700,4703],{},[185,4701,4702],{},"Нова людина входить у проєкт місяцями."," Немає документації, стандартів, зрозумілої структури, а все знає одна людина.",[259,4705,4706,4709],{},[185,4707,4708],{},"Залежність від одного розробника."," Якщо він піде або захворіє, проєкт зупиниться. Це бізнес-ризик, а не лише технічний.",[259,4711,4712,4715],{},[185,4713,4714],{},"Повільний сайт або падіння під навантаженням, а причини не знайдені."," Хтось гасить пожежі, ніхто не розбирається з системними причинами.",[259,4717,4718,4721],{},[185,4719,4720],{},"Незрозуміло, скільки це має коштувати."," Підрядник називає суму, а ви не можете оцінити її адекватність.",[259,4723,4724,4727],{},[185,4725,4726],{},"Рішення ухвалюються «як вийде»."," Різні частини системи написані в різних стилях, є три способи зробити те саме.",[259,4729,4730,4733],{},[185,4731,4732],{},"Стратегічні питання без відповіді."," Переписувати чи латати, переходити на інший стек, робити мікросервіси чи лишити моноліт.",[137,4735,4736],{},"Перші сім пунктів, до речі, зазвичай не лікуються найманням ще одного розробника. Додаткова людина у нескерований процес додає хаосу.",[144,4738,4740],{"id":4739},"коли-достатньо-розробника","Коли достатньо розробника",[137,4742,4743],{},"Тех-лід не завжди потрібен, і не варто ним переплачувати. Розробника достатньо, якщо:",[256,4745,4746,4749,4752,4755,4758],{},[259,4747,4748],{},"проєкт невеликий (лендінг, корпоративний сайт, типовий інтернет-магазин на готовій основі) і стек стандартний;",[259,4750,4751],{},"задачі чітко сформульовані й оцінюються без великої невизначеності;",[259,4753,4754],{},"над проєктом працює одна-дві людини, яким довіряють;",[259,4756,4757],{},"вимоги стабільні, а архітектурних рішень майже немає;",[259,4759,4760],{},"вже є працюючі процеси: тести, рев'ю, CI, і ви бачите, що вони працюють.",[137,4762,4763],{},"Приклад: ви хочете додати на існуючий магазин новий спосіб доставки або блок рекомендацій. Задача локальна, її вирішує розробник за кілька днів. Тех-лід тут вартий хіба що на коротку консультацію.",[144,4765,4767],{"id":4766},"типові-сценарії-коли-тех-лід-рятує-проєкт","Типові сценарії, коли тех-лід рятує проєкт",[137,4769,4770],{},"Нижче узагальнені ситуації, з якими ми стикаємося. Це не конкретні клієнти, а патерни.",[291,4772,4774],{"id":4773},"сценарій-1-старт-нового-проєкту","Сценарій 1. Старт нового проєкту",[137,4776,4777],{},"На етапі старту найдорожчі помилки: вибір стеку, структура даних, межі між модулями. Виправляти їх через рік коштує у рази більше. Тут достатньо тех-ліда на 5–10 годин у тиждень: він складає технічний план, ухвалює ключові рішення і налаштовує процеси, а реалізують розробники.",[291,4779,4781],{"id":4780},"сценарій-2-успадкований-код","Сценарій 2. «Успадкований» код",[137,4783,4784,4785,4788,4789,727],{},"Проєкт залишився від попереднього підрядника. Код працює, але ніхто не знає, наскільки він надійний. Перш ніж вкладати гроші в розвиток, варто зробити ",[245,4786,4787],{"href":4460},"технічний аудит коду",": отримати оцінку архітектури, безпеки й продуктивності та план виправлень за пріоритетами. Про це докладніше в статті ",[245,4790,4791],{"href":494},"що таке технічний аудит і коли він потрібен",[291,4793,4795],{"id":4794},"сценарій-3-вибір-і-контроль-підрядника","Сценарій 3. Вибір і контроль підрядника",[137,4797,4798,4799,727],{},"Ви наймаєте студію чи фрилансера, але не можете перевірити їхні оцінки й код. Тех-лід з вашого боку складає вимоги, оцінює пропозиції, рев'юїть результат на етапах. Це страхує від переплат і від проєкту, який «ніби готовий», але не підтримується. Питання, які варто поставити підряднику, ми зібрали окремо: ",[245,4800,4801],{"href":781},"12 питань перед вибором підрядника",[291,4803,4805],{"id":4804},"сценарій-4-команда-є-а-результат-непередбачуваний","Сценарій 4. Команда є, а результат непередбачуваний",[137,4807,4808],{},"Розробники хороші, але терміни зриваються, а якість нерівна. Часто тут не потрібно міняти людей, потрібні стандарти, рев'ю та тест-стратегія. Тех-лід вводить ці практики за кілька тижнів і далі лише підтримує.",[291,4810,4812],{"id":4811},"сценарій-5-масштабування-і-повільна-робота","Сценарій 5. Масштабування і повільна робота",[137,4814,4815],{},"Сайт повільнішає, база росте, виникають блокування й повільні запити. Типова причина в Laravel-проєктах: N+1 запити, відсутні індекси, важкі синхронні операції, які варто виносити в черги. Тех-лід швидко знаходить вузькі місця за профілюванням і ставить задачі в порядку впливу.",[144,4817,4819],{"id":4818},"формати-співпраці-з-тех-лідом","Формати співпраці з тех-лідом",[137,4821,4822],{},"Тех-лід не обов'язково штатна одиниця на повний день. Для малого й середнього бізнесу найчастіше працює фракційний формат.",[152,4824,4825,4838],{},[155,4826,4827],{},[158,4828,4829,4832,4835],{},[161,4830,4831],{},"Формат",[161,4833,4834],{},"Для чого",[161,4836,4837],{},"Орієнтир за ціною",[177,4839,4840,4851,4862,4873],{},[158,4841,4842,4845,4848],{},[182,4843,4844],{},"Разова консультація (90 хв)",[182,4846,4847],{},"оцінити архітектуру, стек, пропозицію підрядника",[182,4849,4850],{},"3 000–4 000 грн",[158,4852,4853,4856,4859],{},[182,4854,4855],{},"Технічний аудит",[182,4857,4858],{},"зрозуміти стан проєкту й отримати план виправлень",[182,4860,4861],{},"від 12 000 грн",[158,4863,4864,4867,4870],{},[182,4865,4866],{},"Тех-лід на проєкт",[182,4868,4869],{},"план, рішення, рев'ю на період розробки",[182,4871,4872],{},"за погодинною ставкою, $32–35 \u002F год",[158,4874,4875,4878,4881],{},[182,4876,4877],{},"Виділений спеціаліст у вашій команді",[182,4879,4880],{},"постійна участь частину або весь день",[182,4882,4883],{},"від $1 800 \u002F міс",[137,4885,4886,4887,4890,4891,4895,4896,727],{},"Це наші орієнтири з цінової сторінки, точну вартість залежно від обсягу ми називаємо після брифу. Деталі формату ",[245,4888,4889],{"href":34},"тех-ліда на аутсорсі"," і умови ",[245,4892,4894],{"href":4893},"\u002Fposluhy\u002Fvydilenyi-spetsialist","виділеного спеціаліста"," описані на окремих сторінках, а загальні ставки зібрані на сторінці ",[245,4897,4898],{"href":77},"цін",[137,4900,4901],{},"Фракційний тех-лід ефективний тому, що більшість рішень не потребують присутності щодня: достатньо спланувати, зробити рев'ю, розв'язати складне питання й пояснити команді. Решту часу команда працює за узгодженими правилами.",[744,4903,4904],{},[137,4905,4906,4909,4910,4913],{},[185,4907,4908],{},"Не впевнені, що вам потрібно?"," Почніть із консультації тех-ліда на 90 хвилин: розберемо проєкт, ризики й скажемо, чи потрібен вам тех-лід постійно, чи вистачить розробника. ",[245,4911,4912],{"href":34},"Тех-лід на аутсорсі",", від 3 000 грн.",[144,4915,4917],{"id":4916},"скільки-часу-тех-ліду-потрібно-на-проєкт","Скільки часу тех-ліду потрібно на проєкт",[137,4919,4920],{},"Запитання, яке ставлять найчастіше: скільки годин на тиждень потрібно? Єдиної відповіді немає, але орієнтири з практики такі (оціночні, залежать від проєкту):",[256,4922,4923,4929,4935],{},[259,4924,4925,4928],{},[185,4926,4927],{},"Старт проєкту, перші 2–4 тижні:"," 8–15 годин на тиждень. Це найінтенсивніший період: архітектура, налаштування CI, перші рев'ю, розбиття на задачі.",[259,4930,4931,4934],{},[185,4932,4933],{},"Стабільна розробка командою з 2–3 людей:"," 4–8 годин на тиждень. Рев'ю, відповіді на технічні питання, планування наступних ітерацій.",[259,4936,4937,4940],{},[185,4938,4939],{},"Підтримка вже запущеного продукту:"," 2–4 години на тиждень або за запитом: складні інциденти, оцінка нових фіч, контроль технічного боргу.",[137,4942,4943],{},"Якщо хтось пропонує «тех-ліда на 40 годин» для проєкту з однією людиною в команді, це швидше за все розробник із гучнішою назвою. Перевіряйте, що саме входить у роботу: рішення й рев'ю чи лише написання коду.",[144,4945,4947],{"id":4946},"як-зрозуміти-що-тех-лід-працює-добре","Як зрозуміти, що тех-лід працює добре",[137,4949,4950],{},"Якщо ви найняли тех-ліда, ось ознаки результату, які можна перевірити без глибоких технічних знань:",[256,4952,4953,4959,4965,4971,4977,4983],{},[259,4954,4955,4958],{},[185,4956,4957],{},"з'явилися письмові рішення."," Хоча б короткі записи: що вибрали й чому;",[259,4960,4961,4964],{},[185,4962,4963],{},"реліз став рутиною."," Деплой не вимагає героїзму й не ламає сусідніх функцій;",[259,4966,4967,4970],{},[185,4968,4969],{},"оцінки стали точнішими."," Відхилення зменшуються, а ризики озвучуються заздалегідь;",[259,4972,4973,4976],{},[185,4974,4975],{},"код-рев'ю проходять усі зміни."," І це не формальність: у коментарях видно змістовні зауваження;",[259,4978,4979,4982],{},[185,4980,4981],{},"нова людина входить у проєкт за дні, а не за місяці."," Є README, інструкція запуску, угоди щодо стилю;",[259,4984,4985,4988],{},[185,4986,4987],{},"ви розумієте, що відбувається."," Тех-лід пояснює технічні речі мовою бізнесу: що, навіщо, скільки.",[137,4990,4991],{},"Якщо ж після кількох місяців нічого з цього не змінилося, а тех-лід лише «багато пише коду», то вам, ймовірно, потрібен просто senior-розробник, і це нормально, тільки платити за іншу роль не варто.",[144,4993,4995],{"id":4994},"помилки-при-наймі-тех-ліда","Помилки при наймі тех-ліда",[256,4997,4998,5004,5010,5016,5022],{},[259,4999,5000,5003],{},[185,5001,5002],{},"Шукати «героя», який усе зробить сам."," Тех-лід налаштовує систему, а не замінює її.",[259,5005,5006,5009],{},[185,5007,5008],{},"Не давати повноважень."," Якщо тех-лід може лише радити, а рішення ухвалюються поза ним, користь мінімальна.",[259,5011,5012,5015],{},[185,5013,5014],{},"Плутати з архітектором-теоретиком."," Хороший тех-лід регулярно пише код або хоча б читає його, інакше рішення відриваються від реальності.",[259,5017,5018,5021],{},[185,5019,5020],{},"Наймати на повний день, коли вистачить частини."," Для проєкту на 2–3 розробників зазвичай достатньо кількох годин на тиждень.",[259,5023,5024,5027],{},[185,5025,5026],{},"Не перевірити досвід на реальних проєктах."," Попросіть розповісти про конкретні рішення, їхні наслідки й помилки. Чесна розповідь про провали каже більше, ніж список технологій.",[144,5029,858],{"id":857},[137,5031,5032],{},"Коротко: розробник потрібен, щоб зробити задачу, тех-лід потрібен, щоб правильно вибирати задачі та рішення і щоб система не розсипалась зі зростанням. Якщо у вашому проєкті збігаються кілька ознак із переліку вище (зриви термінів, залежність від однієї людини, ламкі релізи, незрозуміла якість коду), почніть із невеликого кроку: консультації або аудиту. Це недорого й швидко покаже, чи потрібен вам тех-лід на постійній основі.",[137,5034,5035],{},"Якщо ж проєкт простий, а розробник працює без пожеж, переплачувати за тех-ліда не потрібно. Ми скажемо про це чесно, бо краще втратити замовлення, ніж продати зайве.",[744,5037,5038],{},[137,5039,5040,5043,5044,727],{},[185,5041,5042],{},"Хочете розібратися, яка роль потрібна вашому проєкту?"," Розкажіть про задачу, і ми підкажемо, достатньо розробника чи потрібен тех-лід, без зобов'язань. ",[245,5045,5046],{"href":83},"Написати нам",{"title":14,"searchDepth":465,"depth":879,"links":5048},[5049,5050,5051,5052,5053,5060,5061,5062,5063,5064],{"id":4545,"depth":465,"text":4546},{"id":4629,"depth":465,"text":4630},{"id":4679,"depth":465,"text":4680},{"id":4739,"depth":465,"text":4740},{"id":4766,"depth":465,"text":4767,"children":5054},[5055,5056,5057,5058,5059],{"id":4773,"depth":879,"text":4774},{"id":4780,"depth":879,"text":4781},{"id":4794,"depth":879,"text":4795},{"id":4804,"depth":879,"text":4805},{"id":4811,"depth":879,"text":4812},{"id":4818,"depth":465,"text":4819},{"id":4916,"depth":465,"text":4917},{"id":4946,"depth":465,"text":4947},{"id":4994,"depth":465,"text":4995},{"id":857,"depth":465,"text":858},"tech-lead.decision",[5067,5069,5071,5073],{"marker":910,"text":5068},"кожен реліз ламає сусідній модуль",{"marker":910,"text":5070},"оцінки зриваються, ніхто не знає чому",{"marker":913,"text":5072},"рішення: фракційний тех-лід",{"marker":905,"text":5074},"ADR, код-рев'ю, технічний план","5 ознак",[5077,5080,5083,5086],{"q":5078,"a":5079},"Чим тех-лід відрізняється від senior-розробника?","Розробник відповідає за якість свого коду, а тех-лід за технічні рішення проєкту загалом: архітектуру, стандарти, оцінки й ризики. Senior-розробник може виконувати цю роль, лише якщо має на це час і повноваження. Це різні відповідальності, а не просто рівні досвіду.",{"q":5081,"a":5082},"Скільки коштує консультація тех-ліда?","Наша консультація тех-ліда на 90 хвилин коштує 3 000–4 000 грн. За цей час ми розбираємо архітектуру чи план робіт і даємо конкретні рекомендації. Довший супровід проєкту обговорюємо окремо, бо обсяг залежить від команди та задач.",{"q":5084,"a":5085},"Чи потрібен тех-лід невеликому проєкту?","Зазвичай ні, якщо проєкт простий, задачі зрозумілі, а розробник досвідчений. Тех-лід потрібен, коли релізи ламають суміжні модулі, оцінки зриваються або в команді кілька розробників без спільних стандартів. Тоді навіть кілька годин на місяць можуть уберегти від дорогих помилок.",{"q":5087,"a":5088},"Чи може тех-лід працювати неповний робочий день?","Так, для невеликих компаній зручний фракційний формат: тех-лід займається проєктом кілька годин на тиждень чи місяць. Він ухвалює архітектурні рішення, проводить код-рев'ю та готує технічний план. Повна зайнятість виправдана здебільшого для великої команди. Це дешевше, ніж штатна посада, і дає потрібний контроль над якістю.",{},"\u002Fuk\u002Fblog\u002Fkoly-potriben-tekh-lid",{"title":4534,"description":4539},"Найняти тех-ліда чи достатньо розробника? Ознаки, що проєкту потрібен техлід, чим він відрізняється від senior, формати співпраці та орієнтири за ціною.","Коли потрібен тех-лід замість розробника — Tochno.","koly-potriben-tekh-lid","uk\u002Fblog\u002Fkoly-potriben-tekh-lid",[4530],"nUR38Gki3hZSj1iLbVRAdpX1vQdNk_cx397AJaksXjA",{"id":5099,"title":5100,"author":132,"body":5101,"cover":901,"coverFile":5620,"coverLines":5621,"coverStat":5630,"date":916,"description":5105,"excerpt":901,"extension":917,"faq":5631,"featured":931,"key":901,"meta":5644,"navigation":933,"path":5645,"readingTime":1483,"seo":5646,"seoDescription":5647,"seoTitle":5648,"slug":5649,"stem":5650,"tags":5651,"updated":1467,"__hash__":5652},"blog_uk\u002Fuk\u002Fblog\u002Flaravel-chy-opencart-wordpress-dlia-mahazynu.md","Laravel чи OpenCart\u002FWordPress для магазину: чесне порівняння",{"type":134,"value":5102,"toc":5603},[5103,5106,5109,5113,5116,5135,5138,5142,5252,5255,5259,5262,5268,5274,5280,5286,5289,5293,5296,5299,5302,5316,5319,5323,5328,5331,5334,5337,5341,5344,5361,5364,5368,5371,5411,5415,5418,5451,5460,5464,5467,5499,5502,5528,5532,5535,5541,5571,5574,5576,5579,5582,5588],[137,5104,5105],{},"Інтернет-магазин на Laravel краще за OpenCart чи WordPress лише тоді, коли у вас нестандартна бізнес-логіка, складні інтеграції або плани на швидке зростання. Для невеликого каталогу зі стандартним кошиком готова CMS дешевша і швидша в запуску, і говорити інакше було б нечесно. Нижче порівнюємо платформи за критеріями, які впливають на гроші власника: вартість володіння, швидкість, безпека, гнучкість і ризики.",[137,5107,5108],{},"Ми працюємо з Laravel і Nuxt, тому в нас є очевидна упередженість. Щоб її компенсувати, ми прямо вказуємо, де наш вибір програє. Автор статті, Євгеній, 11 років пише на PHP\u002FLaravel і мав справу з міграціями магазинів з обох таборів: і на Laravel, і з нього.",[144,5110,5112],{"id":5111},"про-що-саме-порівнюємо","Про що саме порівнюємо",[137,5114,5115],{},"Спершу уточнимо терміни, бо їх часто плутають.",[256,5117,5118,5123,5129],{},[259,5119,5120,5122],{},[185,5121,1060],{}," це готова PHP-платформа саме для інтернет-магазинів: каталог, кошик, замовлення, модулі оплати й доставки з коробки.",[259,5124,5125,5128],{},[185,5126,5127],{},"WordPress + WooCommerce"," це система керування контентом з плагіном магазину. Сильна в контенті й блогу, а торгівля працює через плагін.",[259,5130,5131,5134],{},[185,5132,5133],{},"Laravel"," це не CMS, а PHP-фреймворк. Магазин на ньому пишеться як програма під ваші процеси: ви отримуєте каркас (маршрути, база, черги, авторизація, тести), а все інше будуєте самі або підключаєте перевірені пакети.",[137,5136,5137],{},"Тобто порівнюємо готовий продукт з конструктором-каркасом. Це різні філософії: «налаштуй готове» проти «збудуй потрібне».",[144,5139,5141],{"id":5140},"швидкий-огляд-у-таблиці","Швидкий огляд у таблиці",[152,5143,5144,5158],{},[155,5145,5146],{},[158,5147,5148,5150,5152,5155],{},[161,5149,1051],{},[161,5151,1060],{},[161,5153,5154],{},"WooCommerce",[161,5156,5157],{},"Laravel (кастом)",[177,5159,5160,5173,5186,5199,5213,5226,5239],{},[158,5161,5162,5164,5167,5170],{},[182,5163,1070],{},[182,5165,5166],{},"Швидко",[182,5168,5169],{},"Дуже швидко",[182,5171,5172],{},"Повільніше",[158,5174,5175,5178,5181,5183],{},[182,5176,5177],{},"Початковий бюджет",[182,5179,5180],{},"Низький",[182,5182,5180],{},[182,5184,5185],{},"Вищий",[158,5187,5188,5191,5193,5196],{},[182,5189,5190],{},"Гнучкість логіки",[182,5192,1160],{},[182,5194,5195],{},"Через плагіни",[182,5197,5198],{},"Необмежена",[158,5200,5201,5204,5207,5210],{},[182,5202,5203],{},"Швидкодія за замовчуванням",[182,5205,5206],{},"Середня",[182,5208,5209],{},"Залежить від плагінів",[182,5211,5212],{},"Контролюєте самі",[158,5214,5215,5218,5221,5223],{},[182,5216,5217],{},"Безпека",[182,5219,5220],{},"Залежить від модулів",[182,5222,5209],{},[182,5224,5225],{},"Ваша відповідальність, але менше поверхні атаки",[158,5227,5228,5231,5234,5236],{},[182,5229,5230],{},"Тести й CI",[182,5232,5233],{},"Рідко",[182,5235,5233],{},[182,5237,5238],{},"Звичайна практика",[158,5240,5241,5244,5247,5249],{},[182,5242,5243],{},"Вартість змін через 2 роки",[182,5245,5246],{},"Зростає",[182,5248,5246],{},[182,5250,5251],{},"Стабільніша",[137,5253,5254],{},"Таблиця спрощена: хороший розробник зробить пристойний магазин на будь-якій платформі, а поганий зіпсує будь-яку. Але тенденції вона передає.",[144,5256,5258],{"id":5257},"де-готова-cms-виграє","Де готова CMS виграє",[137,5260,5261],{},"Почнемо з честного: у багатьох випадках OpenCart чи WooCommerce це правильний вибір.",[137,5263,5264,5267],{},[185,5265,5266],{},"Швидкий старт і низький поріг."," Готова тема, модулі оплати, налаштований каталог: перший магазин можна запустити за кілька тижнів і за невеликі гроші. Для перевірки гіпотези «чи купуватимуть цей товар» це ідеально.",[137,5269,5270,5273],{},[185,5271,5272],{},"Екосистема й спільнота."," Багато стандартних задач (знижки, купони, інтеграція з Новою Поштою, експорт у Google Merchant) вже вирішені. Є документація й тисячі розробників на ринку, тому знайти виконавця легко.",[137,5275,5276,5279],{},[185,5277,5278],{},"Контент."," WordPress традиційно сильний в управлінні контентом: блог, статті, лендінги, редактор. Якщо магазин це лише частина контентного сайту, WooCommerce логічний вибір.",[137,5281,5282,5285],{},[185,5283,5284],{},"Невеликий каталог зі стандартними процесами."," Якщо у вас 100–300 товарів, одна доставка, одна платіжка й стандартний кошик, кастом навряд чи окупиться.",[137,5287,5288],{},"Тому наше перше правило: якщо задача влізає в стандарт, не ускладнюйте. Ми справді іноді радимо клієнтам готове рішення.",[144,5290,5292],{"id":5291},"де-готова-cms-починає-коштувати-дорожче","Де готова CMS починає коштувати дорожче",[137,5294,5295],{},"Проблеми готових платформ рідко видно на старті. Вони з'являються через рік-два.",[291,5297,1177],{"id":5298},"модулі-від-різних-авторів",[137,5300,5301],{},"Магазин на OpenCart чи WooCommerce збирається з десятка модулів: оплата, доставка, фільтри, SEO, програма лояльності. Кожен має свого автора, свій темп оновлень і свою якість коду. Типові наслідки:",[256,5303,5304,5307,5310,5313],{},[259,5305,5306],{},"Оновлення ядра ламає модуль, а автор модуля вже не відповідає.",[259,5308,5309],{},"Два модулі конфліктують, бо обидва змінюють одну й ту саму частину системи.",[259,5311,5312],{},"Модуль працює, але робить зайві запити до бази, і сторінка каталогу гальмує.",[259,5314,5315],{},"Для поправки потрібно лізти в чужий код, і наступне оновлення цю правку затирає.",[137,5317,5318],{},"Для сайту, який робить 10 замовлень на день, це дрібниці. Для магазину, де кожна хвилина простою це гроші, це реальний ризик.",[291,5320,5322],{"id":5321},"швидкодія","Швидкодія",[137,5324,5325,5326,727],{},"Швидкість магазину залежить від того, скільки запитів до бази і скільки скриптів виконується на сторінці. У готових платформах за замовчуванням багато зайвого: десятки плагінів підключають свої стилі й скрипти на всіх сторінках. Налаштувати це можна, але потрібен досвід, і результат крихкий. Додатково на швидкість впливають метрики, які бачить пошуковик, про них ми писали в статті ",[245,5327,1249],{"href":1248},[137,5329,5330],{},"У кастомному рішенні ви контролюєте кожен запит: eager loading проти N+1, кеш, черги для важких операцій, окремий frontend на Nuxt з серверним рендерингом. Це не робить сайт швидким автоматично, але дає інструменти.",[291,5332,5217],{"id":5333},"безпека",[137,5335,5336],{},"Найпопулярніша платформа це й найчастіша мішень. Більшість зламів WordPress-сайтів відбувається через застарілі плагіни та слабкі паролі, а не через ядро. Кожен додатковий плагін розширює поверхню атаки. Це не означає, що Laravel «безпечний сам по собі»: помилки в коді трапляються скрізь. Різниця в тому, що в кастомному проєкті чужого коду менше, а ваш код проходить код-рев'ю.",[291,5338,5340],{"id":5339},"складна-бізнес-логіка","Складна бізнес-логіка",[137,5342,5343],{},"Ось чим кастом виправдовується. Приклади логіки, яку важко втиснути в готову платформу без костилів:",[256,5345,5346,5349,5352,5355,5358],{},[259,5347,5348],{},"ціни залежать від групи клієнта, обсягу замовлення й контракту (B2B);",[259,5350,5351],{},"склад розподілений по кількох точках із різними правилами резервування;",[259,5353,5354],{},"замовлення проходить через погодження чи складається з кількох відправлень;",[259,5356,5357],{},"двостороння синхронізація з обліковою системою (1С чи іншою) в реальному часі;",[259,5359,5360],{},"комплекти, набори й залежності товарів із нестандартною формулою ціни.",[137,5362,5363],{},"На готовій CMS це реалізується серією модулів і правок. Кожна правка ускладнює оновлення, а разом вони перетворюються на «форк», який вже не оновлюється. На Laravel ця логіка просто частина вашого коду з тестами.",[144,5365,5367],{"id":5366},"де-кастом-на-laravel-виграє","Де кастом на Laravel виграє",[137,5369,5370],{},"Підсумуємо переваги кастомної розробки.",[299,5372,5373,5379,5385,5393,5399,5405],{},[259,5374,5375,5378],{},[185,5376,5377],{},"Код належить вам."," Немає залежності від чужих модулів і ліцензій. Договір фіксує права на код, і ви можете змінити підрядника.",[259,5380,5381,5384],{},[185,5382,5383],{},"Архітектура під вас."," Модель даних описує ваш бізнес, а не абстрактний магазин.",[259,5386,5387,5390,5391,727],{},[185,5388,5389],{},"Автотести."," На Laravel звичайна практика покривати тестами замовлення, ціни, знижки, оплату. Це дозволяє змінювати код без страху щось зламати. Про те, що саме варто автоматизувати, читайте в статті ",[245,5392,1932],{"href":1931},[259,5394,5395,5398],{},[185,5396,5397],{},"Передбачувана швидкість."," Профілювання, кеш, черги, окремий frontend: усе під контролем.",[259,5400,5401,5404],{},[185,5402,5403],{},"Інтеграції без милиць."," API, вебхуки, черги повторів, ідемпотентність: усе, що потрібно для надійної роботи з платіжками й службами доставки.",[259,5406,5407,5410],{},[185,5408,5409],{},"Нижча вартість змін у довгій перспективі."," Перший рік дорожчий, зате додавання нової функції через рік не вимагає боротьби з модулями.",[291,5412,5414],{"id":5413},"нюанси-про-які-мовчать","Нюанси, про які мовчать",[137,5416,5417],{},"Кастом не безкоштовний і не безхмарний. Є мінуси, і про них важливо знати.",[256,5419,5420,5430,5439,5445],{},[259,5421,5422,5425,5426,5429],{},[185,5423,5424],{},"Вищий вхід."," Те, що в OpenCart уже є (адмінка, купони, налаштування валют), доводиться будувати або підключати пакети. Тому наш мінімальний бюджет ",[245,5427,5428],{"href":28},"кастомного магазину"," стартує від 150 000 грн, тоді як шаблонний запуск може бути в рази дешевшим.",[259,5431,5432,5435,5436,727],{},[185,5433,5434],{},"Залежність від команди."," Якщо розробник зник, а документації й тестів немає, вам так само важко, як і з готовою CMS. Тому ми вимагаємо документацію, доступи до репозиторію й код-рев'ю. Це частина ",[245,5437,5438],{"href":43},"процесу роботи",[259,5440,5441,5444],{},[185,5442,5443],{},"Довший старт."," Орієнтовно 10–14 тижнів проти 3–5 для шаблонного рішення.",[259,5446,5447,5450],{},[185,5448,5449],{},"Менше готових «фіч»."," Блог, SEO-плагіни, візуальний редактор: у Laravel їх доведеться підключати окремо. Для контентної частини ми зазвичай використовуємо Nuxt із файловим контентом.",[744,5452,5453],{},[137,5454,5455,5457,5458,727],{},[185,5456,4908],{}," Проведемо консультацію тех-ліда на 90 хвилин: подивимось ваш бізнес-процес і чесно скажемо, чи потрібен кастом, чи вистачить готової CMS. Деталі на сторінці ",[245,5459,33],{"href":34},[144,5461,5463],{"id":5462},"як-ми-вирішуємо-пять-питань","Як ми вирішуємо: п'ять питань",[137,5465,5466],{},"Ось питання, які ми ставимо клієнту перед тим, як рекомендувати платформу.",[299,5468,5469,5475,5481,5487,5493],{},[259,5470,5471,5474],{},[185,5472,5473],{},"Чи вкладається ваша логіка ціноутворення й замовлень у стандартний кошик?"," Якщо так, рухайтесь у бік готового рішення.",[259,5476,5477,5480],{},[185,5478,5479],{},"Скільки інтеграцій потрібно, і наскільки вони критичні?"," Одна оплата й одна доставка це стандарт. П'ять систем із двосторонньою синхронізацією це кастом.",[259,5482,5483,5486],{},[185,5484,5485],{},"Який обсяг каталогу і трафіку через рік-два?"," Від кількох тисяч товарів і значного трафіку питання швидкодії стає серйозним.",[259,5488,5489,5492],{},[185,5490,5491],{},"Хто підтримуватиме сайт?"," Якщо в команді вже є WordPress-розробник, а бюджет обмежений, це вагомий аргумент.",[259,5494,5495,5498],{},[185,5496,5497],{},"Яка вартість простою і помилки?"," Чим дорожча хвилина недоступності, тим більше сенсу вкладатись у тести, архітектуру й моніторинг.",[137,5500,5501],{},"Орієнтовний підсумок наших рекомендацій:",[256,5503,5504,5510,5516,5522],{},[259,5505,5506,5509],{},[185,5507,5508],{},"Перевірка ідеї, малий каталог, стандартні процеси:"," готова CMS або конструктор.",[259,5511,5512,5515],{},[185,5513,5514],{},"Контентний проєкт із вітриною:"," WordPress з WooCommerce.",[259,5517,5518,5521],{},[185,5519,5520],{},"Магазин із нестандартною логікою, B2B, багатьма інтеграціями або планами на масштабування:"," Laravel.",[259,5523,5524,5527],{},[185,5525,5526],{},"Існуючий магазин на OpenCart, який вже не витримує:"," спершу аудит, і лише потім рішення про міграцію.",[144,5529,5531],{"id":5530},"міграція-коли-перерости-готову-cms","Міграція: коли «перерости» готову CMS",[137,5533,5534],{},"Найчастіша історія з нашого досвіду: магазин запустили на OpenCart чи WooCommerce, він виріс, а модулів стало 30+. Сторінки відкриваються повільно, кожне оновлення це тиждень тестування, а нова фіча це доробка поверх доробки. Власник вирішує мігрувати.",[137,5536,5537,5538,5540],{},"Тут корисно не поспішати. Перед рішенням про міграцію ми радимо ",[245,5539,4787],{"href":4460},": іноді проблему вирішує чистка модулів, кеш і оптимізація запитів, а повна міграція не потрібна. Якщо ж аудит показує, що архітектура вичерпала себе, міграція планується поетапно:",[256,5542,5543,5549,5555,5561],{},[259,5544,5545,5548],{},[185,5546,5547],{},"Спочатку дані."," Каталог, клієнти, історія замовлень переносяться з перевіркою цілісності.",[259,5550,5551,5554],{},[185,5552,5553],{},"URL і SEO."," Старі адреси отримують 301-редиректи, інакше ви втратите позиції в пошуку.",[259,5556,5557,5560],{},[185,5558,5559],{},"Паралельний запуск."," Нова версія тестується на копії реальних даних до перемикання.",[259,5562,5563,5566,5567,5570],{},[185,5564,5565],{},"Тестування перед запуском."," Перевіряємо шлях покупця з ",[245,5568,5569],{"href":2074},"чек-листа на 60 пунктів"," і відкат на випадок проблем.",[137,5572,5573],{},"Міграція це завжди ризик, тому її планують на період низького трафіку, а не напередодні сезону розпродажів.",[144,5575,858],{"id":857},[137,5577,5578],{},"Не існує «найкращої платформи» взагалі, є платформа, яка підходить вашій задачі. Готова CMS дає швидкий і дешевий старт, але накопичує вартість змін. Laravel дає контроль і передбачуваність, але вимагає більших початкових вкладень і сильнішої команди.",[137,5580,5581],{},"Практичне правило: порівнюйте не вартість запуску, а вартість володіння на горизонті 2–3 роки. Включайте в неї оновлення, підтримку, швидкість, ризик простою й вартість нових функцій. Тоді картина часто змінюється на користь тієї платформи, яку ви спочатку відкидали.",[137,5583,5584,5585,727],{},"Коротко: стандартна вітрина без особливої логіки це OpenCart чи WooCommerce; ваш бізнес-процес визначає код, а не навпаки це Laravel. Якщо вагаєтесь, краще витратити годину на консультацію, ніж місяці на міграцію. Скільки це може коштувати, ми розбирали в статті ",[245,5586,5587],{"href":1423},"Скільки коштує розробка інтернет-магазину у 2026",[744,5589,5590],{},[137,5591,5592,5594,5595,5597,5598,5602],{},[185,5593,1435],{}," Розкажіть про свій проєкт у ",[245,5596,1985],{"href":17}," або подивіться, як ми підходимо до ",[245,5599,5601],{"href":5600},"\u002Fposluhy\u002Flaravel-rozrobka","розробки на Laravel",". Дамо чесну рекомендацію, навіть якщо це буде не Laravel.",{"title":14,"searchDepth":465,"depth":879,"links":5604},[5605,5606,5607,5608,5614,5617,5618,5619],{"id":5111,"depth":465,"text":5112},{"id":5140,"depth":465,"text":5141},{"id":5257,"depth":465,"text":5258},{"id":5291,"depth":465,"text":5292,"children":5609},[5610,5611,5612,5613],{"id":5298,"depth":879,"text":1177},{"id":5321,"depth":879,"text":5322},{"id":5333,"depth":879,"text":5217},{"id":5339,"depth":879,"text":5340},{"id":5366,"depth":465,"text":5367,"children":5615},[5616],{"id":5413,"depth":879,"text":5414},{"id":5462,"depth":465,"text":5463},{"id":5530,"depth":465,"text":5531},{"id":857,"depth":465,"text":858},"stack.compare",[5622,5624,5626,5628],{"marker":905,"text":5623},"WooCommerce: швидкий старт",{"marker":910,"text":5625},"OpenCart: модулі від різних авторів",{"marker":905,"text":5627},"Laravel: код і логіка ваші",{"marker":913,"text":5629},"вибір залежить від задачі","3 платформи",[5632,5635,5638,5641],{"q":5633,"a":5634},"Що краще для інтернет-магазину: Laravel чи OpenCart?","Для типового магазину зі стандартним каталогом і невеликим бюджетом готова CMS на кшталт OpenCart швидша й дешевша на старті. Laravel виграє там, де потрібні нестандартна логіка, глибокі інтеграції та масштабування. Рішення залежить від ваших процесів, а не від моди.",{"q":5636,"a":5637},"Скільки коштує магазин на Laravel порівняно з готовою CMS?","Кастомний магазин у нас стартує від 150 000 грн, зазвичай 10–14 тижнів. Готова CMS на старті дешевша, але витрати можуть зрости через платні модулі, доробки й обмеження. Тому порівнюйте не вартість запуску, а сукупні витрати за кілька років.",{"q":5639,"a":5640},"Коли варто переходити з OpenCart чи WordPress на кастомне рішення?","Коли ви платите за дедалі більше модулів, постійно обходите обмеження CMS і кожне оновлення ламає кастомізації. Інші ознаки: повільна робота та страх чіпати код. Міграцію краще планувати поетапно, зберігши адреси сторінок і SEO-позиції. Так ви не втратите трафік під час переїзду.",{"q":5642,"a":5643},"Чи можна зробити SEO-дружній магазин на Laravel?","Так, але те, що CMS дає з коробки, доведеться закласти самостійно: метатеги, canonical, sitemap, чисті URL і швидкість. Це частина кошторису, тому обговоріть її з розробником до старту й перевірте перед запуском. Тоді результат буде не гіршим, ніж у готовій CMS, а часто швидшим.",{},"\u002Fuk\u002Fblog\u002Flaravel-chy-opencart-wordpress-dlia-mahazynu",{"title":5100,"description":5105},"Інтернет-магазин на Laravel чи OpenCart\u002FWordPress: порівняння за ціною, швидкістю, безпекою і гнучкістю. Коли готова CMS краща, а коли ні.","Laravel чи OpenCart і WordPress для магазину — Tochno.","laravel-chy-opencart-wordpress-dlia-mahazynu","uk\u002Fblog\u002Flaravel-chy-opencart-wordpress-dlia-mahazynu",[4530,942],"7YN7VSDGJgYmdUPKwFvbWAwRXQBy5Bw4jLAyCPVReqc",{"id":5654,"title":5655,"author":132,"body":5656,"cover":901,"coverFile":6396,"coverLines":6397,"coverStat":6406,"date":916,"description":5660,"excerpt":901,"extension":917,"faq":6407,"featured":931,"key":901,"meta":6420,"navigation":933,"path":6421,"readingTime":1483,"seo":6422,"seoDescription":6423,"seoTitle":6424,"slug":6425,"stem":6426,"tags":6427,"updated":944,"__hash__":6428},"blog_uk\u002Fuk\u002Fblog\u002Fnuxt-dlia-marketynhovoho-saitu.md","Nuxt для маркетингового сайту: SEO, швидкість, мультимовність",{"type":134,"value":5657,"toc":6372},[5658,5661,5664,5668,5681,5684,5734,5737,5828,5831,5835,5839,5849,5903,5915,5919,5929,5966,5969,5973,5988,5992,5995,5999,6002,6006,6016,6034,6038,6049,6053,6056,6077,6080,6084,6095,6107,6111,6114,6118,6132,6136,6147,6151,6154,6157,6171,6175,6178,6198,6201,6209,6213,6216,6242,6247,6251,6306,6310,6353,6359,6369],[137,5659,5660],{},"Nuxt розробка для маркетингового сайту виправдана, коли вам потрібні швидкі сторінки з повним HTML для пошуковиків, чіткий контроль над SEO і можливість додати інтерактив (калькулятор, форму, кабінет) без переписування сайту. Для сайту з п'яти статичних сторінок і редактором, що «просто хоче щось поправити», простіше інструменти не вигадаєш. Нижче розбираємо, що саме дає Nuxt, як це налаштувати, і де він зайвий.",[137,5662,5663],{},"Ми самі робимо власний сайт Tochno на Nuxt із генерацією статичних сторінок, тому розповідаємо про налаштування, з якими стикаємося щодня. Конкретні версії й імена модулів змінюються, тому перед впровадженням звіряйте з документацією.",[144,5665,5667],{"id":5666},"чому-маркетинговому-сайту-важливий-ssg-або-ssr","Чому маркетинговому сайту важливий SSG або SSR",[137,5669,5670,5671,5674,5675,5680],{},"Класичний SPA на Vue чи React віддає порожній ",[386,5672,5673],{},"\u003Cdiv id=\"app\">",", а контент малює JavaScript у браузері. ",[245,5676,5679],{"href":5677,"rel":5678},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fjavascript\u002Fjavascript-seo-basics",[249],"Google вміє виконувати JS",", але робить це у другій хвилі індексації, із затримкою і не завжди бездоганно. Інші пошукові системи і сервіси попереднього перегляду посилань (месенджери, соцмережі) JS не виконують зовсім.",[137,5682,5683],{},"Для маркетингового сайту це неприйнятно: його головна мета, щоб його знаходили й коректно показували в пошуку та в соцмережах. Тому потрібен HTML із повним текстом уже у відповіді сервера. Nuxt дає це з коробки в кількох режимах:",[152,5685,5686,5699],{},[155,5687,5688],{},[158,5689,5690,5693,5696],{},[161,5691,5692],{},"Режим",[161,5694,5695],{},"Як працює",[161,5697,5698],{},"Коли обирати",[177,5700,5701,5712,5723],{},[158,5702,5703,5706,5709],{},[182,5704,5705],{},"SSG (prerender)",[182,5707,5708],{},"усі сторінки збираються в HTML під час білда",[182,5710,5711],{},"лендінги, корпоративні сайти, блоги, документація",[158,5713,5714,5717,5720],{},[182,5715,5716],{},"SSR",[182,5718,5719],{},"HTML формується на сервері на кожен запит",[182,5721,5722],{},"персоналізовані сторінки, каталоги з частими змінами",[158,5724,5725,5728,5731],{},[182,5726,5727],{},"Гібрид (routeRules)",[182,5729,5730],{},"частина маршрутів пререндериться, частина рендериться на запит",[182,5732,5733],{},"сайт із блогом і кабінетом чи API",[137,5735,5736],{},"Гібрид у Nuxt налаштовується декларативно:",[416,5738,5742],{"className":5739,"code":5740,"language":5741,"meta":14,"style":14},"language-ts shiki shiki-themes github-dark-default","\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  routeRules: {\n    '\u002F**': { prerender: true },       \u002F\u002F marketing pages: static HTML\n    '\u002Fapi\u002F**': { prerender: false },  \u002F\u002F API stays dynamic\n    '\u002Fkabinet\u002F**': { ssr: false },    \u002F\u002F private area: SPA, no SEO needed\n  },\n})\n","ts",[386,5743,5744,5749,5763,5768,5784,5800,5816,5823],{"__ignoreMap":14},[424,5745,5746],{"class":426,"line":427},[424,5747,5748],{"class":2129},"\u002F\u002F nuxt.config.ts\n",[424,5750,5751,5754,5757,5760],{"class":426,"line":465},[424,5752,5753],{"class":651},"export",[424,5755,5756],{"class":651}," default",[424,5758,5759],{"class":2146}," defineNuxtConfig",[424,5761,5762],{"class":3436},"({\n",[424,5764,5765],{"class":426,"line":879},[424,5766,5767],{"class":430},"  routeRules: {\n",[424,5769,5770,5773,5776,5778,5781],{"class":426,"line":2181},[424,5771,5772],{"class":445},"    '\u002F**'",[424,5774,5775],{"class":430},": { prerender: ",[424,5777,4028],{"class":438},[424,5779,5780],{"class":430}," },       ",[424,5782,5783],{"class":2129},"\u002F\u002F marketing pages: static HTML\n",[424,5785,5786,5789,5791,5794,5797],{"class":426,"line":2187},[424,5787,5788],{"class":445},"    '\u002Fapi\u002F**'",[424,5790,5775],{"class":430},[424,5792,5793],{"class":438},"false",[424,5795,5796],{"class":430}," },  ",[424,5798,5799],{"class":2129},"\u002F\u002F API stays dynamic\n",[424,5801,5802,5805,5808,5810,5813],{"class":426,"line":2193},[424,5803,5804],{"class":445},"    '\u002Fkabinet\u002F**'",[424,5806,5807],{"class":430},": { ssr: ",[424,5809,5793],{"class":438},[424,5811,5812],{"class":430}," },    ",[424,5814,5815],{"class":2129},"\u002F\u002F private area: SPA, no SEO needed\n",[424,5817,5818,5821],{"class":426,"line":2199},[424,5819,5820],{"class":430},"  }",[424,5822,3785],{"class":3436},[424,5824,5825],{"class":426,"line":2219},[424,5826,5827],{"class":3436},"})\n",[137,5829,5830],{},"Для сайту, що змінюється раз на тиждень, SSG майже завжди найкращий вибір: сторінки віддаються з CDN чи звичайного nginx без обчислень, а відповідь миттєва.",[144,5832,5834],{"id":5833},"seo-в-nuxt-що-налаштувати-а-що-вже-є","SEO в Nuxt: що налаштувати, а що вже є",[291,5836,5838],{"id":5837},"мета-теги-і-канонічні-адреси","Мета-теги і канонічні адреси",[137,5840,5841,5842,399,5845,5848],{},"Nuxt має вбудований ",[386,5843,5844],{},"useSeoMeta",[386,5846,5847],{},"useHead",". Усе, що ми описуємо в компоненті сторінки, потрапляє в готовий HTML:",[416,5850,5852],{"className":5739,"code":5851,"language":5741,"meta":14,"style":14},"useSeoMeta({\n  title: 'Розробка сайтів на Nuxt під ключ',\n  description: 'Лендінги й корпоративні сайти: дизайн, розробка, SEO.',\n  ogTitle: 'Розробка сайтів на Nuxt під ключ',\n  ogImage: '\u002Fog\u002Frozrobka-saitiv.png',\n})\n",[386,5853,5854,5860,5870,5880,5889,5899],{"__ignoreMap":14},[424,5855,5856,5858],{"class":426,"line":427},[424,5857,5844],{"class":2146},[424,5859,5762],{"class":430},[424,5861,5862,5865,5868],{"class":426,"line":465},[424,5863,5864],{"class":430},"  title: ",[424,5866,5867],{"class":445},"'Розробка сайтів на Nuxt під ключ'",[424,5869,3785],{"class":430},[424,5871,5872,5875,5878],{"class":426,"line":879},[424,5873,5874],{"class":430},"  description: ",[424,5876,5877],{"class":445},"'Лендінги й корпоративні сайти: дизайн, розробка, SEO.'",[424,5879,3785],{"class":430},[424,5881,5882,5885,5887],{"class":426,"line":2181},[424,5883,5884],{"class":430},"  ogTitle: ",[424,5886,5867],{"class":445},[424,5888,3785],{"class":430},[424,5890,5891,5894,5897],{"class":426,"line":2187},[424,5892,5893],{"class":430},"  ogImage: ",[424,5895,5896],{"class":445},"'\u002Fog\u002Frozrobka-saitiv.png'",[424,5898,3785],{"class":430},[424,5900,5901],{"class":426,"line":2193},[424,5902,5827],{"class":430},[137,5904,5905,5906,5908,5909,5911,5912,5914],{},"Правила, які ми дотримуємо: унікальний ",[386,5907,1812],{}," до 60 символів і ",[386,5910,1815],{}," до 155 для кожної сторінки, один ",[386,5913,1819],{},", канонічна адреса в єдиному форматі (без кінцевого слеша, або навпаки, але завжди однаково). Дублі й розбіжності в канонічних адресах це одна з найчастіших причин «дивних» проблем в Search Console.",[291,5916,5918],{"id":5917},"sitemap-robots-структуровані-дані","Sitemap, robots, структуровані дані",[137,5920,5921,5922,1646,5925,5928],{},"Для sitemap і robots є готові модулі (",[386,5923,5924],{},"@nuxtjs\u002Fsitemap",[386,5926,5927],{},"@nuxtjs\u002Frobots","), для schema.org окремі модулі чи власний composable, що додає JSON-LD. Для маркетингового сайту ми зазвичай додаємо:",[256,5930,5931,5940,5945,5954,5960],{},[259,5932,5933,399,5936,5939],{},[386,5934,5935],{},"Organization",[386,5937,5938],{},"WebSite"," на всі сторінки;",[259,5941,5942,5944],{},[386,5943,1844],{}," на внутрішні сторінки;",[259,5946,5947,5950,5951,5953],{},[386,5948,5949],{},"Service"," або ",[386,5952,1841],{}," на сторінки послуг;",[259,5955,5956,5959],{},[386,5957,5958],{},"FAQPage"," там, де на сторінці справді є блок питань;",[259,5961,5962,5965],{},[386,5963,5964],{},"BlogPosting"," із автором для статей.",[137,5967,5968],{},"Важливо, щоб розмітка відповідала видимому контенту. Розмітка питань, яких на сторінці немає, порушує правила пошукових систем і шкодить більше, ніж допомагає.",[291,5970,5972],{"id":5971},"внутрішні-посилання-та-хлібні-крихти","Внутрішні посилання та хлібні крихти",[137,5974,5975,5976,5979,5980,5983,5984,5987],{},"Nuxt-компонент ",[386,5977,5978],{},"NuxtLink"," рендерить звичайний ",[386,5981,5982],{},"\u003Ca href>",", тому пошукові системи бачать посилання. Простіше помилитися з кнопками, що навігують через ",[386,5985,5986],{},"router.push"," без реальної адреси: такі переходи для краулера невидимі. Усі індексовані переходи мають бути реальними посиланнями.",[291,5989,5991],{"id":5990},"перевірка-перед-релізом","Перевірка перед релізом",[137,5993,5994],{},"Після білда корисно мати автоматичну перевірку: чи є в кожного HTML унікальний title і description, один h1, канонічна адреса, чи немає битих внутрішніх посилань. Ми робимо це скриптом, який запускається в CI, і блокуємо реліз при порушеннях. Це дешевше, ніж шукати дублі в Search Console за місяць після запуску.",[144,5996,5998],{"id":5997},"швидкість-на-чому-виграє-nuxt-і-де-можна-програти","Швидкість: на чому виграє Nuxt, і де можна програти",[137,6000,6001],{},"Nuxt не робить сайт швидким автоматично. Він дає інструменти, а результат залежить від того, як ними користуватися.",[291,6003,6005],{"id":6004},"зображення","Зображення",[137,6007,6008,6009,6012,6013,6015],{},"Модуль ",[386,6010,6011],{},"@nuxt\u002Fimage"," перетворює картинки у сучасні формати (WebP, AVIF), підбирає розміри під екран і додає ",[386,6014,413],{},". Два правила, що дають найбільше:",[299,6017,6018,6024],{},[259,6019,6020,6021,1666],{},"Зображення першого екрана (LCP-елемент) не лінивити, а навпаки, пріоритезувати (",[386,6022,6023],{},"fetchpriority=\"high\"",[259,6025,6026,6027,399,6029,6031,6032,727],{},"Завжди вказувати ",[386,6028,398],{},[386,6030,402],{},", щоб не було стрибків верстки (CLS). Про метрики докладно в статті ",[245,6033,1249],{"href":1248},[291,6035,6037],{"id":6036},"шрифти","Шрифти",[137,6039,6040,6041,6044,6045,6048],{},"Шрифти найчастіше псують і LCP, і CLS. У Nuxt модуль ",[386,6042,6043],{},"@nuxt\u002Ffonts"," завантажує шрифти зі сторонніх сервісів під час білда і віддає їх зі свого домену, підставляє запасні метрики для зменшення стрибків і додає ",[386,6046,6047],{},"preload",". Вигода очевидна: менше запитів на сторонні домени й жодного блокуючого CSS від Google Fonts. Порада: обирайте не більше двох-трьох накреслень і підмножини (subsets) лише для потрібних мов.",[291,6050,6052],{"id":6051},"розмір-javascript","Розмір JavaScript",[137,6054,6055],{},"Тут Nuxt програє «чистому» HTML. Навіть статична сторінка підвантажує Vue, роутер і ядро Nuxt, щоб гідратувати сторінку. Орієнтир: ядро з'їдає десятки кілобайт стисненого JS ще до вашого коду. Що ми робимо, щоб тримати бюджет:",[256,6057,6058,6068,6071,6074],{},[259,6059,6060,6061,6064,6065,389],{},"ліниво гідратуємо важкі інтерактивні блоки (калькулятор, форма, cookie-банер) через ",[386,6062,6063],{},"hydrate-on-visible"," та ",[386,6066,6067],{},"hydrate-on-idle",[259,6069,6070],{},"підключаємо важкі бібліотеки (наприклад, валідацію форм) лише в момент потреби, динамічним імпортом;",[259,6072,6073],{},"не тягнемо UI-кіт цілком, а беремо лише компоненти, що використовуємо;",[259,6075,6076],{},"відстежуємо розмір бандлу в CI, щоб регресії були видно одразу.",[137,6078,6079],{},"Чесно: якщо вашому сайту треба один екран тексту й форма, ванільний HTML або Astro дадуть менший JS. Nuxt виграє, коли на сайті багато компонентів, інтерактиву й спільної логіки.",[291,6081,6083],{"id":6082},"кешування-і-cdn","Кешування і CDN",[137,6085,6086,6087,6090,6091,6094],{},"Для SSG достатньо віддавати статичні файли з довгим ",[386,6088,6089],{},"Cache-Control"," для хешованих ресурсів (",[386,6092,6093],{},"\u002F_nuxt\u002F*",") і коротким для HTML. Це можна зробити на nginx, Vercel чи Cloudflare. Окремо перевірте, щоб стиснення (gzip або brotli) було ввімкнене: різниця в розмірі передачі помітна.",[744,6096,6097],{},[137,6098,6099,6102,6103,6106],{},[185,6100,6101],{},"Потрібен сайт, який швидко відкривається і приводить заявки?"," Робимо лендінги й корпоративні сайти на Nuxt: дизайн, розробка, SEO-основа та перевірка швидкості перед запуском. ",[245,6104,6105],{"href":25},"Розробка сайтів на Nuxt під ключ",", від 25 000 грн.",[144,6108,6110],{"id":6109},"мультимовність-без-дублів-і-плутанини","Мультимовність без дублів і плутанини",[137,6112,6113],{},"Для двомовного сайту (українська й англійська) важливо три речі: структура адрес, hreflang і переклади.",[291,6115,6117],{"id":6116},"структура-адрес","Структура адрес",[137,6119,6120,6121,6123,6124,6127,6128,6131],{},"Найпрактичніша схема для українського ринку: основна мова без префікса, інші з префіксом. Тобто ",[386,6122,71],{}," для української й ",[386,6125,6126],{},"\u002Fen\u002Fservices"," для англійської. У модулях Nuxt-i18n це режим ",[386,6129,6130],{},"prefix_except_default",". Слаги української версії транслітеруємо латиницею за офіційною транслітерацією, англійської робимо англійською. Так адреси читабельні й корисні для пошуку.",[291,6133,6135],{"id":6134},"hreflang-і-canonical","hreflang і canonical",[137,6137,6138,6139,6142,6143,6146],{},"Кожна мовна версія посилається на всі інші та на себе (",[386,6140,6141],{},"hreflang","), а канонічна адреса вказує на саму сторінку. Додається ",[386,6144,6145],{},"x-default"," на основну мову. Важливий нюанс: якщо англійська версія ще не готова, не публікуйте порожніх сторінок і не віддавайте hreflang на неіснуючі адреси. Краще мова, вимкнена прапорцем, поки контент не готовий.",[291,6148,6150],{"id":6149},"переклади-й-контент","Переклади й контент",[137,6152,6153],{},"Нестатичні тексти (кнопки, навігація, мітки форм) зручно тримати в JSON-файлах локалей. Контент сторінок і статей краще віддати в окремі Markdown- або YAML-файли за мовами, щоб редактор міг змінювати текст без правки компонентів. Тоді додавання нової мови зводиться до додавання файлів, а не до змін у шаблонах.",[137,6155,6156],{},"Типові помилки в мультимовності:",[256,6158,6159,6162,6165,6168],{},[259,6160,6161],{},"автоматичний редирект за мовою браузера, який заважає краулеру бачити всі версії (краще пропонувати перемикач, а не примусово перенаправляти);",[259,6163,6164],{},"переклад лише тексту, без перекладу мета-тегів і alt-атрибутів;",[259,6166,6167],{},"перемикач мови, що веде на головну, а не на ту саму сторінку іншою мовою;",[259,6169,6170],{},"різні формати дат і валют без урахування локалі.",[144,6172,6174],{"id":6173},"контент-де-його-зберігати","Контент: де його зберігати",[137,6176,6177],{},"Для маркетингового сайту є три підходи:",[299,6179,6180,6186,6192],{},[259,6181,6182,6185],{},[185,6183,6184],{},"Файли в репозиторії"," (Markdown\u002FYAML через Nuxt Content). Плюси: версіонування, швидкість, жодних зовнішніх залежностей, повний контроль. Мінус: правки йдуть через розробника або Git.",[259,6187,6188,6191],{},[185,6189,6190],{},"Headless CMS"," (Strapi, Directus, Sanity та інші). Плюси: зручний редактор для нетехнічної людини. Мінуси: ще одна система для підтримки й додаткові витрати.",[259,6193,6194,6197],{},[185,6195,6196],{},"Адмінка на Laravel."," Виправдана, коли контент тісно пов'язаний з бізнес-логікою (каталог, замовлення). Тоді Nuxt бере дані з API Laravel.",[137,6199,6200],{},"Для сайту, де контент змінюється кілька разів на місяць, перший варіант найекономніший: кожна зміна це коміт і автоматична пересборка. Якщо ж сайт редагують щодня кілька людей, без CMS не обійтися.",[137,6202,6203,6204,6208],{},"Зв'язку Nuxt і Laravel присвячена наша ",[245,6205,6207],{"href":6206},"\u002Fposluhy\u002Ffull-stack-nuxt","розробка на Nuxt і Laravel",", коли потрібно більше, ніж статичний сайт: кабінет, замовлення, інтеграції.",[144,6210,6212],{"id":6211},"коли-nuxt-не-потрібен","Коли Nuxt не потрібен",[137,6214,6215],{},"Краще сказати прямо, коли ми не радимо Nuxt:",[256,6217,6218,6224,6230,6236],{},[259,6219,6220,6223],{},[185,6221,6222],{},"Сайт на 3–5 сторінок без інтерактиву й без планів зростання."," Достатньо статичного HTML або простого генератора.",[259,6225,6226,6229],{},[185,6227,6228],{},"Редактор самостійно щодня змінює контент і дизайн."," Тут буде кращим WordPress або конструктор, бо вигода від повного контролю над кодом не виправдає витрат на підтримку.",[259,6231,6232,6235],{},[185,6233,6234],{},"Дуже малий бюджет і потреба «вчора»."," Конструктор запустить сайт швидше, а перейти на власний код можна пізніше, коли виникнуть обмеження.",[259,6237,6238,6241],{},[185,6239,6240],{},"Команда без жодного досвіду з Vue."," Вартість підтримки зросте. Якщо ви плануєте самі розвивати сайт, врахуйте цей фактор.",[137,6243,6244,6245,727],{},"У решті випадків, коли потрібні швидкість, власний дизайн, SEO-контроль і запас на розвиток, Nuxt виправдовує себе. Порівняння з іншими підходами для магазинів ми розбирали в статті про ",[245,6246,997],{"href":996},[144,6248,6250],{"id":6249},"підводні-камені-з-якими-ми-стикалися","Підводні камені, з якими ми стикалися",[256,6252,6253,6274,6280,6292,6297],{},[259,6254,6255,6258,6259,6262,6263,6266,6267,5950,6270,6273],{},[185,6256,6257],{},"Гідратаційні помилки."," Якщо HTML із сервера не збігається з тим, що рендерить клієнт (випадкові значення, ",[386,6260,6261],{},"Date.now()",", залежності від ",[386,6264,6265],{},"window","), Vue видає попередження й може перемалювати сторінку. Дані, що залежать від браузера, виносимо в ",[386,6268,6269],{},"onMounted",[386,6271,6272],{},"\u003CClientOnly>",", але лише для неіндексованого контенту.",[259,6275,6276,6279],{},[185,6277,6278],{},"Контент лише на клієнті."," Усе, що має індексуватися, повинно бути в HTML. Перевірка проста: відкрийте «Переглянути код сторінки» (не інспектор) і знайдіть свій текст.",[259,6281,6282,6285,6286,399,6288,6291],{},[185,6283,6284],{},"Кінцеві слеші та дублі адрес."," ",[386,6287,71],{},[386,6289,6290],{},"\u002Fposluhy\u002F"," для пошуковика різні адреси. Оберіть один формат, налаштуйте редирект на рівні сервера й канонічну адресу.",[259,6293,6294,6296],{},[185,6295,710],{}," Аналітика, чати й віджети можуть з'їсти весь виграш у швидкості. Підключайте їх після згоди користувача і відкладено.",[259,6298,6299,6302,6303,6305],{},[185,6300,6301],{},"Прев'ю-середовища в індексі."," Закривайте тестові та preview-деплої від індексації (",[386,6304,1835],{},"), інакше пошуковик знайде дублі вашого сайту.",[144,6307,6309],{"id":6308},"чек-лист-перед-запуском-nuxt-сайту","Чек-лист перед запуском Nuxt-сайту",[299,6311,6312,6317,6325,6328,6335,6338,6341,6344,6347,6350],{},[259,6313,6314,6315,727],{},"Відкритий код сторінки містить повний текст і один ",[386,6316,1819],{},[259,6318,6319,6320,399,6322,6324],{},"Унікальні ",[386,6321,1812],{},[386,6323,1815],{}," на кожній сторінці.",[259,6326,6327],{},"Канонічні адреси в єдиному форматі, редирект зі слешів налаштований.",[259,6329,6330,399,6332,6334],{},[386,6331,1831],{},[386,6333,1828],{}," працюють на проді та закривають тестові середовища.",[259,6336,6337],{},"Структуровані дані проходять Rich Results Test.",[259,6339,6340],{},"Зображення в сучасних форматах, першого екрана не лінивимо, розміри задані.",[259,6342,6343],{},"Шрифти віддаються з вашого домену, із запасними метриками.",[259,6345,6346],{},"Lighthouse на мобільному, а не на десктопі; реальні дані CWV додаємо після запуску з Search Console.",[259,6348,6349],{},"Форми й кнопки працюють без JS або мають запасний шлях (посилання на месенджер, mailto).",[259,6351,6352],{},"Мовні версії посилаються одна на одну, порожніх мов немає.",[137,6354,6355,6356,6358],{},"Якщо ви вже маєте сайт на Nuxt і сумніваєтесь у ньому, першим кроком буде ",[245,6357,4787],{"href":4460}," або експрес-перевірка швидкості й індексації.",[744,6360,6361],{},[137,6362,6363,6366,6367,727],{},[185,6364,6365],{},"Плануєте сайт або перепис на Nuxt?"," Опишіть задачу в брифі: ми скажемо, чи Nuxt справді вам потрібен, і дамо оцінку за 1 робочий день. ",[245,6368,1279],{"href":17},[875,6370,6371],{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":14,"searchDepth":465,"depth":879,"links":6373},[6374,6375,6381,6387,6392,6393,6394,6395],{"id":5666,"depth":465,"text":5667},{"id":5833,"depth":465,"text":5834,"children":6376},[6377,6378,6379,6380],{"id":5837,"depth":879,"text":5838},{"id":5917,"depth":879,"text":5918},{"id":5971,"depth":879,"text":5972},{"id":5990,"depth":879,"text":5991},{"id":5997,"depth":465,"text":5998,"children":6382},[6383,6384,6385,6386],{"id":6004,"depth":879,"text":6005},{"id":6036,"depth":879,"text":6037},{"id":6051,"depth":879,"text":6052},{"id":6082,"depth":879,"text":6083},{"id":6109,"depth":465,"text":6110,"children":6388},[6389,6390,6391],{"id":6116,"depth":879,"text":6117},{"id":6134,"depth":879,"text":6135},{"id":6149,"depth":879,"text":6150},{"id":6173,"depth":465,"text":6174},{"id":6211,"depth":465,"text":6212},{"id":6249,"depth":465,"text":6250},{"id":6308,"depth":465,"text":6309},"nuxt.config.ts",[6398,6400,6402,6404],{"marker":905,"text":6399},"prerender: весь контент у HTML",{"marker":905,"text":6401},"canonical, hreflang, sitemap",{"marker":910,"text":6403},"JS-бюджет: стежимо за розміром",{"marker":913,"text":6405},"i18n: префікс мови без дублів","SSG",[6408,6411,6414,6417],{"q":6409,"a":6410},"Чи добре Nuxt підходить для SEO?","Так: Nuxt віддає готовий HTML через SSG або SSR, тож пошукові системи й AI-боти одразу бачать увесь контент. Метатеги, canonical, sitemap та hreflang потрібно налаштувати, але інструменти для цього є. Без налаштувань будь-який фреймворк дасть посередній результат.",{"q":6412,"a":6413},"Скільки коштує сайт на Nuxt?","Лендінг на Nuxt у нас стартує від 25 000 грн і робиться 2–3 тижні, корпоративний сайт від 60 000 грн, зазвичай 5–7 тижнів. Кінцева сума залежить від кількості сторінок, мов, інтеграцій і складності дизайну. Точну суму називаємо після короткого брифу.",{"q":6415,"a":6416},"Чим SSG відрізняється від SSR у Nuxt?","SSG генерує сторінки заздалегідь під час збирання, а SSR формує їх на сервері під кожен запит. Для маркетингового сайту з нечастими змінами SSG простіший, швидший і дешевший у хостингу. SSR доречний, коли контент часто змінюється або залежить від користувача.",{"q":6418,"a":6419},"Коли Nuxt не потрібен?","Якщо потрібна проста візитка чи сайт, який щодня редагують без розробника, практичнішими будуть WordPress або конструктор. Nuxt виправданий, коли важливі швидкість, SEO, мультимовність і контроль над кодом. Обирайте за реальними потребами, а не за технологічною модою.",{},"\u002Fuk\u002Fblog\u002Fnuxt-dlia-marketynhovoho-saitu",{"title":5655,"description":5660},"Nuxt розробка для маркетингового сайту: як SSG дає SEO та швидкість, як налаштувати мультимовність і де Nuxt не потрібен. Практика з прикладами конфігу.","Nuxt розробка маркетингового сайту: SEO, швидкість — Tochno.","nuxt-dlia-marketynhovoho-saitu","uk\u002Fblog\u002Fnuxt-dlia-marketynhovoho-saitu",[943],"dqP4aYzIRkRwZewVQVhMpPoSgzF0eZbDvpsDXQSHJm4",{"id":6430,"title":6431,"author":132,"body":6432,"cover":901,"coverFile":7156,"coverLines":7157,"coverStat":7166,"date":916,"description":6436,"excerpt":901,"extension":917,"faq":7167,"featured":931,"key":901,"meta":7180,"navigation":933,"path":7181,"readingTime":1483,"seo":7182,"seoDescription":7183,"seoTitle":7184,"slug":7185,"stem":7186,"tags":7187,"updated":944,"__hash__":7188},"blog_uk\u002Fuk\u002Fblog\u002Fruchne-chy-avtomatyzovane-testuvannia.md","Ручне vs автоматизоване тестування: що потрібно малому бізнесу",{"type":134,"value":6433,"toc":7135},[6434,6437,6440,6444,6450,6456,6545,6548,6552,6555,6587,6594,6603,6607,6614,6617,6640,6648,6898,6904,6907,6911,6914,6927,6930,6941,6945,6948,6952,6959,6963,6969,6973,6983,6987,6992,6996,6999,7025,7032,7036,7039,7043,7046,7050,7053,7057,7060,7064,7067,7070,7073,7077,7109,7116,7118,7121,7132],[137,6435,6436],{},"Малому бізнесу зазвичай не потрібно вибирати між ручним та автоматизованим тестуванням: потрібна правильна послідовність. Спочатку ручне тестування нового та нестабільного функціоналу, потім автотести для кількох критичних сценаріїв, які повторюються перед кожним релізом: реєстрація, кошик, оформлення замовлення, оплата. Така комбінація закриває основні ризики за помірні гроші.",[137,6438,6439],{},"Нижче розбираємо, у чому різниця, що кожен підхід ловить, скільки це коштує за порядком величини і як розпочати без зайвих витрат. Ми працюємо з обома підходами, тому не будемо стверджувати, що «автотести вирішують усе» або що «ручного вистачить».",[144,6441,6443],{"id":6442},"у-чому-різниця-між-ручним-та-автоматизованим-тестуванням","У чому різниця між ручним та автоматизованим тестуванням",[137,6445,6446,6449],{},[185,6447,6448],{},"Ручне тестування"," — це коли людина відкриває сайт і проходить сценарії очима користувача: додає товар у кошик, оформлює замовлення, перевіряє на різних пристроях, шукає нестандартні ситуації. Результат — знайдені баги з описом, скриншотами або відео.",[137,6451,6452,6455],{},[185,6453,6454],{},"Автоматизоване тестування"," — це коли ті самі сценарії записані кодом, і програма виконує їх сама. Наприклад, скрипт на Playwright відкриває браузер, додає товар, проходить checkout і перевіряє, що замовлення створилося. Запускається за кілька хвилин і повторюється скільки завгодно разів.",[152,6457,6458,6470],{},[155,6459,6460],{},[158,6461,6462,6464,6467],{},[161,6463,1051],{},[161,6465,6466],{},"Ручне",[161,6468,6469],{},"Автоматизоване",[177,6471,6472,6482,6493,6504,6515,6524,6535],{},[158,6473,6474,6476,6479],{},[182,6475,1070],{},[182,6477,6478],{},"Швидко, без підготовки",[182,6480,6481],{},"Потрібен час на написання й налаштування",[158,6483,6484,6487,6490],{},[182,6485,6486],{},"Вартість одного прогону",[182,6488,6489],{},"Щоразу оплачуються години",[182,6491,6492],{},"Майже нульова після створення",[158,6494,6495,6498,6501],{},[182,6496,6497],{},"Пошук нових, несподіваних проблем",[182,6499,6500],{},"Сильна сторона: людина помічає дивне",[182,6502,6503],{},"Слабка: перевіряє лише закладене",[158,6505,6506,6509,6512],{},[182,6507,6508],{},"Повторювані сценарії (регрес)",[182,6510,6511],{},"Нудно і дорого, людина помиляється",[182,6513,6514],{},"Сильна сторона: стабільно й швидко",[158,6516,6517,6520,6522],{},[182,6518,6519],{},"Оцінка зручності, дизайну, змісту",[182,6521,1122],{},[182,6523,1205],{},[158,6525,6526,6529,6532],{},[182,6527,6528],{},"Кросбраузерність і пристрої",[182,6530,6531],{},"Реальні пристрої, але повільно",[182,6533,6534],{},"Швидко в кількох браузерах, але лише емуляція",[158,6536,6537,6539,6542],{},[182,6538,126],{},[182,6540,6541],{},"Не потрібна",[182,6543,6544],{},"Тести ламаються разом із зміною інтерфейсу",[137,6546,6547],{},"Звідси проста логіка: людина шукає нове й дивне, машина захищає від повторення старого.",[144,6549,6551],{"id":6550},"що-саме-ловить-ручне-тестування","Що саме ловить ручне тестування",[137,6553,6554],{},"Людина здатна побачити те, що ніхто не передбачав у вимогах. На практиці ручне тестування виявляє:",[256,6556,6557,6563,6569,6575,6581],{},[259,6558,6559,6562],{},[185,6560,6561],{},"Логічні помилки:"," знижка застосовується двічі, доставка рахується некоректно для певного міста.",[259,6564,6565,6568],{},[185,6566,6567],{},"Проблеми зручності:"," кнопка під клавіатурою на мобільному, незрозуміле повідомлення про помилку, форма, що очищається після невдалої валідації.",[259,6570,6571,6574],{},[185,6572,6573],{},"Візуальні дефекти:"," текст, що налізає, зображення, що розтягнулися, неправильний шрифт.",[259,6576,6577,6580],{},[185,6578,6579],{},"Нестандартні шляхи:"," повернутися «назад» після оплати, відкрити кошик у двох вкладках, змінити кількість до нуля.",[259,6582,6583,6586],{},[185,6584,6585],{},"Реальні пристрої:"," старий Android, Safari на iPhone, повільна мережа.",[137,6588,6589,6590,6593],{},"Типова ручна перевірка — це чек-лист із десятків пунктів. Ми показували, як він виглядає для магазину, у ",[245,6591,6592],{"href":2074},"чек-листі тестування інтернет-магазину перед запуском",". Якщо ви не знаєте, з чого розпочати, найкращий перший крок — один раз провести повне ручне тестування й зафіксувати результат у вигляді тест-кейсів. Їх згодом можна автоматизувати.",[137,6595,6596,6597,6600,6601,2626],{},"Ручне тестування потрібне перед запуском нового сайту, після великих змін, при додаванні складного функціоналу (оплата, інтеграція з доставкою, особистий кабінет). У нас це послуга ",[245,6598,6599],{"href":2730},"ручного тестування сайтів"," від $20 за годину; для магазину є окремий ",[245,6602,30],{"href":31},[144,6604,6606],{"id":6605},"що-саме-ловить-автоматизоване-тестування","Що саме ловить автоматизоване тестування",[137,6608,6609,6610,6613],{},"Автотести найкраще працюють там, де сценарій стабільний і повторюється часто. Це класичний ",[185,6611,6612],{},"регрес",": після кожної зміни коду треба переконатися, що старе не зламалося.",[137,6615,6616],{},"Кандидати на автоматизацію в магазині:",[299,6618,6619,6622,6625,6628,6631,6634,6637],{},[259,6620,6621],{},"Реєстрація й вхід користувача.",[259,6623,6624],{},"Додавання товару в кошик, зміна кількості, видалення.",[259,6626,6627],{},"Оформлення замовлення гостем і зареєстрованим клієнтом.",[259,6629,6630],{},"Застосування промокоду.",[259,6632,6633],{},"Оплата в тестовому режимі платіжки.",[259,6635,6636],{},"Пошук і фільтри каталогу (базові випадки).",[259,6638,6639],{},"Форми заявок і зворотного зв'язку.",[137,6641,6642,6643,609],{},"Приклад простого автотесту на ",[245,6644,6647],{"href":6645,"rel":6646},"https:\u002F\u002Fplaywright.dev\u002Fdocs\u002Fintro",[249],"Playwright",[416,6649,6651],{"className":5739,"code":6650,"language":5741,"meta":14,"style":14},"import { test, expect } from '@playwright\u002Ftest'\n\ntest('гість може оформити замовлення', async ({ page }) => {\n  await page.goto('\u002Fcatalog\u002Fkrosivky-run')\n  await page.getByRole('button', { name: 'Додати в кошик' }).click()\n  await page.goto('\u002Fcart')\n  await page.getByRole('link', { name: 'Оформити замовлення' }).click()\n\n  await page.getByLabel('Телефон').fill('+380501234567')\n  await page.getByLabel(\"Ім'я\").fill('Тест Тестович')\n  await page.getByRole('button', { name: 'Підтвердити' }).click()\n\n  await expect(page.getByText('Дякуємо за замовлення')).toBeVisible()\n})\n",[386,6652,6653,6667,6671,6701,6720,6748,6763,6787,6791,6817,6841,6864,6868,6894],{"__ignoreMap":14},[424,6654,6655,6658,6661,6664],{"class":426,"line":427},[424,6656,6657],{"class":651},"import",[424,6659,6660],{"class":430}," { test, expect } ",[424,6662,6663],{"class":651},"from",[424,6665,6666],{"class":445}," '@playwright\u002Ftest'\n",[424,6668,6669],{"class":426,"line":465},[424,6670,2196],{"emptyLinePlaceholder":933},[424,6672,6673,6676,6678,6681,6683,6686,6689,6692,6695,6698],{"class":426,"line":879},[424,6674,6675],{"class":2146},"test",[424,6677,2173],{"class":430},[424,6679,6680],{"class":445},"'гість може оформити замовлення'",[424,6682,1646],{"class":430},[424,6684,6685],{"class":651},"async",[424,6687,6688],{"class":430}," ({ ",[424,6690,6691],{"class":3436},"page",[424,6693,6694],{"class":430}," }) ",[424,6696,6697],{"class":651},"=>",[424,6699,6700],{"class":430}," {\n",[424,6702,6703,6706,6709,6712,6714,6717],{"class":426,"line":2181},[424,6704,6705],{"class":651},"  await",[424,6707,6708],{"class":430}," page.",[424,6710,6711],{"class":2146},"goto",[424,6713,2173],{"class":430},[424,6715,6716],{"class":445},"'\u002Fcatalog\u002Fkrosivky-run'",[424,6718,6719],{"class":430},")\n",[424,6721,6722,6724,6726,6729,6731,6734,6737,6740,6743,6746],{"class":426,"line":2187},[424,6723,6705],{"class":651},[424,6725,6708],{"class":430},[424,6727,6728],{"class":2146},"getByRole",[424,6730,2173],{"class":430},[424,6732,6733],{"class":445},"'button'",[424,6735,6736],{"class":430},", { name: ",[424,6738,6739],{"class":445},"'Додати в кошик'",[424,6741,6742],{"class":430}," }).",[424,6744,6745],{"class":2146},"click",[424,6747,4095],{"class":430},[424,6749,6750,6752,6754,6756,6758,6761],{"class":426,"line":2193},[424,6751,6705],{"class":651},[424,6753,6708],{"class":430},[424,6755,6711],{"class":2146},[424,6757,2173],{"class":430},[424,6759,6760],{"class":445},"'\u002Fcart'",[424,6762,6719],{"class":430},[424,6764,6765,6767,6769,6771,6773,6776,6778,6781,6783,6785],{"class":426,"line":2199},[424,6766,6705],{"class":651},[424,6768,6708],{"class":430},[424,6770,6728],{"class":2146},[424,6772,2173],{"class":430},[424,6774,6775],{"class":445},"'link'",[424,6777,6736],{"class":430},[424,6779,6780],{"class":445},"'Оформити замовлення'",[424,6782,6742],{"class":430},[424,6784,6745],{"class":2146},[424,6786,4095],{"class":430},[424,6788,6789],{"class":426,"line":2219},[424,6790,2196],{"emptyLinePlaceholder":933},[424,6792,6793,6795,6797,6800,6802,6805,6807,6810,6812,6815],{"class":426,"line":1483},[424,6794,6705],{"class":651},[424,6796,6708],{"class":430},[424,6798,6799],{"class":2146},"getByLabel",[424,6801,2173],{"class":430},[424,6803,6804],{"class":445},"'Телефон'",[424,6806,1666],{"class":430},[424,6808,6809],{"class":2146},"fill",[424,6811,2173],{"class":430},[424,6813,6814],{"class":445},"'+380501234567'",[424,6816,6719],{"class":430},[424,6818,6819,6821,6823,6825,6827,6830,6832,6834,6836,6839],{"class":426,"line":935},[424,6820,6705],{"class":651},[424,6822,6708],{"class":430},[424,6824,6799],{"class":2146},[424,6826,2173],{"class":430},[424,6828,6829],{"class":445},"\"Ім'я\"",[424,6831,1666],{"class":430},[424,6833,6809],{"class":2146},[424,6835,2173],{"class":430},[424,6837,6838],{"class":445},"'Тест Тестович'",[424,6840,6719],{"class":430},[424,6842,6843,6845,6847,6849,6851,6853,6855,6858,6860,6862],{"class":426,"line":1594},[424,6844,6705],{"class":651},[424,6846,6708],{"class":430},[424,6848,6728],{"class":2146},[424,6850,2173],{"class":430},[424,6852,6733],{"class":445},[424,6854,6736],{"class":430},[424,6856,6857],{"class":445},"'Підтвердити'",[424,6859,6742],{"class":430},[424,6861,6745],{"class":2146},[424,6863,4095],{"class":430},[424,6865,6866],{"class":426,"line":3589},[424,6867,2196],{"emptyLinePlaceholder":933},[424,6869,6870,6872,6875,6878,6881,6883,6886,6889,6892],{"class":426,"line":3595},[424,6871,6705],{"class":651},[424,6873,6874],{"class":2146}," expect",[424,6876,6877],{"class":430},"(page.",[424,6879,6880],{"class":2146},"getByText",[424,6882,2173],{"class":430},[424,6884,6885],{"class":445},"'Дякуємо за замовлення'",[424,6887,6888],{"class":430},")).",[424,6890,6891],{"class":2146},"toBeVisible",[424,6893,4095],{"class":430},[424,6895,6896],{"class":426,"line":3609},[424,6897,5827],{"class":430},[137,6899,6900,6901,6903],{},"Такий тест виконується за кілька секунд і запускається автоматично при кожному оновленні коду. Якщо хтось зламав кнопку «Підтвердити», ви дізнаєтеся до релізу, а не зі скарги покупця. У нас є окрема послуга ",[245,6902,4396],{"href":2671},": Playwright-сценарії ключових шляхів і запуск у CI, вартість визначається після аудиту.",[137,6905,6906],{},"Чого автотести не роблять: не оцінюють дизайн, не «відчувають» зручність, не знаходять проблем, про які ніхто не подумав. Тест перевіряє лише те, що в нього закладено.",[144,6908,6910],{"id":6909},"скільки-це-коштує-порівняння-за-порядком-величини","Скільки це коштує: порівняння за порядком величини",[137,6912,6913],{},"Точні суми залежать від проєкту, тому дамо орієнтири з нашого прайсу й логіку витрат.",[256,6915,6916,6921],{},[259,6917,6918,6920],{},[185,6919,6448],{}," — погодинна оплата: ставка QA-інженера $20–25 за годину. Витрати повторюються при кожному релізі, але гнучко масштабуються: не треба нічого будувати наперед. Для магазину разовий QA-аудит із чек-листом 150+ пунктів стартує від 6 000 грн.",[259,6922,6923,6926],{},[185,6924,6925],{},"Автоматизація"," — разова інвестиція в написання й налаштування плюс невелика підтримка. Перші сценарії готові приблизно за 1–2 тижні. Далі кожен прогін майже безкоштовний.",[137,6928,6929],{},"Правило окупності для малого бізнесу виглядає так: якщо ви випускаєте оновлення рідко (раз на кілька місяців), дешевше тестувати вручну. Якщо оновлення щотижня й кожне вимагає повного регресу, автотести окупаються швидко, бо щоразу заощаджують години ручної роботи. Точку беззбитковості не варто прораховувати на око: порахуйте, скільки годин займає ваш ручний регрес, і помножте на кількість релізів за рік.",[744,6931,6932],{},[137,6933,6934,6937,6938,727],{},[185,6935,6936],{},"Не впевнені, з чого почати?"," Ми зробимо безкоштовний експрес-чек вашого сайту за 48 годин і підкажемо, де достатньо ручної перевірки, а де вже час на автотести. Деталі — на сторінці ",[245,6939,6940],{"href":2730},"ручного тестування",[144,6942,6944],{"id":6943},"як-вирішити-що-потрібно-саме-вам","Як вирішити, що потрібно саме вам",[137,6946,6947],{},"Замість абстрактних порад скористайтеся простою схемою рішень за ситуацією.",[291,6949,6951],{"id":6950},"ви-запускаєте-новий-сайт-або-магазин","Ви запускаєте новий сайт або магазин",[137,6953,6954,6955,6958],{},"Потрібне ",[185,6956,6957],{},"ручне тестування"," перед запуском. Саме на цьому етапі найбільше нового коду й найбільше сюрпризів. Перевірте повний checkout, мобільну версію, форми, листи, інтеграції. Автотести на цьому етапі передчасні: інтерфейс ще змінюється, тести доведеться переписувати.",[291,6960,6962],{"id":6961},"сайт-працює-оновлення-нечасті","Сайт працює, оновлення нечасті",[137,6964,6965,6968],{},[185,6966,6967],{},"Ручний регрес"," перед кожним релізом за готовим чек-листом. Складіть із 20–30 пунктів найважливіше (оформлення замовлення, оплата, форми) і проходьте після змін. Це дешево й надійно.",[291,6970,6972],{"id":6971},"оновлення-часті-а-помилки-у-checkout-уже-коштували-замовлень","Оновлення часті, а помилки у checkout уже коштували замовлень",[137,6974,6975,6976,6979,6980,727],{},"Час на ",[185,6977,6978],{},"автотести"," критичних шляхів. Починайте з трьох-п'яти сценаріїв, що безпосередньо приносять гроші: кошик, checkout, оплата. Типові баги в цих місцях ми розбирали в статті ",[245,6981,6982],{"href":1628},"чому губляться замовлення на checkout",[291,6984,6986],{"id":6985},"розробка-ведеться-постійно-є-команда","Розробка ведеться постійно, є команда",[137,6988,6989,6990,727],{},"Поєднуйте обидва підходи: автотести в CI на кожен pull request, ручне тестування нових фіч перед випуском. Виділений QA в команді (part-time чи full-time) закриває це без наймання штатного співробітника, деталі — у форматі ",[245,6991,4894],{"href":4893},[144,6993,6995],{"id":6994},"з-чого-почати-покроковий-план-на-місяць","З чого почати: покроковий план на місяць",[137,6997,6998],{},"Реалістичний сценарій для малого магазину без тестування взагалі:",[299,7000,7001,7007,7013,7019],{},[259,7002,7003,7006],{},[185,7004,7005],{},"Тиждень 1."," Ручний QA-аудит: проходимо весь сайт за чек-листом, фіксуємо баги з відео та пріоритетами. На виході — список проблем і набір тест-кейсів.",[259,7008,7009,7012],{},[185,7010,7011],{},"Тиждень 2."," Виправлення критичних і серйозних багів. Повторна перевірка виправленого.",[259,7014,7015,7018],{},[185,7016,7017],{},"Тиждень 3."," Вибираємо 3–5 найважливіших тест-кейсів для автоматизації: ті, що торкаються грошей. Пишемо Playwright-сценарії.",[259,7020,7021,7024],{},[185,7022,7023],{},"Тиждень 4."," Підключаємо запуск автотестів до процесу розгортання (CI). Домовляємося про правило: реліз не виходить, якщо автотести червоні.",[137,7026,7027,7028,7031],{},"Після цього ручне тестування займається новим функціоналом і дивними кейсами, автотести охороняють перевірене. Щомісячний регрес можна передати на ",[245,7029,7030],{"href":853},"підтримку сайту"," від 8 000 грн на місяць, де регрес перед релізами входить у формат.",[144,7033,7035],{"id":7034},"що-потрібно-щоб-автотести-справді-працювали","Що потрібно, щоб автотести справді працювали",[137,7037,7038],{},"Автотести — не «встановив і забув». Вони потребують трьох речей, без яких швидко перетворюються на джерело шуму.",[291,7040,7042],{"id":7041},"стабільне-тестове-середовище","Стабільне тестове середовище",[137,7044,7045],{},"Тести мають запускатися на окремому стенді з тестовими даними, а не на живому магазині. Для оплати використовується тестовий режим платіжки, для Нової Пошти — тестовий ключ або заглушка. Це дозволяє безпечно створювати замовлення й не плутати їх зі справжніми. База даних перед прогоном скидається до відомого стану: інакше тест, що вчора проходив, сьогодні впаде через чужі дані.",[291,7047,7049],{"id":7048},"стійкі-селектори-та-сценарії","Стійкі селектори та сценарії",[137,7051,7052],{},"Тест, прив'язаний до верстки («третій div у другому блоці»), ламається від будь-якої правки дизайну. Надійніше шукати елементи за роллю та підписом (кнопка «Підтвердити», поле «Телефон»), як у прикладі вище, або за спеціальними атрибутами для тестів. Тоді змінити колір чи відступ можна без ремонту тестів.",[291,7054,7056],{"id":7055},"запуск-у-ci-і-правило-реакції","Запуск у CI і правило реакції",[137,7058,7059],{},"Автотест має сенс тільки тоді, коли його запускають автоматично й хтось реагує на червоний результат. Типова схема: тести стартують на кожен pull request і перед релізом, а звіт із відео та трасою падіння доступний усій команді. Домовтеся про просте правило: якщо тести червоні, реліз не виходить, поки причину не з'ясовано. Падіння може бути як реальним багом, так і застарілим тестом, але ігнорувати його не можна.",[144,7061,7063],{"id":7062},"приклад-розрахунку-окупності","Приклад розрахунку окупності",[137,7065,7066],{},"Візьмемо умовний приклад, щоб показати логіку, а не конкретні цифри для вашого бізнесу. Припустимо, повний ручний регрес ключових сценаріїв займає 3 години, а оновлення виходять раз на тиждень. За рік це близько 50 прогонів по 3 години, тобто 150 годин. За ставки QA-інженера $20–25 за годину це десятки тисяч гривень на рік тільки на повторення однієї й тієї самої перевірки.",[137,7068,7069],{},"Автоматизація тих самих сценаріїв — разові витрати на 1–2 тижні роботи й невелика щорічна підтримка тестів. Прогін автотестів займає хвилини, і людина потрібна лише для розбору падінь. У такому прикладі автоматизація окупається протягом першого-другого кварталу. Якщо ж релізи раз на квартал, тих самих чотирьох прогонів на рік не вистачить, щоб виправдати витрати, і дешевше лишити ручний регрес.",[137,7071,7072],{},"Важливе застереження: це орієнтовна модель. Реальні цифри залежать від складності сценаріїв, стабільності інтерфейсу та кількості інтеграцій. Тому ми завжди починаємо з оцінки на конкретному проєкті, а не з універсальних обіцянок.",[144,7074,7076],{"id":7075},"типові-помилки-малого-бізнесу","Типові помилки малого бізнесу",[256,7078,7079,7085,7091,7097,7103],{},[259,7080,7081,7084],{},[185,7082,7083],{},"Автоматизувати все й одразу."," Великий набір крихких тестів — тягар: вони падають через дрібниці, і їх перестають слухати. Краще мало, але стабільно.",[259,7086,7087,7090],{},[185,7088,7089],{},"Автоматизувати нестабільний інтерфейс."," Якщо дизайн змінюється щотижня, тести постійно ламаються.",[259,7092,7093,7096],{},[185,7094,7095],{},"Покладатися лише на розробника."," Автор коду тестує так, як задумав, а не як вчинить покупець.",[259,7098,7099,7102],{},[185,7100,7101],{},"Не фіксувати результати."," Без звіту неможливо порівняти реліз із попереднім і довести, що виправлене справді виправлене.",[259,7104,7105,7108],{},[185,7106,7107],{},"Думати, що тестування — витрата, а не страховка."," Один пропущений баг в оплаті зазвичай коштує більше, ніж місяць регулярного регресу. Точну суму для вашого магазину порахуйте за кількістю замовлень на день і відсотком, що пройшов би checkout.",[137,7110,7111,7112,7115],{},"Якщо ви вже бачите, що проблеми в самому коді, а не в сценаріях, можливо, потрібен ",[245,7113,7114],{"href":494},"технічний аудит",", а не нові тести: автотести не лікують погану архітектуру, вони лише швидше її викривають.",[144,7117,858],{"id":857},[137,7119,7120],{},"Ручне тестування знаходить нове, дивне й незручне, автоматизоване захищає від повторення старих помилок. Малому бізнесу зазвичай достатньо починати з ручного тестування й чек-листа, а потім автоматизувати кілька критичних сценаріїв, коли релізи стають частими. Головне — не обирати між підходами, а розкласти ролі: людина досліджує, машина стереже.",[744,7122,7123],{},[137,7124,7125,7128,7129,7131],{},[185,7126,7127],{},"Потрібен реліз без неприємних сюрпризів?"," Опишіть свій проєкт у ",[245,7130,1985],{"href":17}," — запропонуємо схему тестування: що перевіряти вручну, що автоматизувати і скільки це коштуватиме.",[875,7133,7134],{},"html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .sQhOw, html code.shiki .sQhOw{--shiki-default:#FFA657}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":14,"searchDepth":465,"depth":879,"links":7136},[7137,7138,7139,7140,7141,7147,7148,7153,7154,7155],{"id":6442,"depth":465,"text":6443},{"id":6550,"depth":465,"text":6551},{"id":6605,"depth":465,"text":6606},{"id":6909,"depth":465,"text":6910},{"id":6943,"depth":465,"text":6944,"children":7142},[7143,7144,7145,7146],{"id":6950,"depth":879,"text":6951},{"id":6961,"depth":879,"text":6962},{"id":6971,"depth":879,"text":6972},{"id":6985,"depth":879,"text":6986},{"id":6994,"depth":465,"text":6995},{"id":7034,"depth":465,"text":7035,"children":7149},[7150,7151,7152],{"id":7041,"depth":879,"text":7042},{"id":7048,"depth":879,"text":7049},{"id":7055,"depth":879,"text":7056},{"id":7062,"depth":465,"text":7063},{"id":7075,"depth":465,"text":7076},{"id":857,"depth":465,"text":858},"checkout.spec.ts",[7158,7160,7162,7164],{"marker":905,"text":7159},"додати товар у кошик",{"marker":905,"text":7161},"оформлення замовлення гостем",{"marker":910,"text":7163},"ручна перевірка: нова фіча",{"marker":913,"text":7165},"автотести запускаються на кожен реліз","1 хв 48 с",[7168,7171,7174,7177],{"q":7169,"a":7170},"Що дешевше: ручне чи автоматизоване тестування?","На старті дешевше ручне: його можна замовити разово й погодинно, у нас ставка QA-інженера $20–25 за годину. Автотести потребують вкладень у написання й підтримку, але окупаються на повторюваних сценаріях. Малому бізнесу зазвичай варто почати з ручного й автоматизувати лише стабільне ядро.",{"q":7172,"a":7173},"Коли малому бізнесу потрібні автотести?","Коли однакові перевірки повторюються після кожного релізу, а ручна регресія забирає забагато часу. Типовий кандидат — шлях покупки в магазині. Якщо продукт часто змінюється, автотести ламатимуться, тому автоматизуйте лише стабільні сценарії. Інакше ви витрачатимете гроші на постійне виправлення самих тестів, а не на користь для бізнесу.",{"q":7175,"a":7176},"З чого почати тестування сайту, якщо його ніколи не тестували?","З ручного QA-аудиту критичних сценаріїв: замовлення, оплата, форми, мобільна версія. Для магазину це 3–5 днів і від 6 000 грн. За результатами аудиту стане видно, які перевірки варто автоматизувати, а які залишити людині. Це дає базу, від якої легко рухатися далі.",{"q":7178,"a":7179},"Чи можуть автотести повністю замінити ручного тестувальника?","Ні. Автотести добре ловлять регресію в уже відомих сценаріях, але не оцінюють зручність і не знаходять несподіваних проблем у новому функціоналі. Ручне й автоматизоване тестування доповнюють одне одного, а їхнє співвідношення залежить від продукту та бюджету.",{},"\u002Fuk\u002Fblog\u002Fruchne-chy-avtomatyzovane-testuvannia",{"title":6431,"description":6436},"Ручне чи автоматизоване тестування сайту: у чому різниця, що обрати малому бізнесу, з чого почати і коли автотести окупаються. Практичний розбір.","Ручне чи автоматизоване тестування: що обрати — Tochno.","ruchne-chy-avtomatyzovane-testuvannia","uk\u002Fblog\u002Fruchne-chy-avtomatyzovane-testuvannia",[2033],"ibivK6OPfwtlrCQ4Pg_KFNubYX9XbJSYrJ1LkC7q_ck",{"id":7190,"title":7191,"author":132,"body":7192,"cover":901,"coverFile":8132,"coverLines":8133,"coverStat":8142,"date":916,"description":7196,"excerpt":901,"extension":917,"faq":8143,"featured":931,"key":901,"meta":8156,"navigation":933,"path":8157,"readingTime":1483,"seo":8158,"seoDescription":8159,"seoTitle":8160,"slug":8161,"stem":8162,"tags":8163,"updated":1467,"__hash__":8164},"blog_uk\u002Fuk\u002Fblog\u002Fshcho-take-tekhnichnyi-audyt-kodu.md","Що таке технічний аудит коду і коли він потрібен",{"type":134,"value":7193,"toc":8114},[7194,7197,7200,7204,7207,7210,7238,7241,7245,7248,7292,7295,7299,7303,7306,7309,7326,7329,7548,7551,7553,7556,7602,7605,7725,7728,7732,7735,7771,7774,7811,7814,7818,7828,7832,7835,7839,7856,7859,7863,7866,7928,7931,7934,7945,7949,7956,7959,7973,7980,7984,7987,8007,8010,8014,8017,8040,8046,8050,8053,8088,8091,8093,8096,8111],[137,7195,7196],{},"Технічний аудит коду — це незалежна перевірка вихідного коду, архітектури та інфраструктури проєкту, результатом якої є звіт: що працює добре, що небезпечно чи повільно, і в якому порядку це виправляти. Він потрібен, коли ви успадковуєте проєкт, змінюєте підрядника, готуєтеся до масштабування чи продажу бізнесу або просто не розумієте, чому кожна нова фіча коштує дорожче за попередню.",[137,7198,7199],{},"Нижче — що саме ми перевіряємо в Laravel-проєктах, як виглядає звіт, які сигнали вказують, що час замовляти аудит, і чого від нього не варто очікувати.",[144,7201,7203],{"id":7202},"що-таке-технічний-аудит-і-чим-він-не-є","Що таке технічний аудит і чим він не є",[137,7205,7206],{},"Аудит — це діагностика, а не лікування. Експерт читає код, запускає проєкт, дивиться на базу даних, залежності, конфігурацію, процес розгортання й складає документ із висновками. Виправлення — окремий етап, який ви можете віддати будь-якій команді, а не обов'язково тій, що проводила аудит.",[137,7208,7209],{},"Аудит коду відрізняється від суміжних послуг:",[256,7211,7212,7221,7227,7233],{},[259,7213,7214,7217,7218,7220],{},[185,7215,7216],{},"QA-тестування"," перевіряє поведінку продукту очима користувача: чи працює кошик, форма, оплата. Це ",[245,7219,1324],{"href":31},". Код при цьому не читається.",[259,7222,7223,7226],{},[185,7224,7225],{},"Код-рев'ю"," оцінює конкретні зміни (pull request) в процесі розробки.",[259,7228,7229,7232],{},[185,7230,7231],{},"Пентест"," — цілеспрямована спроба зламати систему. Ми проводимо перевірку безпеки на рівні коду й конфігурації, але не заявляємо про повний пентест.",[259,7234,7235,7237],{},[185,7236,4855],{}," охоплює проєкт цілком: структуру, якість, безпеку, продуктивність, процеси.",[137,7239,7240],{},"Найкращий результат дають обидва підходи разом: QA знаходить симптоми, аудит коду — причини.",[144,7242,7244],{"id":7243},"сигнали-що-аудит-вам-потрібен","Сигнали, що аудит вам потрібен",[137,7246,7247],{},"Не кожен проєкт потребує аудиту щороку. Є ситуації, коли це особливо виправдано.",[299,7249,7250,7256,7262,7268,7274,7280,7286],{},[259,7251,7252,7255],{},[185,7253,7254],{},"Змінюється команда."," Новий підрядник чи тех-лід має швидко зрозуміти, що саме він отримує, перш ніж брати відповідальність.",[259,7257,7258,7261],{},[185,7259,7260],{},"Нові фічі дорожчають і довго робляться."," Розробники кажуть «там усе переплетено» — це класичний симптом технічного боргу.",[259,7263,7264,7267],{},[185,7265,7266],{},"Сайт повільний або падає під навантаженням."," Особливо в сезонні піки: акції, розпродажі.",[259,7269,7270,7273],{},[185,7271,7272],{},"Після інциденту."," Витік даних, злам адмінки, втрата замовлень.",[259,7275,7276,7279],{},[185,7277,7278],{},"Перед великими змінами."," Міграція на нову версію фреймворку, масштабування, інтеграція з CRM або 1С.",[259,7281,7282,7285],{},[185,7283,7284],{},"Перед продажем або інвестиціями."," Покупець чи інвестор хоче бачити стан активу.",[259,7287,7288,7291],{},[185,7289,7290],{},"Ви не довіряєте оцінкам підрядника."," Незалежна думка допоможе зрозуміти, чи справді «це треба переписати».",[137,7293,7294],{},"Якщо хоча б два пункти вам знайомі, аудит окупиться швидше, ніж ви витратите гроші на нову порцію виправлень «навмання».",[144,7296,7298],{"id":7297},"що-ми-перевіряємо-в-laravel-проєкті","Що ми перевіряємо в Laravel-проєкті",[291,7300,7302],{"id":7301},"архітектура-і-якість-коду","Архітектура і якість коду",[137,7304,7305],{},"Перше, що ми дивимося, — де живе бізнес-логіка. У здоровому проєкті контролер тонкий: валідація, виклик сервісу, відповідь. У нездоровому — контролер на 600 рядків із розрахунком знижок, відправкою листів і роботою з платіжкою.",[137,7307,7308],{},"Ми перевіряємо:",[256,7310,7311,7314,7317,7320,7323],{},[259,7312,7313],{},"розподіл відповідальності: контролери, сервіси, Form Request, Policy, Job;",[259,7315,7316],{},"дублювання коду та «божественні» класи;",[259,7318,7319],{},"залежності між модулями й циклічні зв'язки;",[259,7321,7322],{},"відповідність фреймворку: чи не обходять його механізми власними велосипедами;",[259,7324,7325],{},"покриття тестами й відтворюваність: чи проходять тести, чи є CI.",[137,7327,7328],{},"Типовий приклад проблеми, яку ми описуємо у звіті:",[416,7330,7332],{"className":2120,"code":7331,"language":2122,"meta":14,"style":14},"\u002F\u002F OrderController.php — логіка в контролері\npublic function store(Request $request)\n{\n    $total = 0;\n    foreach ($request->items as $item) {\n        $product = Product::find($item['id']);      \u002F\u002F запит у циклі\n        $total += $product->price * $item['qty'];\n    }\n    if ($request->promo === 'SALE10') {            \u002F\u002F «магічне» значення\n        $total *= 0.9;\n    }\n    $order = Order::create([...]);\n    Mail::to($request->email)->send(new OrderMail($order)); \u002F\u002F синхронна відправка\n}\n",[386,7333,7334,7339,7355,7359,7371,7390,7417,7444,7448,7470,7482,7486,7507,7544],{"__ignoreMap":14},[424,7335,7336],{"class":426,"line":427},[424,7337,7338],{"class":2129},"\u002F\u002F OrderController.php — логіка в контролері\n",[424,7340,7341,7343,7345,7348,7350,7352],{"class":426,"line":465},[424,7342,3522],{"class":651},[424,7344,3514],{"class":651},[424,7346,7347],{"class":2146}," store",[424,7349,2173],{"class":430},[424,7351,3908],{"class":438},[424,7353,7354],{"class":430}," $request)\n",[424,7356,7357],{"class":426,"line":879},[424,7358,3448],{"class":430},[424,7360,7361,7364,7366,7369],{"class":426,"line":2181},[424,7362,7363],{"class":430},"    $total ",[424,7365,442],{"class":651},[424,7367,7368],{"class":438}," 0",[424,7370,3467],{"class":430},[424,7372,7373,7376,7379,7381,7384,7387],{"class":426,"line":2187},[424,7374,7375],{"class":651},"    foreach",[424,7377,7378],{"class":430}," ($request",[424,7380,2167],{"class":651},[424,7382,7383],{"class":430},"items ",[424,7385,7386],{"class":651},"as",[424,7388,7389],{"class":430}," $item) {\n",[424,7391,7392,7395,7397,7400,7402,7405,7408,7411,7414],{"class":426,"line":2193},[424,7393,7394],{"class":430},"        $product ",[424,7396,442],{"class":651},[424,7398,7399],{"class":438}," Product",[424,7401,2143],{"class":651},[424,7403,7404],{"class":2146},"find",[424,7406,7407],{"class":430},"($item[",[424,7409,7410],{"class":445},"'id'",[424,7412,7413],{"class":430},"]);      ",[424,7415,7416],{"class":2129},"\u002F\u002F запит у циклі\n",[424,7418,7419,7422,7425,7428,7430,7433,7436,7439,7442],{"class":426,"line":2199},[424,7420,7421],{"class":430},"        $total ",[424,7423,7424],{"class":651},"+=",[424,7426,7427],{"class":430}," $product",[424,7429,2167],{"class":651},[424,7431,7432],{"class":430},"price ",[424,7434,7435],{"class":651},"*",[424,7437,7438],{"class":430}," $item[",[424,7440,7441],{"class":445},"'qty'",[424,7443,3503],{"class":430},[424,7445,7446],{"class":426,"line":2219},[424,7447,3797],{"class":430},[424,7449,7450,7452,7454,7456,7459,7461,7464,7467],{"class":426,"line":1483},[424,7451,3968],{"class":651},[424,7453,7378],{"class":430},[424,7455,2167],{"class":651},[424,7457,7458],{"class":430},"promo ",[424,7460,4128],{"class":651},[424,7462,7463],{"class":445}," 'SALE10'",[424,7465,7466],{"class":430},") {            ",[424,7468,7469],{"class":2129},"\u002F\u002F «магічне» значення\n",[424,7471,7472,7474,7477,7480],{"class":426,"line":935},[424,7473,7421],{"class":430},[424,7475,7476],{"class":651},"*=",[424,7478,7479],{"class":438}," 0.9",[424,7481,3467],{"class":430},[424,7483,7484],{"class":426,"line":1594},[424,7485,3797],{"class":430},[424,7487,7488,7491,7493,7495,7497,7500,7502,7505],{"class":426,"line":3589},[424,7489,7490],{"class":430},"    $order ",[424,7492,442],{"class":651},[424,7494,2140],{"class":438},[424,7496,2143],{"class":651},[424,7498,7499],{"class":2146},"create",[424,7501,2236],{"class":430},[424,7503,7504],{"class":651},"...",[424,7506,3721],{"class":430},[424,7508,7509,7512,7514,7517,7520,7522,7525,7527,7530,7532,7535,7538,7541],{"class":426,"line":3595},[424,7510,7511],{"class":438},"    Mail",[424,7513,2143],{"class":651},[424,7515,7516],{"class":2146},"to",[424,7518,7519],{"class":430},"($request",[424,7521,2167],{"class":651},[424,7523,7524],{"class":430},"email)",[424,7526,2167],{"class":651},[424,7528,7529],{"class":2146},"send",[424,7531,2173],{"class":430},[424,7533,7534],{"class":651},"new",[424,7536,7537],{"class":438}," OrderMail",[424,7539,7540],{"class":430},"($order)); ",[424,7542,7543],{"class":2129},"\u002F\u002F синхронна відправка\n",[424,7545,7546],{"class":426,"line":3609},[424,7547,2256],{"class":430},[137,7549,7550],{},"У звіті це перетворюється на конкретні пункти: винести розрахунок у сервіс, завантажувати товари одним запитом, промокоди зберігати в базі, лист відправляти через чергу.",[291,7552,5217],{"id":5333},[137,7554,7555],{},"Для Laravel ми перевіряємо базові, але критичні речі, які часто пропускають:",[256,7557,7558,7564,7571,7581,7587,7590,7593,7599],{},[259,7559,7560,7563],{},[386,7561,7562],{},"APP_DEBUG=true"," на продакшені та витік змінних середовища;",[259,7565,7566,7567,7570],{},"масове присвоєння (",[386,7568,7569],{},"$guarded = []",") і відсутність перевірки прав доступу в контролерах;",[259,7572,7573,7574,1646,7577,7580],{},"SQL-ін'єкції через сирі запити (",[386,7575,7576],{},"DB::raw",[386,7578,7579],{},"whereRaw"," з конкатенацією);",[259,7582,7583,7584,3849],{},"XSS через вивід неекранованих даних (",[386,7585,7586],{},"{!! !!}",[259,7588,7589],{},"завантаження файлів без перевірки типу й розміру;",[259,7591,7592],{},"CSRF, налаштування cookie, заголовки безпеки;",[259,7594,7595,7596,3849],{},"застарілі пакети з відомими вразливостями (",[386,7597,7598],{},"composer audit",[259,7600,7601],{},"зберігання секретів у репозиторії та історії git.",[137,7603,7604],{},"Небезпечний приклад, який трапляється частіше, ніж хотілося б:",[416,7606,7608],{"className":2120,"code":7607,"language":2122,"meta":14,"style":14},"\u002F\u002F пошук у адмінці: ін'єкція через конкатенацію\n$orders = DB::select(\"SELECT * FROM orders WHERE email = '\" . $request->email . \"'\");\n\n\u002F\u002F правильно: прив'язка параметрів\n$orders = DB::select('SELECT * FROM orders WHERE email = ?', [$request->email]);\n",[386,7609,7610,7615,7674,7678,7683],{"__ignoreMap":14},[424,7611,7612],{"class":426,"line":427},[424,7613,7614],{"class":2129},"\u002F\u002F пошук у адмінці: ін'єкція через конкатенацію\n",[424,7616,7617,7620,7622,7625,7627,7630,7632,7635,7638,7640,7643,7646,7649,7652,7654,7657,7660,7662,7664,7667,7669,7672],{"class":426,"line":465},[424,7618,7619],{"class":430},"$orders ",[424,7621,442],{"class":651},[424,7623,7624],{"class":438}," DB",[424,7626,2143],{"class":651},[424,7628,7629],{"class":2146},"select",[424,7631,2173],{"class":430},[424,7633,7634],{"class":445},"\"",[424,7636,7637],{"class":651},"SELECT",[424,7639,2529],{"class":651},[424,7641,7642],{"class":651}," FROM",[424,7644,7645],{"class":445}," orders ",[424,7647,7648],{"class":651},"WHERE",[424,7650,7651],{"class":445}," email ",[424,7653,442],{"class":651},[424,7655,7656],{"class":445}," '\"",[424,7658,7659],{"class":651}," .",[424,7661,2164],{"class":430},[424,7663,2167],{"class":651},[424,7665,7666],{"class":430},"email ",[424,7668,727],{"class":651},[424,7670,7671],{"class":445}," \"'\"",[424,7673,2190],{"class":430},[424,7675,7676],{"class":426,"line":879},[424,7677,2196],{"emptyLinePlaceholder":933},[424,7679,7680],{"class":426,"line":2181},[424,7681,7682],{"class":2129},"\u002F\u002F правильно: прив'язка параметрів\n",[424,7684,7685,7687,7689,7691,7693,7695,7697,7700,7702,7704,7706,7708,7710,7712,7714,7717,7720,7722],{"class":426,"line":2187},[424,7686,7619],{"class":430},[424,7688,442],{"class":651},[424,7690,7624],{"class":438},[424,7692,2143],{"class":651},[424,7694,7629],{"class":2146},[424,7696,2173],{"class":430},[424,7698,7699],{"class":445},"'",[424,7701,7637],{"class":651},[424,7703,2529],{"class":651},[424,7705,7642],{"class":651},[424,7707,7645],{"class":445},[424,7709,7648],{"class":651},[424,7711,7651],{"class":445},[424,7713,442],{"class":651},[424,7715,7716],{"class":445}," ?'",[424,7718,7719],{"class":430},", [$request",[424,7721,2167],{"class":651},[424,7723,7724],{"class":430},"email]);\n",[137,7726,7727],{},"Окремо дивимося на персональні дані покупців: що зберігається, хто має доступ, чи є резервні копії та журналювання. Це не юридичний висновок, а технічна оцінка ризиків.",[291,7729,7731],{"id":7730},"продуктивність-і-база-даних","Продуктивність і база даних",[137,7733,7734],{},"Більшість повільних Laravel-сайтів страждають від кількох повторюваних проблем:",[256,7736,7737,7747,7753,7759,7765],{},[259,7738,7739,7742,7743,7746],{},[185,7740,7741],{},"N+1 запити."," Список із 50 товарів породжує 150 запитів до бази, бо зв'язки підвантажуються по одному. Лікується ",[386,7744,7745],{},"with()",", але спочатку це треба знайти.",[259,7748,7749,7752],{},[185,7750,7751],{},"Відсутні індекси"," на колонках, за якими фільтрують і сортують.",[259,7754,7755,7758],{},[185,7756,7757],{},"Важкі запити в кожному запиті сторінки:"," лічильники, підсумки, які можна кешувати.",[259,7760,7761,7764],{},[185,7762,7763],{},"Синхронна робота з зовнішніми API"," в основному потоці: Нова Пошта, платіжка, листи.",[259,7766,7767,7770],{},[185,7768,7769],{},"Відсутнє кешування"," конфігурації, маршрутів, результатів дорогих обчислень.",[137,7772,7773],{},"Ми вмикаємо журнал запитів на тестовому середовищі, проходимо ключові сценарії (каталог, картка товару, кошик, checkout) і фіксуємо кількість запитів та час відповіді. Для виявлення N+1 дуже допомагає заборона «лінивого» завантаження в нерелізному середовищі:",[416,7775,7777],{"className":2120,"code":7776,"language":2122,"meta":14,"style":14},"\u002F\u002F AppServiceProvider::boot()\nModel::preventLazyLoading(! app()->isProduction());\n",[386,7778,7779,7784],{"__ignoreMap":14},[424,7780,7781],{"class":426,"line":427},[424,7782,7783],{"class":2129},"\u002F\u002F AppServiceProvider::boot()\n",[424,7785,7786,7789,7791,7794,7796,7798,7801,7803,7805,7808],{"class":426,"line":465},[424,7787,7788],{"class":438},"Model",[424,7790,2143],{"class":651},[424,7792,7793],{"class":2146},"preventLazyLoading",[424,7795,2173],{"class":430},[424,7797,2208],{"class":651},[424,7799,7800],{"class":2146}," app",[424,7802,2228],{"class":430},[424,7804,2167],{"class":651},[424,7806,7807],{"class":2146},"isProduction",[424,7809,7810],{"class":430},"());\n",[137,7812,7813],{},"Після цього будь-яка неоптимальна вибірка падає з помилкою ще на розробці. У звіті ми показуємо до\u002Fпісля в цифрах, а не загальні слова про «оптимізацію».",[291,7815,7817],{"id":7816},"база-даних-і-дані","База даних і дані",[137,7819,7820,7821,7824,7825,7827],{},"Перевіряємо схему: чи відтворюється вона міграціями з нуля, чи є зовнішні ключі та обмеження унікальності, як зберігаються гроші (цілі числа в копійках або ",[386,7822,7823],{},"decimal",", але не ",[386,7826,4174],{},"), чи немає «сміттєвих» таблиць і дублікатів. Для магазину особливо важливі статуси замовлень, склад і ціни: тут помилки коштують грошей.",[291,7829,7831],{"id":7830},"залежності-й-підтримуваність","Залежності й підтримуваність",[137,7833,7834],{},"Версія PHP, версія Laravel, статус підтримки, пакети без оновлень кілька років. Ми не радимо «оновити все одразу», а будуємо реалістичний план: що критично (вразливості), що бажано, що можна відкласти.",[291,7836,7838],{"id":7837},"інфраструктура-й-процес-розгортання","Інфраструктура й процес розгортання",[256,7840,7841,7844,7847,7850,7853],{},[259,7842,7843],{},"Як проєкт розгортається: вручну по FTP чи автоматично з перевіркою тестів?",[259,7845,7846],{},"Чи є середовище стейджингу, відмінне від продакшену?",[259,7848,7849],{},"Резервні копії: чи їх хтось колись відновлював?",[259,7851,7852],{},"Моніторинг помилок і доступності: дізнаєтеся ви про збій від системи чи від клієнта?",[259,7854,7855],{},"Журнали та алерти.",[137,7857,7858],{},"Резервна копія, яку жодного разу не відновлювали, — гіпотеза, а не копія. Ми це перевіряємо в першу чергу.",[144,7860,7862],{"id":7861},"як-виглядає-результат-аудиту","Як виглядає результат аудиту",[137,7864,7865],{},"Хороший звіт відповідає на три питання: що не так, наскільки це критично і що робити першим. Ми структуруємо його так:",[152,7867,7868,7878],{},[155,7869,7870],{},[158,7871,7872,7875],{},[161,7873,7874],{},"Розділ",[161,7876,7877],{},"Зміст",[177,7879,7880,7888,7896,7904,7912,7920],{},[158,7881,7882,7885],{},[182,7883,7884],{},"Короткий висновок",[182,7886,7887],{},"1 сторінка для власника: загальний стан і головні ризики",[158,7889,7890,7893],{},[182,7891,7892],{},"Знахідки",[182,7894,7895],{},"Опис, де саме в коді, чому це проблема, як відтворити",[158,7897,7898,7901],{},[182,7899,7900],{},"Пріоритети",[182,7902,7903],{},"Критичне \u002F серйозне \u002F бажане, оцінка впливу на гроші й ризик",[158,7905,7906,7909],{},[182,7907,7908],{},"План виправлень",[182,7910,7911],{},"Послідовність робіт, орієнтовні трудозатрати, залежності",[158,7913,7914,7917],{},[182,7915,7916],{},"Швидкі перемоги",[182,7918,7919],{},"Що можна зробити за 1–2 дні з видимим ефектом",[158,7921,7922,7925],{},[182,7923,7924],{},"Рекомендації щодо процесу",[182,7926,7927],{},"Тести, CI, рев'ю, моніторинг",[137,7929,7930],{},"Ми не пишемо «код погано» чи «код добре». Кожна знахідка прив'язана до файлу чи сценарію, а пріоритет — до наслідків: «ця вразливість дозволяє переглядати чужі замовлення», «цей запит уповільнює каталог у п'ять разів».",[137,7932,7933],{},"Саме пріоритизація відрізняє корисний аудит від переліку зауважень на 80 сторінок. Власник бізнесу не зобов'язаний усе виправляти, але має знати, що саме горить, а що можна лишити.",[744,7935,7936],{},[137,7937,7938,7941,7942,727],{},[185,7939,7940],{},"Потрібен аудит вашого Laravel-проєкту?"," Ми перевіряємо архітектуру, безпеку й продуктивність і передаємо звіт із планом виправлень за 5–7 днів. Вартість — від 12 000 грн, деталі на сторінці ",[245,7943,7944],{"href":4460},"технічного аудиту коду",[144,7946,7948],{"id":7947},"скільки-це-коштує-і-скільки-триває","Скільки це коштує і скільки триває",[137,7950,7951,7952,7955],{},"Вартість залежить від розміру кодової бази, кількості інтеграцій та глибини перевірки. На сторінці ",[245,7953,7954],{"href":77},"тарифів"," технічний аудит Laravel-проєкту коштує 12 000–25 000 грн залежно від обсягу, термін — 5–7 днів. Точну суму ми називаємо після короткого огляду проєкту: розміру репозиторію, кількості моделей і маршрутів, наявності тестів.",[137,7957,7958],{},"Чинники, що збільшують обсяг:",[256,7960,7961,7964,7967,7970],{},[259,7962,7963],{},"велика кількість інтеграцій (оплата, доставка, CRM, 1С);",[259,7965,7966],{},"відсутність документації та тестів, доводиться розбиратися «з нуля»;",[259,7968,7969],{},"кілька застосунків (бекенд, фронтенд на Nuxt, мобільний клієнт);",[259,7971,7972],{},"стара версія фреймворку з нестандартними патчами.",[137,7974,7975,7976,7979],{},"Для консультації без повного аудиту є формат ",[245,7977,7978],{"href":34},"Tech Lead на годину",": 90 хвилин розмови, огляд архітектури та відповіді на конкретні питання.",[144,7981,7983],{"id":7982},"що-потрібно-підготувати-для-аудиту","Що потрібно підготувати для аудиту",[137,7985,7986],{},"Щоб аудит пройшов швидко й без зайвих пауз, надайте:",[299,7988,7989,7992,7995,7998,8001,8004],{},[259,7990,7991],{},"Доступ до репозиторію лише на читання (або архів коду).",[259,7993,7994],{},"Копію бази даних без персональних даних або доступ до тестового середовища.",[259,7996,7997],{},"Опис проєкту: що робить, хто користувачі, які сценарії найважливіші для бізнесу.",[259,7999,8000],{},"Перелік інтеграцій і зовнішніх сервісів.",[259,8002,8003],{},"Відомі проблеми: що повільно, що ламається, що лякає розробників.",[259,8005,8006],{},"Інформацію про інфраструктуру: хостинг, спосіб розгортання, моніторинг.",[137,8008,8009],{},"Секрети (ключі API, паролі) не потрібні: ми працюємо з знеособленими або тестовими значеннями. Підписати угоду про нерозголошення можна до отримання коду.",[144,8011,8013],{"id":8012},"що-робити-зі-звітом-далі","Що робити зі звітом далі",[137,8015,8016],{},"Після аудиту у вас є три шляхи:",[256,8018,8019,8025,8031],{},[259,8020,8021,8024],{},[185,8022,8023],{},"Виправити власними силами або силами поточної команди."," Звіт слугує технічним завданням.",[259,8026,8027,8030],{},[185,8028,8029],{},"Віддати виправлення нам."," Фікс-пакет рахується за ставками від $20–35 за годину за обсягом знайденого.",[259,8032,8033,8036,8037,727],{},[185,8034,8035],{},"Використати звіт як аргумент у розмові з підрядником"," або при виборі нового. Про це читайте в статті ",[245,8038,8039],{"href":781},"як обрати підрядника на розробку сайту",[137,8041,8042,8043,727],{},"Поширена помилка — спробувати виправити все одразу. Краще піти за пріоритетами: спочатку безпека й втрата грошей, потім продуктивність, потім структура коду. І кожне виправлення супроводжувати тестом, щоб не зламати суміжне. Якщо проєкт критичний для бізнесу, корисно підключити автоматичні перевірки: докладніше в статті про ",[245,8044,8045],{"href":1931},"ручне та автоматизоване тестування",[144,8047,8049],{"id":8048},"як-відрізнити-якісний-аудит-від-формального","Як відрізнити якісний аудит від формального",[137,8051,8052],{},"Ринок аудитів неоднорідний: від автоматичного звіту статичного аналізатора до глибокого розбору архітектури. Кілька ознак, що допоможуть оцінити пропозицію.",[256,8054,8055,8064,8070,8076,8082],{},[259,8056,8057,8060,8061,8063],{},[185,8058,8059],{},"Ручна перевірка, а не лише інструменти."," Статичні аналізатори (PHPStan, Larastan) і ",[386,8062,7598],{}," корисні, але вони не бачать бізнес-логіки. Якщо весь аудит — це роздрукований вивід інструментів, ви платите за те, що могли запустити самі.",[259,8065,8066,8069],{},[185,8067,8068],{},"Знахідки з прикладами."," Кожне зауваження має файл, рядок і пояснення наслідків. «Рекомендуємо покращити безпеку» — не знахідка.",[259,8071,8072,8075],{},[185,8073,8074],{},"Оцінка трудозатрат."," План виправлень без орієнтовних годин не допоможе запланувати бюджет.",[259,8077,8078,8081],{},[185,8079,8080],{},"Розмова з вами, а не лише з кодом."," Аудитор має запитати, що для бізнесу найважливіше: швидкість каталогу, надійність оплати чи простота змін. Від цього залежать пріоритети.",[259,8083,8084,8087],{},[185,8085,8086],{},"Чесні межі."," Хороший аудитор прямо каже, що не перевірялося: наприклад, навантажувальне тестування чи юридична відповідність обробки персональних даних.",[137,8089,8090],{},"Якщо аудит пропонують безкоштовно «в подарунок» до розробки, пам'ятайте про конфлікт інтересів: той, хто пише код, рідко об'єктивно оцінює власну роботу.",[144,8092,858],{"id":857},[137,8094,8095],{},"Технічний аудит коду — не про те, щоб «знайти винних». Це спосіб замінити відчуття «щось не так» на конкретний перелік проблем, ризиків і дій. Він потрібен, коли проєкт змінює власника чи команду, повільніє, дорожчає в розвитку або готується до зростання. Результат — звіт, який можна передати будь-якій команді й виконати поетапно.",[744,8097,8098],{},[137,8099,8100,8103,8104,8106,8107,8110],{},[185,8101,8102],{},"Хочете зрозуміти реальний стан вашого проєкту?"," Залиште ",[245,8105,872],{"href":17}," або напишіть нам на сторінці ",[245,8108,8109],{"href":83},"контактів",": подивимося на проєкт і скажемо, чи потрібен повний аудит, чи вистачить консультації.",[875,8112,8113],{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":14,"searchDepth":465,"depth":879,"links":8115},[8116,8117,8118,8126,8127,8128,8129,8130,8131],{"id":7202,"depth":465,"text":7203},{"id":7243,"depth":465,"text":7244},{"id":7297,"depth":465,"text":7298,"children":8119},[8120,8121,8122,8123,8124,8125],{"id":7301,"depth":879,"text":7302},{"id":5333,"depth":879,"text":5217},{"id":7730,"depth":879,"text":7731},{"id":7816,"depth":879,"text":7817},{"id":7830,"depth":879,"text":7831},{"id":7837,"depth":879,"text":7838},{"id":7861,"depth":465,"text":7862},{"id":7947,"depth":465,"text":7948},{"id":7982,"depth":465,"text":7983},{"id":8012,"depth":465,"text":8013},{"id":8048,"depth":465,"text":8049},{"id":857,"depth":465,"text":858},"audit.report.md",[8134,8136,8138,8140],{"marker":2008,"text":8135},"SQL-запит у циклі: 1 200 запитів",{"marker":910,"text":8137},"бізнес-логіка в контролері",{"marker":910,"text":8139},"залежності не оновлювались",{"marker":905,"text":8141},"міграції відтворюють схему БД","5 днів",[8144,8147,8150,8153],{"q":8145,"a":8146},"Що перевіряють під час технічного аудиту коду?","Архітектуру, безпеку, продуктивність, якість коду, залежності, тести та спосіб розгортання. У Laravel-проєкті дивляться на запити до бази, валідацію, права доступу й обробку помилок. Результатом є звіт із пріоритетами, а не просто перелік зауважень. Власник бачить, що горить зараз, а що можна безпечно відкласти.",{"q":8148,"a":8149},"Скільки коштує аудит коду Laravel-проєкту?","Технічний аудит Laravel-проєкту коштує 12 000–25 000 грн залежно від обсягу кодової бази, кількості інтеграцій і глибини перевірки. Точну суму називаємо після короткого огляду проєкту. Виправлення знайденого оплачується окремо за ставкою $20–35 за годину. Фінальну вартість ми погоджуємо з вами до початку робіт.",{"q":8151,"a":8152},"Скільки часу триває аудит коду?","Зазвичай 5–7 днів до передачі звіту з планом виправлень. Термін збільшують численні інтеграції, відсутність документації та тестів, кілька застосунків або застаріла версія фреймворку. Орієнтовний строк називаємо після огляду проєкту. Власник отримує звіт, у якому знахідки впорядковані за наслідками для бізнесу, тож рішення про виправлення можна ухвалювати одразу.",{"q":8154,"a":8155},"Що потрібно підготувати для аудиту коду?","Доступ до репозиторію лише на читання, знеособлену копію бази або тестове середовище, опис проєкту та інтеграцій і перелік відомих проблем. Паролі та ключі API не потрібні: працюємо з тестовими значеннями. Угоду про нерозголошення можна підписати до отримання коду.",{},"\u002Fuk\u002Fblog\u002Fshcho-take-tekhnichnyi-audyt-kodu",{"title":7191,"description":7196},"Технічний аудит коду: що перевіряють (архітектура, безпека, продуктивність), як виглядає звіт, коли замовляти і скільки це коштує — від 12 000 грн.","Що таке технічний аудит коду і коли він потрібен — Tochno.","shcho-take-tekhnichnyi-audyt-kodu","uk\u002Fblog\u002Fshcho-take-tekhnichnyi-audyt-kodu",[4530],"SVAn1nRZiDfKKbHfG_VQaDlF3q_aSW_vQsm5P8YvMjw",{"id":8166,"title":8167,"author":132,"body":8168,"cover":901,"coverFile":8703,"coverLines":8704,"coverStat":8712,"date":916,"description":8172,"excerpt":901,"extension":917,"faq":8713,"featured":931,"key":901,"meta":8726,"navigation":933,"path":8727,"readingTime":1483,"seo":8728,"seoDescription":8729,"seoTitle":8730,"slug":8731,"stem":8732,"tags":8733,"updated":1467,"__hash__":8734},"blog_uk\u002Fuk\u002Fblog\u002Fskilky-koshtuie-rozrobka-internet-mahazynu.md","Скільки коштує розробка інтернет-магазину у 2026: розбір кошторису",{"type":134,"value":8169,"toc":8688},[8170,8173,8180,8184,8187,8219,8222,8226,8229,8235,8244,8254,8257,8261,8264,8357,8360,8363,8369,8372,8377,8381,8384,8388,8391,8453,8456,8461,8464,8479,8483,8486,8525,8528,8532,8535,8573,8576,8606,8610,8613,8619,8625,8628,8632,8635,8658,8664,8668,8671,8674],[137,8171,8172],{},"Розробка інтернет-магазину у 2026 році коштує від кількох тисяч гривень на конструкторі до кількох сотень тисяч на кастомному рішенні. Для кастомного магазину на Laravel з каталогом, оплатою, Новою Поштою й тестуванням наш орієнтир такий: від 150 000 грн і орієнтовно 10–14 тижнів роботи. Нижче розбираємо, з чого складається ця сума, що її збільшує і що можна прибрати без шкоди для продажів.",[137,8174,8175,8176,8179],{},"Усі цифри нижче взяті з нашої ",[245,8177,8178],{"href":77},"сторінки цін"," і калькулятора, а де ми даємо оцінку, ми прямо про це пишемо. Реальний кошторис завжди залежить від вашого проєкту, тому розглядайте текст як карту, а не як прайс-лист.",[144,8181,8183],{"id":8182},"чому-скільки-коштує-магазин-не-має-однієї-відповіді","Чому «скільки коштує магазин» не має однієї відповіді",[137,8185,8186],{},"Питання схоже на «скільки коштує авто». Є велосипед, є вживаний седан, є кросовер з повним приводом, і всі вони «їздять». З магазинами так само. Вартість визначають п'ять речей.",[256,8188,8189,8195,8201,8207,8213],{},[259,8190,8191,8194],{},[185,8192,8193],{},"Платформа:"," конструктор, готова CMS, кастомна розробка.",[259,8196,8197,8200],{},[185,8198,8199],{},"Обсяг каталогу і складність товарів:"," 50 товарів без варіантів чи 5 000 з комбінаціями розмірів і кольорів.",[259,8202,8203,8206],{},[185,8204,8205],{},"Дизайн:"," шаблон, адаптація макета чи індивідуальний дизайн.",[259,8208,8209,8212],{},[185,8210,8211],{},"Інтеграції:"," оплата, доставка, CRM, облікова система, маркетплейси.",[259,8214,8215,8218],{},[185,8216,8217],{},"Якість і ризики:"," чи є тестування, автотести, моніторинг, гарантія.",[137,8220,8221],{},"Остання позиція найчастіше випадає з порівняння пропозицій. Дві пропозиції по 150 000 грн можуть відрізнятись так, що в одній магазин тестують на 12 пристроях, а в другій перший тест виконує ваш покупець.",[144,8223,8225],{"id":8224},"три-рівні-ціни-від-конструктора-до-кастому","Три рівні ціни: від конструктора до кастому",[137,8227,8228],{},"Спрощено ринок поділяється на три рівні. Підходи орієнтовні й не є чиїмось офіційним прайсом.",[137,8230,8231,8234],{},[185,8232,8233],{},"Конструктор (Shopify, Prom, Horoshop тощо)."," Старт швидкий, а початкові витрати малі. Ви платите щомісячну підписку, комісії й за платні розширення. Обмеження з'являються, коли потрібна нестандартна логіка: складні знижки, особливий розрахунок доставки, інтеграція з вашою обліковою системою.",[137,8236,8237,8240,8241,727],{},[185,8238,8239],{},"Готова CMS (OpenCart, WooCommerce, PrestaShop) із шаблоном."," Це середній шлях: ціна нижча за кастом, є екосистема модулів. Ціна прихована в доробках, оновленнях і підтримці модулів різних авторів. Детально це порівняння ми розбирали в статті ",[245,8242,8243],{"href":996},"Laravel чи OpenCart\u002FWordPress для магазину",[137,8245,8246,8249,8250,8253],{},[185,8247,8248],{},"Кастомна розробка (Laravel + Nuxt)."," Найвища початкова ціна й найбільша гнучкість: код належить вам, немає залежності від чужих модулів, легко додавати складну логіку. Це наш рівень: ",[245,8251,8252],{"href":28},"інтернет-магазин"," від 150 000 грн.",[137,8255,8256],{},"Правило вибору просте: якщо ваша бізнес-логіка вкладається в стандартні налаштування платформи, кастом це переплата. Якщо ви вже впираєтесь у обмеження або знаєте, що впретесь за рік, економія на старті обернеться дорожчою міграцією.",[144,8258,8260],{"id":8259},"з-чого-складається-кошторис-кастомного-магазину","З чого складається кошторис кастомного магазину",[137,8262,8263],{},"Нижче типовий розподіл бюджету. Відсотки наші орієнтовні, на конкретному проєкті вони зсуваються.",[152,8265,8266,8279],{},[155,8267,8268],{},[158,8269,8270,8273,8276],{},[161,8271,8272],{},"Стаття",[161,8274,8275],{},"Орієнтовна частка",[161,8277,8278],{},"Що входить",[177,8280,8281,8292,8302,8313,8324,8335,8346],{},[158,8282,8283,8286,8289],{},[182,8284,8285],{},"Аналітика й проєктування",[182,8287,8288],{},"8–12%",[182,8290,8291],{},"Бриф, структура каталогу, user flow, ТЗ",[158,8293,8294,8296,8299],{},[182,8295,793],{},[182,8297,8298],{},"15–20%",[182,8300,8301],{},"Прототипи, дизайн ключових сторінок, адаптив 375\u002F768\u002F1440, UI-кіт",[158,8303,8304,8307,8310],{},[182,8305,8306],{},"Розробка frontend",[182,8308,8309],{},"20–25%",[182,8311,8312],{},"Каталог, картка, кошик, checkout, акаунт",[158,8314,8315,8318,8321],{},[182,8316,8317],{},"Розробка backend і адмінка",[182,8319,8320],{},"25–30%",[182,8322,8323],{},"Модель товарів, замовлення, ролі, API, адмінка",[158,8325,8326,8329,8332],{},[182,8327,8328],{},"Інтеграції",[182,8330,8331],{},"8–15%",[182,8333,8334],{},"Оплата, доставка, CRM, листи",[158,8336,8337,8340,8343],{},[182,8338,8339],{},"QA і виправлення",[182,8341,8342],{},"10–15%",[182,8344,8345],{},"Ручне тестування, автотести checkout, виправлення",[158,8347,8348,8351,8354],{},[182,8349,8350],{},"Запуск і гарантія",[182,8352,8353],{},"3–5%",[182,8355,8356],{},"Деплой, редиректи, налаштування аналітики, 30 днів гарантії",[137,8358,8359],{},"Зверніть увагу на QA. Якщо в кошторисі тестування немає зовсім, це не економія, а відкладений платіж: ви заплатите виправленнями вже після запуску, коли кожен баг коштує продажів.",[291,8361,8285],{"id":8362},"аналітика-й-проєктування",[137,8364,8365,8366,8368],{},"Тут вирішується, що саме ми будуємо. Погана аналітика дає найдорожчі помилки, бо вони множаться на дизайн і код. На цьому етапі ми з'ясовуємо, скільки категорій, які атрибути у товарів, як рахуються знижки, які способи оплати й доставки потрібні, чи потрібен B2B-кабінет. Тому наш ",[245,8367,872],{"href":17}," докладний: він скорочує кількість сюрпризів у середині проєкту.",[291,8370,124],{"id":8371},"дизайн",[137,8373,8374,8375,727],{},"Індивідуальний дизайн дорожчий, але добре зроблений дизайн магазину впливає на конверсію напряму: від зрозумілого checkout до читабельної картки товару. Якщо у вас вже є брендбук, дизайн дешевшає. За нашим калькулятором, наявний брендбук знижує вартість приблизно на 7%, а готовий макет приблизно на 18%. Деталі про процес дивіться на сторінці ",[245,8376,793],{"href":792},[291,8378,8380],{"id":8379},"розробка","Розробка",[137,8382,8383],{},"Це найбільша стаття. На неї впливають кількість сутностей (товари, варіанти, бренди, відгуки, акції), складність правил цін і кількість ролей в адмінці. Пошук і фільтри на каталозі від 2 000 товарів теж потребують окремого рішення (повнотекстовий пошук, кеш фасетів), а не «чарівної кнопки».",[144,8385,8387],{"id":8386},"що-збільшує-ціну-додаткові-модулі","Що збільшує ціну: додаткові модулі",[137,8389,8390],{},"У нашому калькуляторі додаткові опції рахуються як відсоток від базової суми. Це зручна модель для оцінки.",[152,8392,8393,8403],{},[155,8394,8395],{},[158,8396,8397,8400],{},[161,8398,8399],{},"Опція",[161,8401,8402],{},"Збільшення вартості",[177,8404,8405,8413,8421,8429,8437,8445],{},[158,8406,8407,8410],{},[182,8408,8409],{},"Онлайн-оплата",[182,8411,8412],{},"близько +6%",[158,8414,8415,8418],{},[182,8416,8417],{},"Нова Пошта",[182,8419,8420],{},"близько +5%",[158,8422,8423,8426],{},[182,8424,8425],{},"CRM \u002F 1С",[182,8427,8428],{},"близько +12%",[158,8430,8431,8434],{},[182,8432,8433],{},"Друга мова",[182,8435,8436],{},"близько +10%",[158,8438,8439,8442],{},[182,8440,8441],{},"Автотести Playwright",[182,8443,8444],{},"близько +8%",[158,8446,8447,8450],{},[182,8448,8449],{},"Терміновий запуск",[182,8451,8452],{},"+25%",[137,8454,8455],{},"Приклад розрахунку. Беремо базу 150 000 грн. Додаємо оплату (+6%), Нову Пошту (+5%) і CRM (+12%): разом +23%, тобто приблизно 34 500 грн. Сума близько 184 500 грн. Це орієнтир, а не оферта: точну суму дає оцінка після брифу.",[137,8457,8458,8459,727],{},"Чому інтеграції дорогі? Тому, що вартість складається не лише з написання коду. Кожна зовнішня система додає документацію для вивчення, sandbox-середовище, обробку помилок (що робити, коли API не відповідає), повторні запити, логування й тестування в усіх станах. Проблемні місця таких інтеграцій ми описали в статті ",[245,8460,1700],{"href":1261},[137,8462,8463],{},"Терміновий запуск дорожчий через паралельну роботу кількох людей: потрібна додаткова координація, менше часу на перевірку й вища ціна помилки.",[744,8465,8466],{},[137,8467,8468,8471,8472,8474,8475,8478],{},[185,8469,8470],{},"Хочете побачити цифри для свого магазину?"," Скористайтесь калькулятором на сторінці ",[245,8473,4898],{"href":77},": чотири питання, і ви отримаєте вилку. Точну оцінку ми готуємо за 1 робочий день після ",[245,8476,8477],{"href":17},"брифу",", без зобов'язань.",[144,8480,8482],{"id":8481},"приховані-витрати-про-які-забувають","Приховані витрати, про які забувають",[137,8484,8485],{},"Окрім самої розробки, в бюджет магазину входять речі, яких немає в договорі розробника.",[256,8487,8488,8494,8500,8505,8514,8519],{},[259,8489,8490,8493],{},[185,8491,8492],{},"Хостинг і домен."," Для магазину з помірним трафіком це не великі гроші, але потрібен нормальний сервер, а не найдешевший спільний хостинг. Домен і акаунти мають бути на вас.",[259,8495,8496,8499],{},[185,8497,8498],{},"Платні сервіси:"," транзакційна пошта, SMS, CRM, пошукові сервіси. Комісії платіжних систем зазвичай у відсотках від обороту.",[259,8501,8502,8504],{},[185,8503,5278],{}," Фотографії, описи, характеристики товарів. Наповнення каталогу з 1 000 позицій забирає більше часу, ніж люди очікують.",[259,8506,8507,8510,8511,727],{},[185,8508,8509],{},"Підтримка."," Після запуску магазин живе: оновлення бібліотек, виправлення, нові акції, сезонні зміни. Наші пакети підтримки стартують від 8 000 грн на місяць, подробиці на сторінці ",[245,8512,8513],{"href":853},"підтримки",[259,8515,8516,8518],{},[185,8517,269],{}," Технічна база входить у розробку, але просування (тексти, посилання, робота з пошуковими запитами) окрема стаття.",[259,8520,8521,8524],{},[185,8522,8523],{},"Маркетинг."," Магазин без трафіку не продає. Бюджет реклами рахуйте окремо від розробки.",[137,8526,8527],{},"Безпечне правило: закладайте на перший рік 15–25% від вартості розробки на підтримку й доопрацювання. Це наша практична оцінка, а не стандарт.",[144,8529,8531],{"id":8530},"як-зменшити-бюджет-без-шкоди","Як зменшити бюджет без шкоди",[137,8533,8534],{},"Заощаджувати можна, і розумно. Ось що працює.",[299,8536,8537,8543,8549,8555,8561,8567],{},[259,8538,8539,8542],{},[185,8540,8541],{},"Почніть з MVP."," Запустіть з 3–4 ключовими сценаріями (каталог, кошик, оплата, доставка) і додавайте решту за даними. Складні модулі (програма лояльності, особистий кабінет з історією, B2B-ціни) чудово відкладаються на другий етап.",[259,8544,8545,8548],{},[185,8546,8547],{},"Приготуйте матеріали наперед."," Брендбук, фото й тексти до старту скорочують і терміни, і вартість.",[259,8550,8551,8554],{},[185,8552,8553],{},"Використайте стандартні рішення там, де вони достатні."," Не пишіть власну CRM, якщо вистачить існуючої з інтеграцією.",[259,8556,8557,8560],{},[185,8558,8559],{},"Оберіть меншу кількість інтеграцій на старті."," Один спосіб оплати й одна служба доставки замість п'яти.",[259,8562,8563,8566],{},[185,8564,8565],{},"Уникайте терміновості,"," якщо можливо: +25% це чутлива ціна за поспіх.",[259,8568,8569,8572],{},[185,8570,8571],{},"Погодьте обсяг письмово."," Нечіткий обсяг веде до нескінченних доробок.",[137,8574,8575],{},"А ось де економити не варто:",[256,8577,8578,8588,8594,8600],{},[259,8579,8580,8583,8584,8587],{},[185,8581,8582],{},"Тестування checkout і оплати."," Баг тут це втрачені гроші щодня. ",[245,8585,8586],{"href":2074},"Чек-лист з 60 пунктів"," допоможе проконтролювати результат, навіть якщо ви не технар.",[259,8589,8590,8593],{},[185,8591,8592],{},"Резервні копії й безпека."," Магазин без бекапів це лотерея.",[259,8595,8596,8599],{},[185,8597,8598],{},"Права на код."," Договір має чітко фіксувати, що код належить вам, а доступи до репозиторію й сервера у вас.",[259,8601,8602,8605],{},[185,8603,8604],{},"Документація й передача."," Інакше ви стаєте заручником одного розробника.",[144,8607,8609],{"id":8608},"два-умовні-сценарії-для-порівняння","Два умовні сценарії для порівняння",[137,8611,8612],{},"Щоб цифри не були абстрактними, розглянемо два гіпотетичні магазини. Це ілюстрації розрахунку, а не реальні проєкти клієнтів.",[137,8614,8615,8618],{},[185,8616,8617],{},"Сценарій А: невеликий магазин на старті."," До 100 товарів, індивідуальний дизайн, одна онлайн-оплата й Нова Пошта. База близько 150 000 грн, плюс оплата (+6%) і доставка (+5%): приблизно 166 500 грн. Термін: 8–10 тижнів. Це типовий вхід у кастомну розробку.",[137,8620,8621,8624],{},[185,8622,8623],{},"Сценарій Б: магазин із каталогом на кілька тисяч позицій."," 2 000–10 000 товарів, є брендбук, оплата, Нова Пошта, інтеграція з CRM і автотести checkout. База вища, бо каталог більший (за калькулятором діапазон для магазину 150 000–220 000 грн), знижка за готовий брендбук (близько 7%), а націнка за опції складає +31% (6% + 5% + 12% + 8%). Підсумкова оцінка легко виходить за 220 000 грн, а терміни ближче до 12 тижнів.",[137,8626,8627],{},"Різниця між сценаріями показує головне: ціну визначають не «сторінки», а обсяг даних, інтеграції й вимоги до якості. Тому оцінку без брифу варто сприймати лише як вилку.",[144,8629,8631],{"id":8630},"як-перевірити-кошторис-підрядника","Як перевірити кошторис підрядника",[137,8633,8634],{},"Коли вам надсилають три пропозиції з різною ціною, порівнюйте не суму, а склад. Запитайте кожного:",[256,8636,8637,8640,8643,8646,8649,8652,8655],{},[259,8638,8639],{},"Що саме входить у ціну, а що ні (дизайн, тексти, тестування, інтеграції, хостинг)?",[259,8641,8642],{},"Які припущення закладено: кількість товарів, сторінок, ролей, мов?",[259,8644,8645],{},"Чи є тестування й хто його проводить? Чи будуть автотести?",[259,8647,8648],{},"Який порядок оплати? У нас типова схема 30 \u002F 40 \u002F 30 за етапами, і вона прив'язує гроші до результату.",[259,8650,8651],{},"Хто володіє кодом, дизайном і доступами після завершення?",[259,8653,8654],{},"Скільки триває гарантія й що вона покриває?",[259,8656,8657],{},"Яка ставка на доробки поза обсягом? У нас погодинна ставка розробника від $20 до $35, залежно від рівня.",[137,8659,8660,8661,727],{},"Підозріло низька ціна зазвичай означає одне з трьох: в обсязі чогось бракує, економиться на тестуванні або проєкт піде на доробках, які оплачуються окремо. Більше запитань для вибору виконавця ми зібрали в статті ",[245,8662,8663],{"href":781},"Як обрати підрядника на розробку: 12 питань, які варто поставити",[144,8665,8667],{"id":8666},"підсумок-з-чим-іти-до-підрядника","Підсумок: з чим іти до підрядника",[137,8669,8670],{},"Реалістичний бюджет кастомного магазину у 2026 році починається від 150 000 грн, а з оплатою, Новою Поштою й CRM зазвичай виходить у діапазон 180 000–220 000 грн. Це наш орієнтир для проєкту середньої складності, а не гарантія на будь-який магазин.",[137,8672,8673],{},"Щоб отримати точну оцінку, підготуйте п'ять речей: приблизну кількість товарів, список інтеграцій, наявність дизайну чи брендбуку, бажаний термін і бюджетну межу. Із цим набором оцінка займає день, а не тиждень, і ви порівнюєте пропозиції на однакових умовах.",[744,8675,8676],{},[137,8677,8678,8681,8682,8684,8685,8687],{},[185,8679,8680],{},"Готові порахувати свій магазин?"," Заповніть ",[245,8683,872],{"href":17}," за 10–15 хвилин, і за 1 робочий день ми повернемось з вилкою цін, термінами й списком ризиків. Або перегляньте сторінку ",[245,8686,27],{"href":28},", щоб побачити, що входить у пакет.",{"title":14,"searchDepth":465,"depth":879,"links":8689},[8690,8691,8692,8697,8698,8699,8700,8701,8702],{"id":8182,"depth":465,"text":8183},{"id":8224,"depth":465,"text":8225},{"id":8259,"depth":465,"text":8260,"children":8693},[8694,8695,8696],{"id":8362,"depth":879,"text":8285},{"id":8371,"depth":879,"text":124},{"id":8379,"depth":879,"text":8380},{"id":8386,"depth":465,"text":8387},{"id":8481,"depth":465,"text":8482},{"id":8530,"depth":465,"text":8531},{"id":8608,"depth":465,"text":8609},{"id":8630,"depth":465,"text":8631},{"id":8666,"depth":465,"text":8667},"estimate.xlsx",[8705,8706,8708,8710],{"marker":913,"text":2002},{"marker":913,"text":8707},"оплата + Нова Пошта",{"marker":910,"text":8709},"CRM \u002F 1С: +12%",{"marker":905,"text":8711},"QA перед запуском","від 150 000 ₴",[8714,8717,8720,8723],{"q":8715,"a":8716},"Скільки коштує інтернет-магазин на замовлення у 2026 році?","Кастомний магазин у нас стартує від 150 000 грн і займає 10–14 тижнів. З оплатою, Новою Поштою та CRM сума зростає орієнтовно до 165 000–185 000 грн. Готові CMS і конструктори дешевші на старті, але мають обмеження.",{"q":8718,"a":8719},"Які приховані витрати є в розробці інтернет-магазину?","Хостинг і домен, ліцензії платних модулів, комісії платіжних систем, контент і фото, тестування, а також підтримка й оновлення після запуску. Їх варто закласти в бюджет заздалегідь. Підтримка у нас стартує від 8 000 грн на місяць.",{"q":8721,"a":8722},"Як зменшити бюджет магазину без шкоди для якості?","Запускайте з мінімальним набором функцій, відкладіть складні модулі та інтеграції на другий етап, використовуйте готові компоненти там, де вони не обмежують. Не економте на тестуванні й безпеці, бо виправляти їх після запуску дорожче. Так ви швидше вийдете на продажі й додаватимете функції вже на реальних даних.",{"q":8724,"a":8725},"Від чого залежить ціна розробки інтернет-магазину?","Від розміру каталогу, кількості інтеграцій (оплата, доставка, CRM, склад), складності дизайну, мов і термінів. Кожен додатковий модуль збільшує базу. Тому просіть детальний кошторис по етапах, а не одну загальну суму. Так легше порівнювати пропозиції різних підрядників між собою.",{},"\u002Fuk\u002Fblog\u002Fskilky-koshtuie-rozrobka-internet-mahazynu",{"title":8167,"description":8172},"Скільки коштує розробка інтернет-магазину у 2026: від 150 000 грн для кастомного рішення. З чого складається кошторис і де можна заощадити.","Скільки коштує розробка інтернет-магазину — Tochno.","skilky-koshtuie-rozrobka-internet-mahazynu","uk\u002Fblog\u002Fskilky-koshtuie-rozrobka-internet-mahazynu",[942],"vw3ojpEgu9xD-LYE812Gs-Sxn1TlyKKYLkf-IaTGNQA",{"id":8736,"title":1538,"author":132,"body":8737,"cover":901,"coverFile":9455,"coverLines":9456,"coverStat":9465,"date":916,"description":8741,"excerpt":901,"extension":917,"faq":9466,"featured":931,"key":901,"meta":9479,"navigation":933,"path":9480,"readingTime":1483,"seo":9481,"seoDescription":9482,"seoTitle":9483,"slug":9484,"stem":9485,"tags":9486,"updated":1467,"__hash__":9487},"blog_uk\u002Fuk\u002Fblog\u002Fyak-my-testuiemo-bah-report-i-test-keis.md",{"type":134,"value":8738,"toc":9432},[8739,8742,8745,8749,8752,8755,8775,8782,8786,8789,8793,8796,8804,8807,8811,8814,8831,8835,8838,8842,8845,8849,8852,8890,8893,8896,8922,8926,8929,8933,8936,9023,9026,9030,9062,9066,9069,9072,9153,9157,9203,9206,9210,9213,9240,9243,9247,9291,9296,9307,9311,9314,9328,9331,9335,9338,9370,9373,9377,9380,9401,9411,9413,9416,9421],[137,8740,8741],{},"Хороший баг-репорт дозволяє розробнику відтворити проблему за дві хвилини, не пишучи тестувальнику жодного уточнення. Хороший тест-кейс дозволяє будь-кому з команди пройти сценарій однаково і отримати порівнювану відповідь. Це дві базові речі, на яких тримається тестування сайтів, і саме за ними видно, чи працює QA, чи лише «клацає».",[137,8743,8744],{},"У цій статті ми показуємо наш підхід: структуру баг-репорту, структуру тест-кейсу, приклади на сценарії чекауту і те, як ми оцінюємо серйозність. Усі приклади нижче ілюстративні, складені для пояснення, і не належать конкретному клієнтові.",[144,8746,8748],{"id":8747},"навіщо-стандартизувати-баг-репорти","Навіщо стандартизувати баг-репорти",[137,8750,8751],{},"Погані баг-репорти коштують дорожче, ніж здається. Фраза «на мобільному не працює оплата» запускає ланцюжок: розробник питає, на якому пристрої, тестувальник відповідає наступного дня, розробник не може відтворити, ставить «не воспроизводится», тікет закривається, а баг лишається в продакшені.",[137,8753,8754],{},"Стандартний формат дає три речі:",[256,8756,8757,8763,8769],{},[259,8758,8759,8762],{},[185,8760,8761],{},"швидкість",": розробник одразу бачить, що робити, і не витрачає ранок на допит;",[259,8764,8765,8768],{},[185,8766,8767],{},"порівнянність",": десять багів у однаковій структурі легко відсортувати за впливом;",[259,8770,8771,8774],{},[185,8772,8773],{},"пам'ять",": через пів року можна знайти, що вже ламалося, і додати регресійний тест.",[137,8776,8777,8778,8781],{},"Саме тому в нашому ",[245,8779,8780],{"href":2730},"ручному тестуванні сайтів"," кожен баг у звіті має однакову форму і відео.",[144,8783,8785],{"id":8784},"анатомія-баг-репорту","Анатомія баг-репорту",[137,8787,8788],{},"Ось поля, які ми заповнюємо завжди.",[291,8790,8792],{"id":8791},"заголовок","Заголовок",[137,8794,8795],{},"Заголовок відповідає на три питання: де, що, за яких умов. Порівняйте:",[256,8797,8798,8801],{},[259,8799,8800],{},"Погано: «Не працює кошик».",[259,8802,8803],{},"Добре: «Кошик: після видалення товару купон залишається, і знижка рахується від старої суми».",[137,8805,8806],{},"Заголовок має бути зрозумілим без відкриття тікета, бо в списку розробник бачить лише його.",[291,8808,8810],{"id":8809},"середовище","Середовище",[137,8812,8813],{},"Без середовища баг може бути нерепродукованим. Фіксуємо:",[256,8815,8816,8819,8822,8825,8828],{},[259,8817,8818],{},"URL і версію збірки або дату деплою;",[259,8820,8821],{},"пристрій і ОС (iPhone 13, iOS 17.5; Windows 11);",[259,8823,8824],{},"браузер і версію;",[259,8826,8827],{},"роль користувача (гість, авторизований, адміністратор);",[259,8829,8830],{},"тестові дані (який товар, який купон, який метод оплати).",[291,8832,8834],{"id":8833},"кроки-відтворення","Кроки відтворення",[137,8836,8837],{},"Нумерований список, кожен крок одна дія. Не «оформити замовлення», а конкретні кліки. Кроки мають бути такими, щоб незнайома людина відтворила баг, не вгадуючи.",[291,8839,8841],{"id":8840},"очікуваний-і-фактичний-результат","Очікуваний і фактичний результат",[137,8843,8844],{},"Це два окремі рядки. Очікуваний результат спирається на вимоги або логіку («після видалення товару знижка перераховується»), фактичний описує те, що сталося. Так розробник одразу бачить розрив. Якщо очікувана поведінка суперечить документації, вказуйте джерело.",[291,8846,8848],{"id":8847},"серйозність-і-пріоритет","Серйозність і пріоритет",[137,8850,8851],{},"Це різні поняття, і їх плутають найчастіше.",[152,8853,8854,8866],{},[155,8855,8856],{},[158,8857,8858,8861,8863],{},[161,8859,8860],{},"Параметр",[161,8862,166],{},[161,8864,8865],{},"Хто визначає",[177,8867,8868,8879],{},[158,8869,8870,8873,8876],{},[182,8871,8872],{},"Серйозність (severity)",[182,8874,8875],{},"наскільки баг ламає продукт технічно",[182,8877,8878],{},"QA",[158,8880,8881,8884,8887],{},[182,8882,8883],{},"Пріоритет (priority)",[182,8885,8886],{},"як швидко це треба виправити з погляду бізнесу",[182,8888,8889],{},"замовник, продакт",[137,8891,8892],{},"Баг із друкарською помилкою в логотипі на головній має низьку серйозність, але може мати високий пріоритет. Баг, що ламається лише на Internet Explorer 11, може мати високу серйозність, але нульовий пріоритет, бо трафіку з цього браузера немає.",[137,8894,8895],{},"Наша шкала серйозності:",[256,8897,8898,8904,8910,8916],{},[259,8899,8900,8903],{},[185,8901,8902],{},"S1 (критична)",": блокує основний сценарій, втрата грошей або даних. Приклад: оплата не проходить.",[259,8905,8906,8909],{},[185,8907,8908],{},"S2 (висока)",": основний сценарій працює, але з помітним спотворенням. Приклад: неправильна сума знижки.",[259,8911,8912,8915],{},[185,8913,8914],{},"S3 (середня)",": є обхідний шлях. Приклад: фільтр скидається при поверненні назад.",[259,8917,8918,8921],{},[185,8919,8920],{},"S4 (низька)",": косметика, дрібниці UI.",[291,8923,8925],{"id":8924},"докази","Докази",[137,8927,8928],{},"Скриншот із виділеною проблемою, відео запису екрана (для динамічних багів воно майже обов'язкове), логи консолі та мережі, якщо є. Відео економить десятки повідомлень у переписці. Для мобільних багів корисно, щоб на записі було видно індикатори пристрою.",[144,8930,8932],{"id":8931},"приклад-баг-репорту","Приклад баг-репорту",[137,8934,8935],{},"Нижче типовий баг, який ми знаходимо в магазинах. Продукт і числа вигадані для ілюстрації.",[744,8937,8938,8943,8957,8963,8973,8978,8995,9001,9007,9017],{},[137,8939,8940],{},[185,8941,8942],{},"BUG-017. Кошик: після видалення товару купон залишається, і знижка рахується від старої суми",[137,8944,8945,8948,8949,8952,8953,8956],{},[185,8946,8947],{},"Серйозність:"," S2. ",[185,8950,8951],{},"Пріоритет:"," P1. ",[185,8954,8955],{},"Статус:"," новий.",[137,8958,8959,8962],{},[185,8960,8961],{},"Середовище:"," staging, збірка від 2026-10-01, Chrome 129 \u002F Windows 11 і Safari \u002F iPhone 13 (iOS 17.5). Роль: гість.",[137,8964,8965,8968,8969,8972],{},[185,8966,8967],{},"Передумови:"," у каталозі є товар A (1 000 грн) і товар B (500 грн). Діє купон ",[386,8970,8971],{},"SALE10"," (знижка 10% на замовлення від 1 200 грн).",[137,8974,8975],{},[185,8976,8977],{},"Кроки:",[299,8979,8980,8983,8989,8992],{},[259,8981,8982],{},"Додати в кошик товар A і товар B (сума 1 500 грн).",[259,8984,8985,8986,8988],{},"Застосувати купон ",[386,8987,8971],{},". Підсумок: 1 350 грн.",[259,8990,8991],{},"Видалити з кошика товар A.",[259,8993,8994],{},"Подивитися підсумок.",[137,8996,8997,9000],{},[185,8998,8999],{},"Очікуваний результат:"," залишився товар B на 500 грн. Купон не діє (мінімум 1 200 грн), підсумок 500 грн, користувач бачить повідомлення, що купон скасовано.",[137,9002,9003,9006],{},[185,9004,9005],{},"Фактичний результат:"," підсумок 450 грн, купон залишається застосованим. При оформленні замовлення сума 450 грн.",[137,9008,9009,9012,9013,9016],{},[185,9010,9011],{},"Відтворюваність:"," 3 з 3 спроб. Докази: відео ",[386,9014,9015],{},"bug-017.mp4",", скриншот кошика.",[137,9018,9019,9022],{},[185,9020,9021],{},"Примітка:"," схожий баг можливий при зміні кількості товару через «мінус».",[137,9024,9025],{},"Зверніть увагу на деталі: передумови описані (інакше розробник не знайде потрібний купон), є примітка про сусідній сценарій, а відтворюваність вказана числом. Це не бюрократія, це економія часу двох людей.",[291,9027,9029],{"id":9028},"типові-помилки-в-баг-репортах","Типові помилки в баг-репортах",[256,9031,9032,9038,9044,9050,9056],{},[259,9033,9034,9037],{},[185,9035,9036],{},"Кілька багів в одному тікеті."," Розробник виправить один, а тікет закриє. Один баг, один тікет.",[259,9039,9040,9043],{},[185,9041,9042],{},"Оцінка замість факту."," «Жахливо працює пошук». Факт: «пошук за словом \"куртка\" повертає 0 результатів, хоча товарів 14».",[259,9045,9046,9049],{},[185,9047,9048],{},"Відсутність очікуваного результату."," Без нього тікет стає питанням смаку.",[259,9051,9052,9055],{},[185,9053,9054],{},"Баг у чужому середовищі."," Перевірте, що проблема не в розширенні браузера й не в кеші, перш ніж писати репорт.",[259,9057,9058,9061],{},[185,9059,9060],{},"Закритий тікет без перевірки."," «Виправлено» має означати «QA повторив кроки й підтвердив».",[144,9063,9065],{"id":9064},"анатомія-тест-кейсу","Анатомія тест-кейсу",[137,9067,9068],{},"Баг-репорт фіксує знайдену проблему, а тест-кейс описує, що саме ми перевіряємо, ще до знаходження будь-яких проблем. Це інструмент повторюваності: той самий сценарій можна пройти перед кожним релізом.",[137,9070,9071],{},"Поля тест-кейсу:",[152,9073,9074,9084],{},[155,9075,9076],{},[158,9077,9078,9081],{},[161,9079,9080],{},"Поле",[161,9082,9083],{},"Що пишемо",[177,9085,9086,9097,9105,9113,9121,9129,9137,9145],{},[158,9087,9088,9091],{},[182,9089,9090],{},"ID",[182,9092,9093,9094],{},"унікальний код, наприклад ",[386,9095,9096],{},"CHK-004",[158,9098,9099,9102],{},[182,9100,9101],{},"Назва",[182,9103,9104],{},"коротко, що перевіряється",[158,9106,9107,9110],{},[182,9108,9109],{},"Передумови",[182,9111,9112],{},"стан системи, тестові дані, роль",[158,9114,9115,9118],{},[182,9116,9117],{},"Кроки",[182,9119,9120],{},"нумерований список дій",[158,9122,9123,9126],{},[182,9124,9125],{},"Очікуваний результат",[182,9127,9128],{},"для кожного кроку або для сценарію",[158,9130,9131,9134],{},[182,9132,9133],{},"Пріоритет",[182,9135,9136],{},"як часто і наскільки критично запускати",[158,9138,9139,9142],{},[182,9140,9141],{},"Тип",[182,9143,9144],{},"позитивний, негативний, граничний",[158,9146,9147,9150],{},[182,9148,9149],{},"Статус",[182,9151,9152],{},"pass \u002F fail \u002F blocked \u002F not run",[291,9154,9156],{"id":9155},"приклад-тест-кейсу","Приклад тест-кейсу",[744,9158,9159,9164,9169,9174,9178,9198],{},[137,9160,9161],{},[185,9162,9163],{},"CHK-004. Оформлення замовлення гостем з оплатою карткою (позитивний сценарій)",[137,9165,9166,9168],{},[185,9167,8951],{}," високий (входить у smoke-набір).",[137,9170,9171,9173],{},[185,9172,8967],{}," товар у наявності, платіжний провайдер у sandbox-режимі, користувач не авторизований.",[137,9175,9176],{},[185,9177,8977],{},[299,9179,9180,9183,9186,9189,9192,9195],{},[259,9181,9182],{},"Відкрити картку товару, додати в кошик.",[259,9184,9185],{},"Перейти в кошик, натиснути «Оформити замовлення».",[259,9187,9188],{},"Заповнити контактні дані (ім'я, телефон, e-mail).",[259,9190,9191],{},"Обрати доставку Новою Поштою: місто, відділення.",[259,9193,9194],{},"Обрати оплату карткою, натиснути «Підтвердити».",[259,9196,9197],{},"Ввести тестову картку на сторінці платіжної системи.",[137,9199,9200,9202],{},[185,9201,8999],{}," після кроку 6 відкривається сторінка «Дякуємо», номер замовлення збігається з листом підтвердження, статус замовлення в адмінці «оплачено», залишок товару зменшився на 1.",[137,9204,9205],{},"Саме такий кейс входить у наш smoke-набір: короткий список із десятка сценаріїв, які проходять після кожного деплою за 15–20 хвилин. Якщо хоч один падає, реліз зупиняється.",[291,9207,9209],{"id":9208},"позитивні-негативні-та-граничні-кейси","Позитивні, негативні та граничні кейси",[137,9211,9212],{},"Для кожної функції ми складаємо мінімум три групи кейсів. Візьмемо поле «Телефон» у чекауті:",[256,9214,9215,9224,9234],{},[259,9216,9217,6285,9220,9223],{},[185,9218,9219],{},"Позитивний:",[386,9221,9222],{},"+380501234567"," приймається.",[259,9225,9226,9229,9230,9233],{},[185,9227,9228],{},"Негативний:"," літери, порожнє поле, номер без коду країни, SQL-подібний рядок (",[386,9231,9232],{},"' OR 1=1 --",") не ламають форму і не потрапляють у базу як код.",[259,9235,9236,9239],{},[185,9237,9238],{},"Граничний:"," 9 цифр, 10, 13, 14; пробіли на початку; вставка номера із дужками й дефісами.",[137,9241,9242],{},"Більшість реальних багів живе саме в негативних і граничних сценаріях, бо розробник за замовчуванням перевіряє те, що має працювати.",[144,9244,9246],{"id":9245},"від-тест-кейсу-до-результату-як-виглядає-наш-процес","Від тест-кейсу до результату: як виглядає наш процес",[299,9248,9249,9255,9261,9267,9273,9279,9285],{},[259,9250,9251,9254],{},[185,9252,9253],{},"Аналіз вимог."," Читаємо ТЗ, макети й сам сайт, шукаємо неоднозначності. Питання до замовника на цьому етапі коштують дешевше за баги.",[259,9256,9257,9260],{},[185,9258,9259],{},"Тест-план."," Фіксуємо, що тестуємо, що ні, на яких пристроях, яким браузером і за який час.",[259,9262,9263,9266],{},[185,9264,9265],{},"Тест-кейси."," Пишемо їх або беремо з нашого чек-листа інтернет-магазину (150+ пунктів), адаптуємо під проєкт.",[259,9268,9269,9272],{},[185,9270,9271],{},"Виконання."," Проходимо сценарії, фіксуємо результат. Паралельно проводимо дослідницьке тестування: вільні сценарії поза списком, де часто й знаходяться найцікавіші баги.",[259,9274,9275,9278],{},[185,9276,9277],{},"Баг-репорти."," Кожен баг одразу оформлюємо за шаблоном із відео.",[259,9280,9281,9284],{},[185,9282,9283],{},"Звіт."," Підсумок: що перевірено, що знайдено, розподіл за серйозністю, рекомендація «можна релізити чи ні».",[259,9286,9287,9290],{},[185,9288,9289],{},"Ре-тест."," Після виправлень перевіряємо кожен виправлений баг і прогоняємо регрес навколо нього.",[137,9292,9293,9294,727],{},"Окремо про регрес. Виправлення одного бага часто ламає сусідній функціонал, тому ми не обмежуємося перевіркою самого фіксу. Якщо сценарій ключовий, його варто винести в автотест: про те, коли це виправдано, ми писали в статті про ",[245,9295,8045],{"href":1931},[744,9297,9298],{},[137,9299,9300,9303,9304,727],{},[185,9301,9302],{},"Потрібен такий звіт для вашого сайту?"," Ми тестуємо вручну, фіксуємо кожен баг за шаблоном із відео й пріоритизуємо за впливом на гроші. ",[245,9305,9306],{"href":2730},"Дізнатися про ручне тестування",[144,9308,9310],{"id":9309},"як-ми-пріоритизуємо-знайдене","Як ми пріоритизуємо знайдене",[137,9312,9313],{},"Після тестування у звіті опиняється десятки багів, а бюджет на виправлення обмежений. Тому ми сортуємо їх не за порядком знаходження, а за впливом на гроші та довіру. Простий підхід, який працює на практиці:",[299,9315,9316,9319,9322,9325],{},[259,9317,9318],{},"Спочатку все, що блокує покупку: кошик, чекаут, оплата, доставка.",[259,9320,9321],{},"Далі баги, що псують дані: неправильні суми, дублі замовлень, втрачені листи.",[259,9323,9324],{},"Потім проблеми, що відштовхують клієнта: повільні сторінки, зламана мобільна версія, незрозумілі помилки форм.",[259,9326,9327],{},"В останню чергу косметика й дрібні неточності.",[137,9329,9330],{},"Так замовник одразу бачить, з чого почати, і може виправити 20% багів, які дають 80% проблем.",[144,9332,9334],{"id":9333},"інструменти-що-нам-потрібно-а-що-ні","Інструменти: що нам потрібно, а що ні",[137,9336,9337],{},"Не потрібна дорога система, щоб робити тестування якісно. Для малих команд достатньо:",[256,9339,9340,9346,9352,9358,9364],{},[259,9341,9342,9345],{},[185,9343,9344],{},"Баг-трекер:"," Jira, Linear, GitHub Issues або навіть Trello. Головне, щоб шаблон тікета був однаковим.",[259,9347,9348,9351],{},[185,9349,9350],{},"Тест-кейси:"," таблиця (Google Sheets) або TestRail-подібний інструмент. Для 30–60 кейсів таблиці вистачає.",[259,9353,9354,9357],{},[185,9355,9356],{},"Запис екрана:"," вбудований запис у macOS та iOS, Android; для десктопу OBS або Loom.",[259,9359,9360,9363],{},[185,9361,9362],{},"Інспектор:"," DevTools (вкладки Console і Network) для логів і запитів.",[259,9365,9366,9369],{},[185,9367,9368],{},"Емулятори й реальні пристрої:"," емуляція в DevTools корисна, але мобільні баги з Safari та клавіатурою краще перевіряти на реальних iPhone й Android.",[137,9371,9372],{},"Корисна звичка: у шаблоні тікета зробіть обов'язковими поля «Середовище» і «Очікуваний результат». Вони відсікають приблизно половину поганих репортів ще до того, як ті потраплять до розробника.",[144,9374,9376],{"id":9375},"як-оцінити-якість-звіту-від-qa","Як оцінити якість звіту від QA",[137,9378,9379],{},"Якщо ви замовляєте тестування і хочете зрозуміти, чи вам віддали якісну роботу, перевірте:",[256,9381,9382,9385,9388,9391,9398],{},[259,9383,9384],{},"чи кожен баг має кроки, очікуваний і фактичний результат та докази;",[259,9386,9387],{},"чи є розподіл за серйозністю, а не просто довгий список;",[259,9389,9390],{},"чи вказані середовища (пристрої, браузери, версія збірки);",[259,9392,9393,9394,9397],{},"чи є список того, що ",[185,9395,9396],{},"не"," перевірялося, і чому;",[259,9399,9400],{},"чи є висновок: готовий продукт до релізу чи ні.",[137,9402,9403,9404,9407,9408,727],{},"Звіт без останнього пункту неповний. Тестування існує, щоб допомогти ухвалити рішення, а не щоб створити кількість тікетів. Докладно про те, що саме перевіряємо в магазині, дивіться у ",[245,9405,9406],{"href":2074},"чек-листі з 60 пунктів",", а про одну з найболючіших груп багів у ",[245,9409,9410],{"href":1628},"статті про втрату замовлень на checkout",[144,9412,858],{"id":857},[137,9414,9415],{},"Баг-репорт і тест-кейс це не формальність, а спосіб робити тестування передбачуваним. Баг-репорт має відповісти на запитання «що, де, як відтворити, наскільки це погано», а тест-кейс «що і як ми перевіряємо кожного релізу». Якщо у вас їх немає, почніть із двох речей: єдиного шаблону тікета і smoke-набору на 10 сценаріїв.",[137,9417,9418,9419,1889],{},"Якщо хочете побачити, як це виглядає на вашому проєкті, є безкоштовний експрес-чек за 48 годин, а повний ",[245,9420,1324],{"href":31},[744,9422,9423],{},[137,9424,9425,9428,9429,727],{},[185,9426,9427],{},"Хочете почати з експрес-чека?"," Надішліть адресу сайту в брифі, і ми за 48 годин повернемо 10–15 ключових проблем з відео. ",[245,9430,9431],{"href":17},"Надіслати бриф",{"title":14,"searchDepth":465,"depth":879,"links":9433},[9434,9435,9443,9446,9450,9451,9452,9453,9454],{"id":8747,"depth":465,"text":8748},{"id":8784,"depth":465,"text":8785,"children":9436},[9437,9438,9439,9440,9441,9442],{"id":8791,"depth":879,"text":8792},{"id":8809,"depth":879,"text":8810},{"id":8833,"depth":879,"text":8834},{"id":8840,"depth":879,"text":8841},{"id":8847,"depth":879,"text":8848},{"id":8924,"depth":879,"text":8925},{"id":8931,"depth":465,"text":8932,"children":9444},[9445],{"id":9028,"depth":879,"text":9029},{"id":9064,"depth":465,"text":9065,"children":9447},[9448,9449],{"id":9155,"depth":879,"text":9156},{"id":9208,"depth":879,"text":9209},{"id":9245,"depth":465,"text":9246},{"id":9309,"depth":465,"text":9310},{"id":9333,"depth":465,"text":9334},{"id":9375,"depth":465,"text":9376},{"id":857,"depth":465,"text":858},"bug-report.template",[9457,9459,9461,9463],{"marker":2008,"text":9458},"купон не знімається при видаленні товару",{"marker":913,"text":9460},"кроки, очікуваний і фактичний результат",{"marker":910,"text":9462},"серйозність S2, пріоритет P1",{"marker":905,"text":9464},"відтворюється у 3 з 3 спроб","BUG-017",[9467,9470,9473,9476],{"q":9468,"a":9469},"Що має бути в хорошому баг-репорті?","Короткий заголовок, середовище, чіткі кроки відтворення, очікуваний і фактичний результат, пріоритет та скриншот або відео. Розробник повинен відтворити помилку без додаткових уточнень. Чим точніші кроки, тим швидше виправлення. Такий звіт також допомагає пізніше перевірити, що виправлення справді спрацювало, і не повертатися до помилки знову.",{"q":9471,"a":9472},"Чим тест-кейс відрізняється від баг-репорту?","Тест-кейс описує, що й як перевірити, ще до тестування, а баг-репорт фіксує знайдену невідповідність. Тест-кейс містить передумови, кроки й очікуваний результат, а баг-репорт додає фактичний. Один тест-кейс може породити кілька баг-репортів. Разом вони складають основу прозорого процесу тестування.",{"q":9474,"a":9475},"Як пріоритизувати знайдені баги?","За впливом на гроші й довіру клієнтів: спершу те, що блокує покупку (кошик, checkout, оплата), потім баги, що псують дані, далі проблеми, які відштовхують клієнта, і наприкінці косметика. Так замовник одразу бачить, з чого почати.",{"q":9477,"a":9478},"Які інструменти потрібні для баг-трекінгу?","Для малої команди достатньо трекера (Jira, Linear, GitHub Issues чи навіть Trello) і таблиці для тест-кейсів. Головне, щоб шаблон тікета був однаковим, а поля «Середовище» й «Очікуваний результат» були обов'язковими. Дорога система не потрібна. Для тест-кейсів на кілька десятків сценаріїв зазвичай вистачає таблиці.",{},"\u002Fuk\u002Fblog\u002Fyak-my-testuiemo-bah-report-i-test-keis",{"title":1538,"description":8741},"Як виглядає хороший баг-репорт і тест-кейс при тестуванні сайтів: шаблони, приклад для чекауту, рівні серйозності й типові помилки. З готовими зразками.","Баг-репорт і тест-кейс: приклад із практики — Tochno.","yak-my-testuiemo-bah-report-i-test-keis","uk\u002Fblog\u002Fyak-my-testuiemo-bah-report-i-test-keis",[2033],"Y-zME5w5zWucoxSXqAZ3KvR1p19B3CmKT5gG02ZZbw8",{"id":9489,"title":9490,"author":132,"body":9491,"cover":901,"coverFile":9955,"coverLines":9956,"coverStat":9965,"date":916,"description":9495,"excerpt":901,"extension":917,"faq":9966,"featured":931,"key":901,"meta":9979,"navigation":933,"path":9980,"readingTime":1483,"seo":9981,"seoDescription":9982,"seoTitle":9983,"slug":9984,"stem":9985,"tags":9986,"updated":1467,"__hash__":9987},"blog_uk\u002Fuk\u002Fblog\u002Fyak-obraty-pidriadnyka-na-rozrobku-saitu.md","Як обрати підрядника на розробку сайту: 12 питань, які варто поставити",{"type":134,"value":9492,"toc":9928},[9493,9496,9499,9503,9506,9509,9535,9538,9542,9546,9549,9553,9559,9562,9566,9569,9572,9576,9579,9583,9587,9590,9593,9597,9604,9607,9611,9614,9618,9622,9625,9635,9639,9645,9649,9652,9662,9666,9670,9673,9679,9683,9686,9715,9718,9722,9725,9763,9767,9770,9865,9868,9872,9875,9910,9913,9915,9918],[137,9494,9495],{},"Щоб обрати підрядника на розробку сайту або інтернет-магазину, не потрібно розбиратися в коді. Достатньо поставити 12 питань про процес, право на код, тестування, ціну та підтримку й уважно послухати, наскільки конкретно вам відповідають. Надійна команда відповідає цифрами, прикладами й документами; ненадійна — загальними фразами про «індивідуальний підхід».",[137,9497,9498],{},"Нижче — питання, які ми самі радимо ставити клієнтам, у тому числі нам. Тех-лід з одинадцятирічним досвідом у PHP і Laravel бачив достатньо проєктів, що зависли на півдорозі, щоб знати: проблеми починаються не з коду, а з нечітких домовленостей на старті.",[144,9500,9502],{"id":9501},"чому-вибір-підрядника-це-управління-ризиком","Чому вибір підрядника — це управління ризиком",[137,9504,9505],{},"Сайт чи магазин — не річ, яку можна повернути в магазин. Якщо підрядник зникне через пів року, ви залишитеся з частково написаним кодом, чужими доступами та втраченим часом. Тому вибір треба робити як управління ризиком: що саме може піти не так і що ви можете перевірити вже зараз.",[137,9507,9508],{},"Основні ризики типові:",[256,9510,9511,9517,9523,9529],{},[259,9512,9513,9516],{},[185,9514,9515],{},"Втрата контролю."," Код, домен, хостинг і сервіси оформлені на підрядника.",[259,9518,9519,9522],{},[185,9520,9521],{},"Роздутий бюджет."," Ціна на старті занижена, а далі кожна зміна — «додаткова робота».",[259,9524,9525,9528],{},[185,9526,9527],{},"Низька якість."," Сайт «працює на ноутбуці розробника», але ламається на телефонах або при оплаті.",[259,9530,9531,9534],{},[185,9532,9533],{},"Залежність від однієї людини."," Нікого, хто міг би підхопити проєкт, коли розробник захворів чи пішов.",[137,9536,9537],{},"Дванадцять питань нижче згруповані за цими ризиками. Ставте їх письмово — відповіді в листі легше порівнювати й потім цитувати.",[144,9539,9541],{"id":9540},"питання-про-результат-і-ціну","Питання про результат і ціну",[291,9543,9545],{"id":9544},"_1-що-саме-я-отримаю-на-кожному-етапі","1. Що саме я отримаю на кожному етапі?",[137,9547,9548],{},"Добра відповідь — список артефактів: структура сторінок, макети у Figma, робочий прототип, тестовий стенд, фінальний реліз. Погана — «спочатку дизайн, потім розробка». Кожен етап має закінчуватися чимось, що ви можете побачити й прийняти.",[291,9550,9552],{"id":9551},"_2-з-чого-складається-ціна-і-що-в-неї-не-входить","2. З чого складається ціна і що в неї не входить?",[137,9554,9555,9556,9558],{},"Попросіть розбивку по етапах або по функціях, а не одну цифру. Ми публікуємо стартові ціни відкрито на сторінці ",[245,9557,7954],{"href":77},": лендінг від 25 000 грн, корпоративний сайт від 60 000 грн, магазин від 150 000 грн. Точна вартість залежить від обсягу, дизайну, інтеграцій і термінів, і вона має пояснюватися, а не «залежати».",[137,9560,9561],{},"Окремо запитайте про речі, які зазвичай лишаються поза кошторисом: тексти й фото, платні ліцензії та шрифти, хостинг, домен, сторонні сервіси. Якщо вони не названі, ви дізнаєтеся про них у кінці.",[291,9563,9565],{"id":9564},"_3-як-рахуються-зміни-вимог","3. Як рахуються зміни вимог?",[137,9567,9568],{},"Зміни неминучі. Питання в тому, як із ними працюють: фіксована ціна з окремою оцінкою змін або погодинна робота з лімітом. Правильна відповідь — що кожна зміна спочатку оцінюється письмово, а ви погоджуєте її до початку роботи. Неправильна — «зробимо, потім розрахуємось».",[137,9570,9571],{},"Для порівняння: погодинні ставки в нашій команді відкриті — від $20 за годину для дизайнера до $32–35 для тех-ліда. Вам не обов'язково працювати погодинно, але ви маєте розуміти, з чого складається будь-яка цифра.",[291,9573,9575],{"id":9574},"_4-скільки-це-триватиме-і-що-впливає-на-термін","4. Скільки це триватиме і що впливає на термін?",[137,9577,9578],{},"Реалістичні орієнтири: лендінг — 2–3 тижні, корпоративний сайт — 5–7 тижнів, магазин — 10–14 тижнів. Якщо підрядник обіцяє магазин із оплатою, доставкою та CRM за два тижні, або він не врахував тестування, або не уявляє складності інтеграцій. Додайте до цього ваш час: затвердження макетів і контенту часто затягує проєкти більше, ніж розробка.",[144,9580,9582],{"id":9581},"питання-про-код-доступи-і-право-власності","Питання про код, доступи і право власності",[291,9584,9586],{"id":9585},"_5-кому-належить-код-і-чи-отримаю-я-доступ-до-репозиторію","5. Кому належить код і чи отримаю я доступ до репозиторію?",[137,9588,9589],{},"Єдина прийнятна відповідь: після оплати код і всі матеріали належать вам, а репозиторій від початку створений на вашому акаунті або передається вам. Якщо розробка йде в приватному репозиторії підрядника, а ви отримаєте «архів по завершенню» — це ризик: ви не бачите прогресу й не маєте гарантій.",[137,9591,9592],{},"Те саме стосується домену, хостингу, акаунтів у платіжних системах і аналітиці. Усе, що пов'язане з грошима й даними клієнтів, має бути зареєстроване на вас.",[291,9594,9596],{"id":9595},"_6-на-чому-будуватиметься-сайт-і-чому-саме-на-цьому","6. На чому будуватиметься сайт і чому саме на цьому?",[137,9598,9599,9600,9603],{},"Не для того, щоб перевірити знання термінів, а щоб почути аргументацію. Для магазину з нестандартною логікою, інтеграціями та власною адмінкою розумно звучить Laravel — ми розбираємо це детальніше в ",[245,9601,9602],{"href":996},"статті про вибір між Laravel, OpenCart і WordPress",". Для швидкого лендінгу або контентного сайту достатньо простіших рішень. Підозріло, якщо підрядник пропонує один і той самий стек для будь-якої задачі лише тому, що «ми так працюємо».",[137,9605,9606],{},"Окремо запитайте: чи легко буде іншій команді підхопити проєкт? Популярний стек, документація, структура коду за загальноприйнятими практиками — це страховка від залежності від одного виконавця.",[291,9608,9610],{"id":9609},"_7-чи-є-документація-і-що-буде-якщо-ви-припините-співпрацю","7. Чи є документація, і що буде, якщо ви припините співпрацю?",[137,9612,9613],{},"Мінімум — інструкція з розгортання, опис змінних середовища, схема бази даних і перелік інтеграцій. Запитайте напряму: «Якщо за рік ми вирішимо працювати з іншою командою, що ви передасте і за який час?» Хороший підрядник не ображається на це питання — він має готову відповідь.",[144,9615,9617],{"id":9616},"питання-про-якість-і-тестування","Питання про якість і тестування",[291,9619,9621],{"id":9620},"_8-хто-тестує-сайт-перед-запуском-і-як","8. Хто тестує сайт перед запуском і як?",[137,9623,9624],{},"Це питання відсіює найбільше. Типова відповідь слабкої команди: «розробники перевіряють самі». Розробник тестує те, що написав, так, як задумав. Незалежна перевірка шукає те, що ніхто не передбачив: порожній кошик, повторне натискання «Оформити», довге прізвище в формі, старий iPhone.",[137,9626,9627,9628,9630,9631,9634],{},"Просіть конкретику: чи є тест-план, які пристрої та браузери перевіряються, як фіксуються баги і скільки раундів виправлень включено в ціну. Для магазину перевірка checkout — окрема тема, ми описували типові помилки в ",[245,9629,9410],{"href":1628},". Якщо підрядник не має власного QA, ви можете замовити незалежне ",[245,9632,9633],{"href":2730},"тестування сайту"," окремо.",[291,9636,9638],{"id":9637},"_9-які-метрики-швидкості-та-доступності-ви-гарантуєте","9. Які метрики швидкості та доступності ви гарантуєте?",[137,9640,9641,9642,727],{},"Не «швидкий сайт», а вимірювані порогові значення: наприклад, Lighthouse на мобільному та показники Core Web Vitals. Запитайте, де і як ці цифри вимірюватимуться, і чи входять оптимізації в ціну. Як перевірити швидкість самостійно, ми пояснюємо в ",[245,9643,9644],{"href":1248},"статті про Core Web Vitals для власника магазину",[291,9646,9648],{"id":9647},"_10-як-ви-працюєте-з-seo-на-етапі-розробки","10. Як ви працюєте з SEO на етапі розробки?",[137,9650,9651],{},"SEO, додане «після запуску», майже завжди означає переробку. Запитайте, чи будуть унікальні title і description для кожної сторінки, canonical, структуровані дані, карта сайту, коректні редіректи зі старого сайту. Якщо у вас вже є сайт і ви мігруєте — редіректи зі старих адрес окреме питання, яке має бути в плані до початку розробки, а не після падіння трафіку.",[744,9653,9654],{},[137,9655,9656,9659,9660,727],{},[185,9657,9658],{},"Не впевнені у відповідях підрядника?"," За 90 хвилин консультації тех-лід розбере комерційну пропозицію й технічне завдання та скаже, які ризики бачить. Вартість — від 3 000 грн, деталі на сторінці ",[245,9661,33],{"href":34},[144,9663,9665],{"id":9664},"питання-про-процес-договір-і-підтримку","Питання про процес, договір і підтримку",[291,9667,9669],{"id":9668},"_11-як-виглядає-комунікація-і-хто-мій-контакт","11. Як виглядає комунікація, і хто мій контакт?",[137,9671,9672],{},"З'ясуйте до початку роботи: хто керує проєктом, як часто будуть звіти, де фіксуються завдання, як швидко відповідають на питання. Добра практика — регулярний короткий звіт (що зроблено, що в роботі, що блокує) і доступ до трекера завдань. Погана ознака — спілкування лише через менеджера, який передає питання «розробникам» і повертається за тиждень.",[137,9674,9675,9676,727],{},"Запитайте також, хто конкретно писатиме код. У студіях трапляється підміна: продає один спеціаліст, а працює інший, молодший. Ми працюємо відкрито: ви знаєте, хто тех-лід, хто QA і хто верстає, а процес описаний на сторінці ",[245,9677,9678],{"href":43},"«Процес»",[291,9680,9682],{"id":9681},"_12-що-в-договорі-оплаті-та-підтримці-після-запуску","12. Що в договорі, оплаті та підтримці після запуску?",[137,9684,9685],{},"Перевірте чотири пункти:",[299,9687,9688,9694,9700,9706],{},[259,9689,9690,9693],{},[185,9691,9692],{},"Офіційний договір"," із предметом, термінами, етапами і відповідальністю сторін.",[259,9695,9696,9699],{},[185,9697,9698],{},"Оплата етапами",", прив'язаними до приймання, а не до календаря. Наша схема — 30 \u002F 40 \u002F 30: передоплата, оплата після основної розробки та остаточний розрахунок після приймання.",[259,9701,9702,9705],{},[185,9703,9704],{},"Гарантійний період"," на виправлення дефектів. У нас — 30 днів після запуску.",[259,9707,9708,9711,9712,727],{},[185,9709,9710],{},"Підтримка після релізу",": що входить, скільки коштує, хто реагує на інциденти. Пакети підтримки розпочинаються від 8 000 грн на місяць, детальніше на сторінці ",[245,9713,9714],{"href":853},"підтримки сайтів",[137,9716,9717],{},"Дуже корисно прописати, що вважається прийняттям роботи: наприклад, відсутність критичних і серйозних дефектів зі списку тест-плану. Без цього «готово» означає різне для двох сторін.",[144,9719,9721],{"id":9720},"тривожні-сигнали-які-не-залежать-від-відповідей","Тривожні сигнали, які не залежать від відповідей",[137,9723,9724],{},"Іноді вже з поведінки підрядника на етапі переговорів видно, що буде далі. Звертайте увагу на такі ознаки:",[256,9726,9727,9733,9739,9745,9751,9757],{},[259,9728,9729,9732],{},[185,9730,9731],{},"Ціна без розбивки і без розмови про вимоги."," Якщо кошторис прийшов після п'ятихвилинного дзвінка — це ціна «з повітря».",[259,9734,9735,9738],{},[185,9736,9737],{},"Тиск часом."," «Знижка діє до п'ятниці» — майже завжди маркетинг, а не бізнес-логіка.",[259,9740,9741,9744],{},[185,9742,9743],{},"Відсутність питань до вас."," Хороший виконавець задає багато питань про аудиторію, процеси продажів, наявні системи. Якщо питань немає, він не збирається вникати.",[259,9746,9747,9750],{},[185,9748,9749],{},"Портфоліо без пояснень."," Скриншоти без опису задачі, ролі та результату. Попросіть показати, що саме робила команда і що змінилося для бізнесу.",[259,9752,9753,9756],{},[185,9754,9755],{},"Відмова показати приклади коду або процесу."," Не обов'язково публікувати чужий код, але розповісти про підхід має бути можливо.",[259,9758,9759,9762],{},[185,9760,9761],{},"Занадто низька ціна порівняно з ринком."," Якщо пропозиція вдвічі нижча за інші, десь прибрано тестування, дизайн або запас часу.",[144,9764,9766],{"id":9765},"як-порівнювати-пропозиції-на-практиці","Як порівнювати пропозиції на практиці",[137,9768,9769],{},"Збирайте щонайменше три пропозиції й зводьте їх у таблицю. Не порівнюйте лише підсумкову суму: порівнюйте склад.",[152,9771,9772,9787],{},[155,9773,9774],{},[158,9775,9776,9778,9781,9784],{},[161,9777,1051],{},[161,9779,9780],{},"Підрядник A",[161,9782,9783],{},"Підрядник B",[161,9785,9786],{},"Підрядник C",[177,9788,9789,9800,9811,9822,9833,9844,9854],{},[158,9790,9791,9794,9796,9798],{},[182,9792,9793],{},"Артефакти на етапах",[182,9795],{},[182,9797],{},[182,9799],{},[158,9801,9802,9805,9807,9809],{},[182,9803,9804],{},"Є незалежне тестування",[182,9806],{},[182,9808],{},[182,9810],{},[158,9812,9813,9816,9818,9820],{},[182,9814,9815],{},"Код і доступи на вас",[182,9817],{},[182,9819],{},[182,9821],{},[158,9823,9824,9827,9829,9831],{},[182,9825,9826],{},"Гарантія, підтримка",[182,9828],{},[182,9830],{},[182,9832],{},[158,9834,9835,9838,9840,9842],{},[182,9836,9837],{},"Метрики швидкості",[182,9839],{},[182,9841],{},[182,9843],{},[158,9845,9846,9848,9850,9852],{},[182,9847,9698],{},[182,9849],{},[182,9851],{},[182,9853],{},[158,9855,9856,9859,9861,9863],{},[182,9857,9858],{},"Ціна і що в неї не входить",[182,9860],{},[182,9862],{},[182,9864],{},[137,9866,9867],{},"Після заповнення стає видно, що дешевша пропозиція часто просто не містить рядків, які є в дорожчій. Якщо ви не впевнені, як оцінити технічні пункти, можна залучити зовнішнього спеціаліста на кілька годин: огляд пропозиції та технічного завдання коштує менше, ніж одна переробка.",[144,9869,9871],{"id":9870},"мініпроцес-вибору-за-тиждень","Мініпроцес вибору за тиждень",[137,9873,9874],{},"Щоб не розтягувати вибір на місяці, можна уклястися в п'ять кроків:",[299,9876,9877,9886,9892,9898,9904],{},[259,9878,9879,9882,9883,727],{},[185,9880,9881],{},"День 1."," Сформулюйте коротке завдання: мета, аудиторія, обов'язкові функції, інтеграції, бажаний термін і бюджетна вилка. Для цього зручно користуватися ",[245,9884,9885],{"href":17},"брифом",[259,9887,9888,9891],{},[185,9889,9890],{},"Дні 2–3."," Надішліть завдання 3–4 кандидатам і попросіть відповісти на 12 питань письмово.",[259,9893,9894,9897],{},[185,9895,9896],{},"День 4."," Проведіть короткі дзвінки: перевірте, наскільки люди розуміють вашу задачу.",[259,9899,9900,9903],{},[185,9901,9902],{},"День 5."," Зведіть пропозиції в таблицю, перегляньте договір.",[259,9905,9906,9909],{},[185,9907,9908],{},"Дні 6–7."," Попросіть невелику пробну роботу або оплачуваний дискавері-етап, перш ніж підписувати великий контракт.",[137,9911,9912],{},"Невеликий оплачуваний пілот — найкраща перевірка. За тиждень видно, як команда комунікує, дотримується термінів і реагує на зауваження.",[144,9914,858],{"id":857},[137,9916,9917],{},"Хороший підрядник не боїться жодного з цих 12 питань, бо в нього вже є відповіді: про артефакти, ціну, код, тестування, договір і підтримку. Погані відповіді не завжди означають нечесність, але вони означають ризик, який ви маєте усвідомлено прийняти або зняти до підписання договору.",[744,9919,9920],{},[137,9921,9922,8681,9925,9927],{},[185,9923,9924],{},"Хочете, щоб ми відповіли на ці 12 питань про ваш проєкт?",[245,9926,872],{"href":17}," — за 1 робочий день надішлемо оцінку з розбивкою по етапах, термінами та тим, що не входить у ціну.",{"title":14,"searchDepth":465,"depth":879,"links":9929},[9930,9931,9937,9942,9947,9951,9952,9953,9954],{"id":9501,"depth":465,"text":9502},{"id":9540,"depth":465,"text":9541,"children":9932},[9933,9934,9935,9936],{"id":9544,"depth":879,"text":9545},{"id":9551,"depth":879,"text":9552},{"id":9564,"depth":879,"text":9565},{"id":9574,"depth":879,"text":9575},{"id":9581,"depth":465,"text":9582,"children":9938},[9939,9940,9941],{"id":9585,"depth":879,"text":9586},{"id":9595,"depth":879,"text":9596},{"id":9609,"depth":879,"text":9610},{"id":9616,"depth":465,"text":9617,"children":9943},[9944,9945,9946],{"id":9620,"depth":879,"text":9621},{"id":9637,"depth":879,"text":9638},{"id":9647,"depth":879,"text":9648},{"id":9664,"depth":465,"text":9665,"children":9948},[9949,9950],{"id":9668,"depth":879,"text":9669},{"id":9681,"depth":879,"text":9682},{"id":9720,"depth":465,"text":9721},{"id":9765,"depth":465,"text":9766},{"id":9870,"depth":465,"text":9871},{"id":857,"depth":465,"text":858},"vendor.checklist",[9957,9959,9961,9963],{"marker":905,"text":9958},"код і доступи належать вам",{"marker":905,"text":9960},"етапи оплати прив'язані до приймання",{"marker":910,"text":9962},"«ціна залежить» без вилки",{"marker":2008,"text":9964},"немає тестування перед релізом","12\u002F12",[9967,9970,9973,9976],{"q":9968,"a":9969},"Як вибрати підрядника на розробку сайту?","Порівнюйте не лише ціну, а й результат, процес, доступи, тестування та підтримку. Просіть кошторис з розбивкою за етапами, умови передачі коду й доступів. Поставте всім підрядникам однакові питання та порівняйте відповіді письмово. Це допомагає порівнювати пропозиції об'єктивно, а не за враженням.",{"q":9971,"a":9972},"Які тривожні сигнали у підрядника на етапі переговорів?","Ціна без розбивки та розмови про вимоги, тиск часом, відсутність питань до вас, портфоліо без пояснень і відмова розповісти про підхід. Також насторожує пропозиція вдвічі нижча за інші: найімовірніше, прибрано тестування, дизайн або запас часу.",{"q":9974,"a":9975},"Чи варто обирати найдешевшу пропозицію на розробку сайту?","Зазвичай ні. Низька ціна часто означає, що в неї не входять тестування, підтримка чи частина функцій, які згодом оплачуються окремо. Порівнюйте склад робіт: дві пропозиції з однаковою сумою можуть містити зовсім різне. Це допомагає не переплатити пізніше за виправлення.",{"q":9977,"a":9978},"Скільки коштує розробка сайту в студії Tochno?","Лендінг від 25 000 грн (2–3 тижні), корпоративний сайт від 60 000 грн (5–7 тижнів), інтернет-магазин від 150 000 грн (10–14 тижнів), MVP від $5 000. Підтримка сайту стартує від 8 000 грн на місяць. Точну суму рахуємо після брифу.",{},"\u002Fuk\u002Fblog\u002Fyak-obraty-pidriadnyka-na-rozrobku-saitu",{"title":9490,"description":9495},"Як обрати підрядника на розробку сайту чи магазину: 12 питань про код, договір, тестування і ціну та сигнали, що мають вас насторожити.","Як обрати підрядника на розробку сайту — Tochno.","yak-obraty-pidriadnyka-na-rozrobku-saitu","uk\u002Fblog\u002Fyak-obraty-pidriadnyka-na-rozrobku-saitu",[942],"OG_TEG5iVWvDG8URXxFxMiLEkgrasnA-CA1RXmMhRco",1794139964169]