WordPress 404 на записах: виправлення пермалінків без шкоди для SEO

Було корисно?

Головна сторінка завантажується. Адмінка працює. Але кожен запис повертає 404. Це не «WordPress такий WordPress». Це шар маршрутизації — правила перепису WordPress, конфігурація веб‑серверу, кеші або редиректи — які сперечаються про те, що означає цей URL.

І так, це інцидент у продакшні. Записи — це дохід, ліди та довіра. Виправити швидко — просто. Виправити правильно — без знищення SEO‑сигналів і без залишення шляху зламаних URL — ось що відокремлює швидку халтуру від ретельного розслідування.

Швидка діагностика — покроковий план

Якщо у вас є лише 15 хвилин до того, як хтось у паніці «просто поверне пермалінки назад», робіть це в порядку. Ви шукаєте найкоротший шлях до визначеності.

Перш за все: підтвердьте, який саме тип 404 ви отримуєте

  • Серверний 404 (Nginx/Apache): WordPress ніколи не запустився. Виправляйте маршрутизацію сервера.
  • WordPress 404 (шаблон 404 теми): PHP виконався, але WordPress не зміг зіставити запит із записом. Виправляйте правила перепису, структуру пермалінків, query vars або слаги в базі.
  • CDN/WAF кешований 404: Джерело може бути виправлене, але користувачі все ще бачать 404. Очищайте кеші та налаштовуйте правила кешування.

По‑друге: протестуйте один відомий URL запису наскрізь

Виберіть запис, який точно існує в базі даних. Не тестуйте «можливо» URL. Тестуйте реальність.

По‑третє: перевірте трубопровід перепису, а потім один раз скиньте правила (не 37 разів)

Якщо ви на Apache, перевірте mod_rewrite і права на .htaccess. Якщо на Nginx — перевірте секцію try_files. Потім акуратно скиньте правила перепису.

По‑четверте: якщо сайт переміщено або структура пермалінків змінена, сплануйте редиректи перед будь‑якими діями

Не «виправляйте» 404 сліпо змінюючи структуру пермалінків. Так ви перетворите локальну проблему маршрутизації у SEO‑перезапит індексації.

Що насправді означає 404 на записі WordPress

Термін «Post 404» приховує три різні відмови:

  1. Веб‑сервер не може відобразити URL як WordPress (чисті пермалінки вимагають правил перепису). Зазвичай це конфіг Apache/Nginx або відсутній .htaccess.
  2. WordPress отримав запит, але не може його розв’язати (правила перепису застаріли, структура пермалінків неправильна, відсутні теги перепису, конфлікт плагінів, некоректні siteurl/home, неправильні мовні префікси тощо).
  3. WordPress розв’язав запит, але щось інше перехоплює (редирект‑лупи, канонічні редиректи на мертві URL, кеш‑шари, WAF блокує або проксі спрямовує на невірний бекенд).

Виправлення залежить від того, який саме випадок. Помилка — вважати всі 404 однаково й одразу робити «flush permalinks». Інколи скидання допомагає, бо регенерує правила; інколи — нічого не змінює, бо сервер ніколи не передає запит WordPress; інколи — погіршує ситуацію, маскуючи невідповідність між старою й новою структурою URL.

Одна цитата, яку варто тримати в голові під час налагодження: Надія — не стратегія.Vince Lombardi

Це не цитата інженера‑надійності, але SRE‑мозок її миттєво розпізнає: вимірюй, перевіряй, потім змінюй.

Жарт №1: Скидання пермалінків — як перезавантаження принтера: часто працює, тож перетворюється на забобон, але не є планом.

Цікаві факти та історичний контекст (бо у цієї проблеми є передісторія)

  • Чисті пермалінки не завжди були «за замовчуванням». Ранні блого‑движки зазвичай використовували URL з query‑string, наприклад ?p=123. Чисті URL вимагали підтримки перепису на сервері.
  • WordPress покладається на те, що веб‑сервер «бреше» за нього. З увімкненими пермалінками веб‑сервер робить вигляд, що файлу не існує, і перекидає запит на index.php, де WordPress вирішує, який це пост.
  • .htaccess Apache зробив спільний хостинг дешевим — і крихким. WordPress став поширеним частково тому, що можна було керувати переписами без root‑доступу. Така гнучкість також легко ламала речі через права або відсутні модулі.
  • Nginx ніколи не підтримував .htaccess навмисно. Це рішення швидше й безпечніше, але при міграції з Apache на Nginx проблема пермалінків часто проявляється одразу.
  • Обробка 404 пошуковими системами еволюціонувала. Пошукові системи краще відсікають мертві URL і трактують нескінченні ланцюги редиректів як низькоякісні. Це підвищує вартість недбалих змін URL.
  • 301 vs 302 стали практичною SEO‑проблемою. «Постійні» редиректи (301) зазвичай передають сигнали надійніше, ніж тимчасові (302), хоча сучасні движки інтерпретують наміри. Проте: для переміщеного контенту використовуйте 301.
  • Система перепису WordPress зберігає правила в базі. Правила генеруються й зберігаються; вони можуть застаріти, якщо плагін змінив маршрути й потім був видалений.
  • Канонічні URL мають значення. WordPress намагатиметься перенаправити «майже правильні» URL на канонічні; якщо логіка каноніки вказує на неіснуючий шлях, ви можете створити самонанесені 404‑лупи.
  • CDN загальноприйнято кешують негативні відповіді. Кешування 404 може бути корисним, але коли 404 — випадкова помилка, ви вже розповсюдили баг глобально.

Практичні завдання: команди, виводи, що вони означають та що робити далі

Ці завдання написані як runbook для on‑call: ви виконуєте команду, інтерпретуєте вивід, приймаєте рішення. Використовуйте їх послідовно або переходьте до розділу, що відповідає вашому стеку.

Завдання 1: Перевірте, чи 404 походить від джерела чи від CDN

cr0x@server:~$ curl -sI https://example.com/2025/hello-world/ | sed -n '1,12p'
HTTP/2 404
date: Fri, 26 Dec 2025 10:22:11 GMT
content-type: text/html; charset=UTF-8
server: nginx
x-cache: HIT
cf-cache-status: HIT

Що це означає: Ви бачите 404, який ймовірно кешований (HIT). Якщо ви виправите джерело, але не очистите кеш — користувачі продовжуватимуть бачити помилку.

Рішення: Очистіть CDN‑кеш для репрезентативного URL після того, як перевірили джерело. Якщо не можете очистити — тимчасово встановіть короткий TTL для 404.

Завдання 2: Підтвердьте, чи виконався WordPress (WordPress 404 vs серверний 404)

cr0x@server:~$ curl -s https://example.com/2025/hello-world/ | grep -iE 'wp-content|wp-includes|rel="shortlink"|wp-json' | head
<link rel='shortlink' href='https://example.com/?p=123' />
<script src='https://example.com/wp-includes/js/jquery/jquery.min.js' id='jquery-core-js'></script>

Що це означає: Сторінку згенерував WordPress (навіть якщо це шаблон 404). Це вказує на проблеми з правилами перепису, невідповідністю пермалінків, відсутнім записом або канонічними редиректами — не на статичне маршрутизацію файлів.

Рішення: Перейдіть до перевірки правил перепису та інших перевірок на рівні WordPress.

Завдання 3: Перевірте, чи запис існує через WP‑CLI

cr0x@server:~$ cd /var/www/html
cr0x@server:~$ wp post list --post_type=post --name=hello-world --fields=ID,post_title,post_status,post_name --format=table
+-----+-------------+------------+------------+
| ID  | post_title  | post_status| post_name  |
+-----+-------------+------------+------------+
| 123 | Hello World | publish    | hello-world|
+-----+-------------+------------+------------+

Що це означає: Запис існує й опублікований. 404 пов’язаний з маршрутизацією, а не з видаленням контенту.

Рішення: Зосередьтеся на пермалінках/переписі/каноніках і конфігурації веб‑серверу.

Завдання 4: Перевірте поточну структуру пермалінків у WordPress

cr0x@server:~$ wp option get permalink_structure
/%year%/%postname%/

Що це означає: WordPress очікує URL типу /2025/hello-world/.

Рішення: Якщо ваші URL у продакшні відрізняються (наприклад, /blog/hello-world/), не здогадуйтеся — відновіть структуру або налаштуйте коректні редиректи.

Завдання 5: Перевірте розмір і наповненість правил перепису

cr0x@server:~$ wp rewrite list --format=table | head -n 12
+-------------------------------+------------------------------------------+----------------+
| match                         | query                                    | source         |
+-------------------------------+------------------------------------------+----------------+
| ^wp-json/?$                   | index.php?rest_route=/                   | rest-api       |
| ^wp-json/(.*)?                | index.php?rest_route=/$matches[1]        | rest-api       |
| ^([0-9]{4})/([^/]+)/?$        | index.php?year=$matches[1]&name=$matches[2] | post          |
| ^([0-9]{4})/page/([0-9]{1,})/?$ | index.php?year=$matches[1]&paged=$matches[2] | post        |

Що це означає: Правила перепису існують і містять патерни, що відповідають вашій структурі пермалінків.

Рішення: Якщо правила порожні або відсутні очікувані патерни — скиньте правила перепису і шукайте конфлікти плагінів або проблеми з записом.

Завдання 6: Безпечно скиньте правила перепису (CLI, один раз)

cr0x@server:~$ wp rewrite flush --hard
Success: Rewrite rules flushed.

Що це означає: WordPress регенерував правила і записав їх (або оновив власний кеш). На Apache опція «hard» намагається також оновити .htaccess.

Рішення: Повторно протестуйте невдалий URL. Якщо він все ще повертає 404 — проблема, ймовірно, в маршрутизації сервера (.htaccess ігнорується, неправильна конфігурація Nginx) або в канонічних редиректах.

Завдання 7: На Apache підтвердіть, що mod_rewrite увімкнено

cr0x@server:~$ apachectl -M 2>/dev/null | grep rewrite
 rewrite_module (shared)

Що це означає: Модуль перепису завантажений.

Рішення: Якщо його немає — увімкніть (залежно від пакета) і перезавантажте Apache; без нього чисті пермалінки 404ять.

Завдання 8: На Apache переконайтеся, що віртуальний хост дозволяє overrides (щоб .htaccess працював)

cr0x@server:~$ sudo apachectl -S 2>/dev/null | sed -n '1,40p'
VirtualHost configuration:
*:80                   example.com (/etc/apache2/sites-enabled/example.conf:1)
ServerRoot: "/etc/apache2"
cr0x@server:~$ sudo grep -R "AllowOverride" -n /etc/apache2/sites-enabled/example.conf
15:    AllowOverride None

Що це означає: AllowOverride None відключає .htaccess. WordPress може регенерувати правила скільки завгодно, але Apache їх ігноруватиме.

Рішення: Встановіть AllowOverride All (або щонайменше FileInfo) для документного кореня, перезавантажте Apache і повторіть тест. Або краще: перенесіть правила перепису в конфіг віртуального хоста для швидкості й прозорості.

Завдання 9: На Apache перевірте, що .htaccess існує і читабельний

cr0x@server:~$ ls -la /var/www/html/.htaccess
-rw-r--r-- 1 www-data www-data 612 Dec 26 10:10 /var/www/html/.htaccess

Що це означає: Файл існує і права виглядають нормальними.

Рішення: Якщо файл відсутній або належить root з жорсткими правами — виправте власника/права і знову скиньте правила перепису.

Завдання 10: На Nginx підтвердіть, що ви використовуєте сумісний з WordPress рядок try_files

cr0x@server:~$ sudo nginx -T 2>/dev/null | grep -n "try_files" | head
147:        try_files $uri $uri/ /index.php?$args;

Що це означає: Це канонічний рядок маршрутизації WordPress. Якщо його немає, пермалінки часто 404ять, бо Nginx шукає файл і повертає 404, якщо не знаходить.

Рішення: Якщо бачите щось на кшталт try_files $uri =404;, виправте блок location і перезавантажте Nginx.

Завдання 11: Переконайтеся, що PHP‑FPM доступний (іноді «404» маскує проблему з upstream)

cr0x@server:~$ systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled)
     Active: active (running)

Що це означає: PHP‑FPM працює; добре.

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

Завдання 12: Перевірте значення «home» і «siteurl» після міграцій

cr0x@server:~$ wp option get home
https://example.com
cr0x@server:~$ wp option get siteurl
https://example.com

Що це означає: Вони контролюють, як WordPress будує канонічні URL і внутрішні посилання. Неправильні значення можуть створювати редиректи на мертві хости або шляхи, що виглядає як 404 для користувачів.

Рішення: Якщо вони вказують на старий домен — виправте і очистіть кеші. Потім перевірте поведінку канонічних редиректів.

Завдання 13: Визначте, чи канонічні редиректи заважають

cr0x@server:~$ curl -sI https://example.com/2025/hello-world | sed -n '1,12p'
HTTP/2 301
date: Fri, 26 Dec 2025 10:23:01 GMT
location: https://example.com/2025/hello-world/

Що це означає: WordPress (або веб‑сервер) нормалізує слеш в кінці. Це нормально.

Рішення: Якщо заголовок Location вказує неправильно (старий домен, неправильний базовий шлях як /blog/) — виправте home/siteurl, структуру пермалінків або серверні редиректи.

Завдання 14: Підтвердьте, що запис відкривається за ID навіть якщо пермалінки не працюють

cr0x@server:~$ curl -sI "https://example.com/?p=123" | sed -n '1,12p'
HTTP/2 200
date: Fri, 26 Dec 2025 10:23:22 GMT
content-type: text/html; charset=UTF-8
server: nginx

Що це означає: WordPress може віддати запис. Контент в порядку. Роути «красивих» URL зламані.

Рішення: Тримайте сайт онлайн, тимчасово переключившись на «Plain» пермалінки, якщо дуже потрібно (короткостроково), але вам потрібні редиректи і ретельний план, щоб уникнути SEO‑шкоди. Краще: відремонтуйте переписи правильно.

Завдання 15: На Nginx знайдіть випадкове кешування тільки статичних відповідей, що повертає 404

cr0x@server:~$ sudo nginx -T 2>/dev/null | grep -n "location ~ \\\\.php" -n | head
162:    location ~ \.php$ {
cr0x@server:~$ sudo nginx -T 2>/dev/null | sed -n '150,190p'
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }

Що це означає: Базова маршрутизація коректна. Якщо ваша конфігурація замість цього мала блок location для /, який повертає 404 для невідомих шляхів, це зламає пермалінки.

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

Завдання 16: Перевірте редирект‑правила, які випадково «з’їдають» URL записів

cr0x@server:~$ sudo nginx -T 2>/dev/null | grep -n "return 301\|rewrite " | head -n 20
88:     return 301 https://example.com$request_uri;
205:    rewrite ^/blog/(.*)$ /$1 permanent;

Що це означає: У вас є правила перепису/редиректу. Перенаправлення /blog/ може бути коректним — або воно може зривати префікс і створювати 404, якщо WordPress налаштований інакше.

Рішення: Перевірте наміри редиректів відносно фактичної структури пермалінків і історичних URL. Не «чистіть» правила перепису під час інциденту, якщо вам не подобаються сюрпризи.

Завдання 17: Перегляньте сгенерований WordPress .htaccess (Apache)

cr0x@server:~$ sed -n '1,120p' /var/www/html/.htaccess
# BEGIN WordPress

RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

Що це означає: Це стандартний блок WordPress. Якщо він відсутній або пошкоджений — пермалінки 404ять.

Рішення: Відновіть блок WordPress (обережно, зберігаючи інші директиви), потім скиньте правила і повторіть тест.

Завдання 18: Перевірте логі сервера для невдалого URL

cr0x@server:~$ sudo tail -n 50 /var/log/nginx/access.log
203.0.113.10 - - [26/Dec/2025:10:24:01 +0000] "GET /2025/hello-world/ HTTP/2.0" 404 548 "-" "Mozilla/5.0"
cr0x@server:~$ sudo tail -n 80 /var/log/nginx/error.log
2025/12/26 10:24:01 [error] 12345#12345: *910 open() "/var/www/html/2025/hello-world/index.html" failed (2: No such file or directory), client: 203.0.113.10, server: example.com, request: "GET /2025/hello-world/ HTTP/2.0", host: "example.com"

Що це означає: Nginx намагався відкрити шлях до файлу (статичний) і не знайшов його, що свідчить, що він не перенаправив на index.php. Це класична ознака неправильно налаштованого try_files або конфліктного location.

Рішення: Виправте блок location / в Nginx і перезавантажте.

Кореневі причини за стеком: WordPress, Apache, Nginx, CDN

Причини на рівні WordPress (WordPress запускається, але все ще 404)

  • Застарілі правила перепису після змін плагінів/тем або міграцій. Виправлення: скиньте правила через WP‑CLI; підтвердіть, що структура пермалінків відповідає очікуваним URL.
  • Невідповідність структури пермалінків (сайт очікує /%postname%/, але посилання — /%year%/%postname%/). Виправлення: відновіть попередню структуру або імплементуйте редиректи, що зберігають старі URL.
  • Неправильні home / siteurl, що ведуть до канонічних редиректів на мертві шляхи/домени. Виправлення: виправте опції та перевірте редиректи.
  • Зміни slug-ів у кастомних типів записів. Виправлення: перереєструйте типи з узгодженими rewrite аргументами; скиньте правила; додайте редиректи для старих slug-ів.
  • Конфліктні плагіни, що підключаються до перепису, редиректів або канонікалізації. Виправлення: тимчасово вимкніть підозрілий плагін, підтвердіть маршрутизацію, потім налаштуйте.
  • Multisite / мовні плагіни, що додають префікси (/en/), які сервер не маршрутизує належним чином. Виправлення: переконайтеся, що серверні переписи пропускають префіксовані шляхи в WordPress.

Причини на Apache (чисті пермалінки залежать від перепису + overrides)

  • mod_rewrite не завантажений. Симптом: всі чисті пермалінки 404ять, але ?p=ID працює.
  • AllowOverride None забороняє .htaccess. WordPress «пише» правила, але Apache їх ігнорує.
  • Відсутній або пошкоджений .htaccess. Може статися під час деплоїв, жорсткого налаштування прав або побудов контейнерів.
  • Неправильний DocumentRoot (віртуальний хост вказує на іншу директорію), тож запити ніколи не доходять до WordPress інсталяції, що володіє базою.

Причини на Nginx (немає «запасного кола» .htaccess)

  • Відсутній рядок try_files ... /index.php?$args;. Це №1 причина, чому «пости 404ять» після міграції на Nginx.
  • Надмірні location‑блоки, що передчасно обрізають маршрутизацію (location / { try_files $uri =404; }), або регекс‑локації, що несподівано мають пріоритет.
  • Неправильні fastcgi параметри, що спричиняють дивну поведінку виконання PHP; іноді проявляється як «адмінка працює, а пости ні» залежно від маршрутів.

Причини на CDN / реверс‑проксі

  • Кешовані 404 відповіді (включаючи негативне кешування). Ви виправляєте джерело, але світ продовжує бачити стару відповідь.
  • Редирект‑правила на краю, що переписують шляхи (/blog/ — видалення або додавання) без налаштованого WordPress.
  • Невідповідність термінації HTTPS, коли WordPress думає, що він на HTTP; канонічні редиректи відскакують і можуть приводити користувачів на мертві варіанти.

Виправте пермалінки без шкоди для SEO

Операційна правда така: більшість «виправлень пермалінків WordPress» випадково змінюють URL. Змінювати URL не завжди погано. Але змінювати URL без плану редиректів — це непрофесійно.

Визначте, що саме ви намагаєтеся зробити

Люди плутають дві різні цілі:

  1. Відновити робочу маршрутизацію, не змінюючи публічних URL. Це ліквідація інциденту. SEO‑дружнє рішення.
  2. Навмисно змінити структуру URL. Це міграція/керована зміна. Потрібна мапа, редиректи й перевірка.

Якщо ви просто хочете, щоб пости перестали 404ити, ймовірно вам потрібна ціль №1.

Правило №1: спочатку відновіть стару структуру пермалінків

Якщо пости 404ять через те, що хтось змінив пермалінки, найбезпечніший SEO‑крок — відкотити структуру, яку вже знають пошукові системи. Потім можна планувати покращення URL, коли вас ніхто не кличе у паніці.

Операційно: це зменшує радіус ураження. SEO‑в сенсі: це зберігає неперервність індексованих URL, вхідних посилань і історичних метрик взаємодії.

Правило №2: коли потрібно змінювати URL, реалізуйте 301‑редиректи з односкочовою політикою

Чистий план редиректів виглядає так:

  • Старий URL → Новий URL (301), ровно один перехід.
  • Жоден старий URL не має редиректитись на проміжний URL, який потім редиректить далі.
  • Жоден редирект не має приводити на 404 або soft‑404 сторінку.

Ланцюги редиректів марнують бюджет обходу і ускладнюють відладку. Вони також накопичуються непомітно, доки хтось не перевірить.

Правило №3: зберігайте ідентичність контенту

Пошукові системи трактують URL як «вказівник ідентичності контенту». Якщо ви змінюєте URL, зберігайте інше стабільним:

  • Тіло контенту — не масово редагуйте під час зміни URL.
  • Титул і метадані — залишайте без змін, якщо нема вагомої причини.
  • Канонічні теги повинні вказувати на фінальний URL, а не на застарілі.

Правило №4: визначте, де живуть редиректи (і дотримуйтеся одного рівня)

Редиректи можна реалізувати в декількох місцях. Виберіть один основний рівень, щоб уникнути дублювання і лупів.

  • На веб‑сервері (Nginx/Apache): Швидко, надійно, підходить для простих патернів (наприклад, видалення /index.php/, зміни префіксу).
  • У WordPress (плагін або functions.php): Гнучко, але додає навантаження застосунку і може не спрацювати, якщо WordPress не виконується.
  • На CDN/edge: Дуже швидко й глобально, але легко некоректно налаштувати в масштабі. Також може приховувати поведінку джерела.

Мій упереджений дефолт: патерн‑редиректи на веб‑сервері, контент‑залежні редиректи в WordPress — лише коли це дійсно необхідно.

Правило №5: перевіряйте вибірково й за логами

Не перевіряйте міграцію URL трьома кліками і вважайте, що все добре. Перевіряйте за допомогою:

  • Вибірки старих URL (топові пости плюс випадкові довгі хвости).
  • Перевірок статусних кодів (очікуйте 301 потім 200).
  • Логів доступу: переконайтеся, що боти й користувачі потрапляють на 200, а не «перескакують» через редиректи.

Жарт №2: SEO — єдина дисципліна, де люди панікують через 302, як ніби це брешить безпека.

Типові помилки (симптом → коренева причина → фікс)

1) «Тільки пости 404, а сторінки працюють»

Симптом: /about/ працює, /2025/my-post/ 404ить.

Коренева причина: Структура пермалінків містить сегменти дати, а правила перепису згенеровано для іншої структури; або серверні переписи надто вузькі (наприклад, співпадають лише з верхньорівневими слагами).

Фікс: Підтвердіть permalink_structure; скиньте правила перепису; переконайтеся, що Nginx маршрутизує всі шляхи через index.php, якщо файл не існує.

2) «Адмінка працює, фронтенд постів 404»

Симптом: /wp-admin/ працює, але більшість публічних URL не працюють.

Коренева причина: Сервер дозволяє явні PHP‑ендпоїнти, але не «красиві» шляхи; відсутній try_files або Apache перепис.

Фікс: Виправте location / в Nginx або підтримку .htaccess на Apache; ізолюйте через ?p=ID.

3) «Після міграції з Apache на Nginx все 404»

Симптом: Сайт частково завантажується, але чисті URL не працюють.

Коренева причина: Очікували, що .htaccess перенесеться як є. Nginx його ігнорує.

Фікс: Додайте конфіг Nginx, дружній до WordPress, з try_files $uri $uri/ /index.php?$args; і правильним PHP‑блоком.

4) «Фікс спрацював для мене, але не для користувачів»

Симптом: Ви бачите 200; інші бачать 404.

Коренева причина: CDN кешує 404; розбіжність між кількома джерелами; або старі вузли кешу все ще віддають застарілий контент.

Фікс: Очистіть кеші краю для уражених шляхів; перевірте джерело напряму (обійдіть CDN, якщо можливо); забезпечте однакову конфігурацію на всіх оригіналах і правила перепису.

5) «Перемикання пермалінків на Plain фіксує проблему»

Симптом: /?p=123 працює; чисті URL — ні.

Коренева причина: Перепис не відбувається на рівні сервера.

Фікс: Не лишайте це на Plain як «рішення». Виправте перепис і поверніться до чистої структури, з редиректами якщо ви змінили публічні URL тимчасово.

6) «Після зміни структури пермалінків трафік падає і Search Console світиться»

Симптом: Багато 404 у звітах для старих URL.

Коренева причина: Зміна структури URL без редиректів; або редиректи є, але ланцюжать / зациклюються; або каноніки вказують неправильно.

Фікс: Реалізуйте 301‑мапу старі → нові; усуньте ланцюги; підтвердіть канонічні теги і sitemap; валідуйте через лог‑семпли.

Три корпоративні історії (анонімізовано, технічно реальні)

Історія 1: Інцидент через хибне припущення

Середня компанія мігрувала маркетинговий сайт WordPress з застарілого VM на Apache до керованої контейнерної платформи з фронтом на Nginx. Чеклист міграції включав експорт/імпорт БД, синхрон медіа і «перевірити, що wp‑admin працює». Він працював. Команда визнала задачу виконаною.

Понеділок вранці: відділ продажів каже «усі блоги поламались». Головна сторінка відкривалася, сторінки категорій були непослідовні, а окремі пости повертали 404. Інженер на чергуванні зробив класичний хід: скинув пермалінки через адмінку. Без змін. Потім знову. Паніка почалася.

Хибне припущення було тонким і поширеним: вони думали, що WordPress «володіє пермалінками». В Apache‑середовищі WordPress виглядає так, бо може писати .htaccess. У Nginx WordPress нічого не «володіє», якщо сервер не налаштований передавати невідомі шляхи на index.php.

Фікс — один рядок try_files в потрібному серверному блоці і перезавантаження. Пости одразу повернули 200. Постмортем‑задача була навіть важливіша: додати синтетичний тест для відомого URL запису (не головної) до гейтів деплою.

Герої не були потрібні. Потрібне було краще визначення «працює».

Історія 2: Оптимізація, що обернулася проти

Одна велика команда тримала сайт за CDN і реверс‑проксі. Хтось помітив високий відсоток кеш‑промахів і вирішив «оптимізувати», кешуючи 404 відповіді на краю з довгим TTL. Аргумент звучав раціонально: 404 часто від ботів, кешування знижує навантаження на джерело.

Потім редактор опублікував велику кампанію й поділився нею в соцмережах. Через кілька хвилин перша хвиля трафіку натрапила на коротке вікно, коли переписи були зламані на одному з origin‑вузлів (відставання конфіг‑деплою). CDN закешував 404 для того URL. Не на кілька секунд. На години.

Джерело виправили швидко, але інтернет продовжував бачити кешований 404. Тікети в службу підтримки посипались. Маркетинг вважав «фікс не спрацював», бо з їхньої перспективи — він не спрацював. SRE на чергуванні мусив простежити заголовки, щоб зрозуміти, що 404 — розподілений артефакт, а не поточна відповідь origin.

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

Вони вийшли на нюансовану політику: короткий TTL для 404, ніякого кешування для відомих шаблонів контенту як /%year%/%postname%/, і hook на очистку кешу при публікації для важливих шляхів.

Історія 3: Нудна, але правильна практика, що врятувала день

Велика організація мала кілька WordPress‑властивостей і колись постраждала від змін пермалінків. Тому вони впровадили нудну практику: кожен деплой включав набір curl‑синтетик з зовні мережі.

Не «сайт ап», а конкретні URL: відомий пост, відома сторінка, відома категорія і один старий URL, що повинен 301 на канонічне місце. Перевірки виконувалися як проти CDN, так і проти origin.

Під час рутинного апдейту шаблон конфігурації Nginx випадково прибрав рядок try_files для одного середовища. Деплой пройшов, heath checks були зелені (вони тестували лише /), але синтетичні перевірки впали миттєво на відомому пості. Rollback стався до того, як хтось це паблічно помітив.

Без драм. Без екстреної наради. Просто провалений гейт і тиха виправа. Ось як виглядає «надійність», коли вона працює: майже нудно і нецікаво.

Чеклісти / план дій крок за кроком

План A: Відновити робочі пермалінки з мінімальним SEO‑ризиком (рекомендовано при інцидентах)

  1. Визначте відомий ID поста за допомогою WP‑CLI (wp post list). Запишіть його.
  2. Протестуйте ?p=ID. Якщо це повертає 200, контент в порядку, а проблема — у переписі.
  3. Перевірте структуру пермалінків (wp option get permalink_structure). Підтвердіть, що вона відповідає історичним URL.
  4. Скиньте правила перепису один раз (wp rewrite flush --hard).
  5. Виправте серверну маршрутизацію:
    • Nginx: підтвердіть try_files $uri $uri/ /index.php?$args;
    • Apache: підтвердіть mod_rewrite, AllowOverride і блок WordPress в .htaccess
  6. Перевірте репрезентативний набір URL (топ‑10 постів плюс 10 випадкових старих постів). Використовуйте заголовки curl, не лише кліки в браузері.
  7. Очистіть CDN‑кеш для уражених шляхів після того, як джерело стало правильним.
  8. Моніторьте логи щодо частоти 404 і редиректів; переконайтеся, що боти бачать 200 для канонічних URL.

План B: Ви навмисно змінили пермалінки (міграція / запит на зміну)

  1. Застигніть цільову структуру пермалінків. Вирішіть один раз. Не «підганяйте» під час міграції.
  2. Експортуйте мапу URL:
    • Шаблони старих URL (попередня структура)
    • Шаблони нових URL (нова структура)
  3. Реалізуйте 301‑редиректи:
    • Віддавайте перевагу патерн‑правилам на Nginx/Apache де можливо
    • Використовуйте WordPress‑редиректи лише для винятків
  4. Оновіть внутрішні посилання, якщо потрібно (WordPress зазвичай генерує нові пермалінки автоматично; слідкуйте за жорстко вбудованими посиланнями в контенті).
  5. Перевірте канонічні теги, щоб вони вказували на нові URL і щоб старі URL редиректували на ті самі канонічні адреси.
  6. Валідуйте у масштабі за вибіркою та логами; шукайте ланцюги редиректів і кластери 404.
  7. Тримайте редиректи довго. «Довго» означає довше, ніж потрібно, щоб старі посилання й закладки згасли. Корпоративно: довше, ніж комусь хотілося б, але не вічно.

План C: Тимчасове стримування, коли не можна негайно виправити переписи

  1. Переключіть пермалінки на Plain (/?p=ID) лише в крайньому випадку і тільки тимчасово.
  2. Додайте банер в інцидентні нотатки: «Plain пермалінки ввімкнені; ризик для SEO; повернути після виправлення переписів.»
  3. Реалізуйте редиректи зі старих красивих URL на ?p=ID тільки якщо маєте надійну мапу (часто її немає). Інакше ви просто створите неправильні редиректи.
  4. Виправте переписи правильно, відновіть структуру пермалінків, потім приберіть тимчасові хакі.

FAQ

1) Чому пости 404ять, але головна сторінка завантажується?

Головна сторінка часто — /, яка може працювати навіть при зламаних переписах. Пости залежать від перепису, щоб напрямити /year/postname/ на index.php.

2) Чи безпечно натискати «Налаштування → Permalinks → Зберегти»?

Зазвичай так — це скидає правила перепису. Але якщо сервер ігнорує .htaccess (Overrides в Apache вимкнено) або ви на Nginx, це не виправить маршрутизацію. Розглядайте це як діагностичний крок, а не остаточне рішення.

3) Який найшвидший тест, щоб підтвердити проблему перепису?

Запросіть /?p=POST_ID. Якщо це повертає 200, а красивий URL 404ить — переписи зламані.

4) Чи варто переключатися на «Plain» пермалінки, щоб зупинити аврійний стан?

Тільки як тимчасовий захід. Це змінює публічні URL і може створити хаос для SEO, якщо не налаштувати редиректи. Краще виправляти механіку переписів.

5) Як виправити пермалінки на Nginx?

Переконайтесь, що в location / є try_files $uri $uri/ /index.php?$args; і що PHP‑запити передаються в PHP‑FPM. Потім перезавантажте Nginx і повторіть тест.

6) Як виправити пермалінки на Apache?

Переконайтесь, що mod_rewrite увімкнено, ваш vhost дозволяє overrides (AllowOverride) і в .htaccess присутній блок WordPress. Потім один раз скиньте правила перепису.

7) Чи шкодять редиректи SEO?

Редиректи — нормальна річ. Мертві URL гірші. Використовуйте 301 для постійних переміщень, уникайте ланцюгів і переконайтеся, що фінальний URL повертає 200 з очікуваним контентом.

8) Чому я все ще бачу 404 після виправлення конфігурації сервера?

Найчастіше: CDN кешував 404, кеш браузера, або ви виправили один origin, але не всі. Перевірте заголовки відповіді на наявність кеш‑хітів і порівняйте поведінку origin vs CDN.

9) Чи може плагін спричинити 404 на постах?

Так. SEO‑плагіни, мульти‑мовні плагіни, плагіни членства і кастомні типи записів можуть реєструвати правила перепису або редиректи. Тимчасово вимкніть підозрілий плагін, скиньте перепис і повторіть тест.

10) Як уникнути цього в майбутніх деплоях?

Додайте синтетичні перевірки для відомого URL поста і для відомого legacy‑редиректу. Застосуйте гейти деплою на основі цих перевірок. Також тримайте конфіг веб‑сервера під контролем версій і переглядайте правила перепису як код додатку.

Висновок: наступні кроки, які можна відправити сьогодні

Якщо пости WordPress 404ять — не починайте зі забобонів. Почніть з класифікації: серверний 404 vs WordPress 404 vs кешований 404. Потім доведіть, що контент існує через ?p=ID. Далі виправте шар маршрутизації — підтримку перепису в Apache або try_files в Nginx — і скиньте правила перепису один раз.

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

Практичні наступні кроки:

  1. Обрати один зламаний URL поста і виконати перевірку заголовків (Завдання 1 + Завдання 13).
  2. Підтвердити, що запис існує і ?p=ID повертає 200 (Завдання 3 + Завдання 14).
  3. Перевірити серверну маршрутизацію (try_files на Nginx або .htaccess/AllowOverride на Apache).
  4. Скинути правила перепису один раз, повторно протестувати, потім очистити CDN‑кеш.
  5. Додати гейт деплою: один відомий URL поста завжди має повертати 200.
← Попередня
MySQL vs MongoDB: помилка «NoSQL, бо модно», що вбиває продуктивність VPS
Наступна →
Docker + TLS: Let’s Encrypt в контейнерах і на хості — обирайте безпечний підхід

Залишити коментар