
🔒 Як обмежити доступ до кастомних типів записів WordPress: покрокове керівництво
Уявіть: ви запустили корпоративний портал на WordPress, завели кастомний тип записів «Обладнання» та наповнили його внутрішньою документацією. За тиждень з’ясовується, що всі ці сторінки спокійно індексуються пошуковиками й видимі будь-кому. Доступ має бути лише в авторизованих співробітників, а у вас, відкрито.
Штатні засоби WordPress не дають змоги точково закрити окремий кастомний тип записів від незареєстрованих користувачів. Ролі та можливості, так, але прив’язка «гість не бачить CPT X» з коробки відсутня. Рішення збирається з трьох компонентів: реєстрація CPT, налаштування ролей і плагін обмеження читання. Четвертий, опціональний,, соціальний вхід, щоб співробітники не вводили пароль щоразу.

Нижче, покроковий розбір кожного компонента з конкретними плагінами та налаштуваннями. Усі інструменти безплатні, доступні в офіційному каталозі WordPress.org і не потребують написання коду, хоча наприкінці розібрано й суто кодовий варіант для тих, хто хоче обійтися без плагінів.
💡 Швидкий огляд:
- Реєструємо кастомний тип записів через Custom Post Type UI, без жодного рядка коду
- Створюємо користувацьку роль у PublishPress Capabilities і призначаємо її співробітникам
- Закриваємо CPT від гостей плагіном WP Access Areas: неавторизований відвідувач отримує редірект на сторінку входу
- Опціонально підключаємо соціальну авторизацію через Super Socializer, вхід за Google-акаунтом без пароля
Крок 1: Реєстрація кастомного типу записів
Перший і найпростіший етап, створення самого CPT. Для цього не потрібно лізти у functions.php: плагін Custom Post Type UI на WordPress.org дає графічний інтерфейс для реєстрації будь-яких типів записів і таксономій.
Встановлення стандартне: «Плагіни → Додати новий», пошук за назвою, активувати. Після активації в бічному меню з’являється пункт «CPT UI → Add/Edit Post Types». Заповнюєте поля: slug (наприклад, equipment), множинна та однинна назва, мітки, і тиснете «Add Post Type».

Плагін сам викликає register_post_type() із правильними параметрами. Жодного ручного коду: на виході, готовий тип записів із підтримкою редактора, архівів і REST API. Якщо в майбутньому знадобиться перенести реєстрацію у functions.php, CPT UI показує згенерований PHP-код на вкладці «Tools».
На етапі реєстрації варто звернути увагу на дві критичні для безпеки опції. У блоці «Settings» CPT UI є прапорець «Publicly Queryable», він визначає, чи можна відкрити запис за прямим посиланням. За замовчуванням true, і навіть після обмеження читання через плагін цей параметр бажано залишати ввімкненим, інакше WordPress поверне 404 замість редіректу на сторінку входу, і користувач не зрозуміє, що сталося. Другий параметр, «Has Archive», вмикає сторінку архіву зі списком усіх записів CPT. Якщо архів не потрібен, вимкніть його, щоб пошуковики не проіндексували службову сторінку з прев’ю закритих документів.
Крок 2: Створення користувацької ролі
Просто закрити CPT від гостей недостатньо, потрібна роль, якій доступ буде відкрито. За замовчуванням WordPress дає фіксований набір: Administrator, Editor, Author, Contributor, Subscriber. Створювати нову роль будемо через плагін PublishPress Capabilities (раніше називався Capability Manager Enhanced, той самий слаг, та сама функціональність, ребрендинг).

Після активації переходимо в «Capabilities → Roles». У правій частині екрана, блок «Create New Role»:

Вводимо назву (наприклад, «Equipment Reader»), вибираємо базову роль для клонування (краще Subscriber, мінімум прав) і тиснемо «Create». Нова роль з’явилася, тепер її можна наповнити можливостями, для читання CPT достатньо стандартної зв’язки read + read_equipment (capability, яку зареєстрував CPT UI).
Призначте створену роль співробітникам, яким потрібен доступ до закритого контенту. Після цього плагін можна деактивувати, ролі та можливості залишаються в базі даних WordPress і не залежать від активного стану PublishPress Capabilities.

Шаг 3: Обмеження доступу до читання CPT
Ключовий крок. Плагін WP Access Areas дозволяє точково задати, хто читає, редагує та коментує записи кожного типу, аж до окремих сторінок. У нього скромні 400 активних встановлень і давно не було великих оновлень, але для задачі «закрити CPT від гостей» він працює передбачувано й без конфліктів.

Після встановлення переходимо в «Settings → Access Areas». У розділі «Default Behaviour» вибираємо:
«If not logged in, redirect to login. Otherwise redirect to the fallback page.»
Це налаштування надсилає неавторизованого користувача на wp-login.php у разі спроби відкрити будь-яку захищену сторінку CPT.

Далі, таблиця всіх зареєстрованих типів записів. Навпроти вашого CPT у стовпці «Reading» з випадного списку вибираємо «Logged in Users». Усе: з цього моменту будь-який гість, який перейшов за прямим посиланням на сторінку CPT, отримує редірект на форму авторизації.
Важливий нюанс: налаштування через таблицю діє лише на нові записи. Для вже створених сторінок потрібно вручну виставити права в бічній панелі редактора, там з’являється блок «Access Areas». Після налаштування обов’язково перевірте результат у режимі інкогніто браузера, відкривши пряме посилання на захищену сторінку CPT, ви повинні побачити wp-login.php, а не вміст.

Альтернативи WP Access Areas, якщо вам потрібне рішення з активнішою підтримкою: PublishPress Permissions (безплатна версія охоплює CPT і ролі) або ContentGate (легкий плагін із правилами на основі статусу входу та ролей).
Шаг 4: Соціальна авторизація (опціонально)
Постійно вводити логін і пароль на корпоративному порталі — це зайве тертя. Логічне рішення: вхід через Google-акаунт одним кліком. Плагін Super Socializer розв’язує цю задачу, 20 000+ активних установок, підтримка Google, Facebook, X (Twitter) та ще десятка провайдерів.

Після активації переходимо в «Super Socializer → Social Login»:

Базові налаштування: вмикаємо чекбокс «Вимкнути реєстрацію користувачів через соціальні мережі» — це важливо, щоб через соцмережі входили лише наявні облікові записи, а не створювалися нові. Далі обираємо провайдера (Google), вказуємо Client ID і Client Secret. Де їх узяти:
- Відкриваємо Google Cloud Console, створюємо проєкт (або обираємо наявний)
- У розділі «APIs & Services → Credentials» тиснемо «Create Credentials → OAuth client ID»
- Тип застосунку, Web application, у Authorized redirect URIs вставляємо URL колбеку з налаштувань Super Socializer
- Зберігаємо, отримуємо Client ID і Client Secret

Копіюємо ключі в поля плагіна:

Критичний момент: у полі Authorized redirect URIs не повинно бути слеша в кінці, інакше отримаєте помилку redirect_uri_mismatch. Після збереження на сторінці входу з’являється кнопка «Увійти через Google».
Важливо: в оригінальній версії допису (2020 рік) описувалася інтеграція з Google+, цей сервіс закрито з квітня 2019 року. Сучасний Super Socializer використовує стандартний протокол Google OAuth 2.0 через Google Identity Services. Інтерфейс Google Cloud Console відтоді оновився, але логіка кроків (проєкт → Credentials → OAuth client ID → redirect URI) залишилася незмінною.
Альтернативний підхід: усе на коді
Якщо зайві плагіни небажані, завдання можна вирішити у functions.php теми або дочірньої теми. Код реєструє CPT, створює роль і вішає перевірку авторизації на шаблон:
1 // Регистрация кастомного типа записей 2 function register_equipment_cpt() { 3 register_post_type('equipment', [ 4 'labels' => ['name' => 'Оборудование', 'singular_name' => 'Оборудование'], 5 'public' => true, 6 'has_archive' => true, 7 'supports' => ['title', 'editor', 'thumbnail'], 8 'capability_type' => 'equipment', 9 'map_meta_cap' => true, 10 ]); 11 } 12 add_action('init', 'register_equipment_cpt'); 13 14 // Создание роли при активации темы 15 function add_equipment_reader_role() { 16 add_role('equipment_reader', 'Equipment Reader', ['read' => true, 'read_equipment' => true]); 17 } 18 add_action('after_switch_theme', 'add_equipment_reader_role'); 19 20 // Редирект гостей с CPT на страницу входа 21 function restrict_equipment_to_logged_in() { 22 if (is_singular('equipment') && !is_user_logged_in()) { 23 wp_redirect(wp_login_url(get_permalink())); 24 exit; 25 } 26 } 27 add_action('template_redirect', 'restrict_equipment_to_logged_in');
Що робить цей код: перший блок реєструє CPT equipment із власним типом можливостей (capability_type). Другий, під час активації теми, створює роль Equipment Reader із правами читання цього CPT. Третій, на хуку template_redirect, перевіряє авторизацію та надсилає гостя на wp-login.php.
Плюс кодового підходу: нуль додаткових плагінів, повний контроль. Мінус: соціальний вхід однаково потребуватиме плагіна (OAuth-інтеграцію вручну писати довго й небезпечно), а кожна зміна ролей — це правка коду.
⁉️🤔 Часті запитання
Чи можна закрити CPT без плагінів, лише через functions.php?
Так. Звʼязка
register_post_type()+add_role()+ хукtemplate_redirectіз перевіркоюis_user_logged_in(), цілком робоче рішення. Код наведено в розділі вище. Соціальний вхід без плагіна реалізувати значно складніше: ручна OAuth-інтеграція потребує обробки токенів, стану та безпеки.
Чому WP Access Areas, а не новіший плагін на кшталт ContentGate?
WP Access Areas, мінімалістичний інструмент під конкретне завдання: «закрити тип записів від гостей». Він не тягне за собою конструктор правил, візуальні редактори та підписки. Якщо потрібна складніша логіка, наприклад, різні рівні доступу для різних ролей на одному CPT, беріть ContentGate або PublishPress Permissions, вони активно оновлюються. Для базового сценарію з цього посібника WP Access Areas достатньо.
Що робити, якщо після налаштування гості все ще бачать сторінки CPT?
Три типові причини. Перша: налаштування «Logged in Users» у таблиці WP Access Areas застосовується лише до нових записів, для старих сторінок потрібно виставити права вручну через бічну панель редактора. Друга: кеш-плагін віддає закешовану версію сторінки гостю, скиньте кеш і налаштуйте винятки для захищеного CPT. Третя: CPT зареєстрований із
'publicly_queryable' => trueі слаг збігається із загальнодоступною сторінкою, перевірте колізію.
Чи можна використовувати Super Socializer лише для входу, без шерінгу та коментарів?
Так, модулі плагіна незалежні. На вкладці «Social Sharing» зніміть усі галочки, кнопки «Поділитися» зникнуть. На вкладці «Social Commenting» вимкніть інтеграцію. Залиште тільки «Social Login» із потрібними провайдерами. Плагін легкий, вимкнення зайвих модулів не впливає на продуктивність.
Чи безпечно вимикати PublishPress Capabilities після створення ролі?
Так. Ролі та можливості WordPress зберігаються в таблиці
wp_options(опціяwp_user_roles) і не залежать від плагіна-творця. Після деактивації PublishPress Capabilities усі створені ролі та видані права зберігаються. Сам плагін можна активувати знову, якщо знадобиться змінити права.
Чи варто писати код, чи вистачить плагінів
Вибір між плагінами та functions.php зводиться до двох факторів: кількість захищених CPT і частота змін прав.
Якщо CPT один (як у прикладі з обладнанням), ролі стабільні й ви готові один раз написати 30 рядків коду, варіант із functions.php чистіший: не плодить плагіни, не залежить від сторонніх оновлень, повністю прозорий. Соціальний вхід можна залишити на Super Socializer, він вирішує вузьке завдання й не конфліктує з кастомним кодом.
Якщо CPT кілька, права часто переглядаються або сайтом керує не-розробник, беріть звʼязку плагінів. CPT UI + PublishPress Capabilities + WP Access Areas (або ContentGate) налаштовуються з адмінки за 15 хвилин і не потребують торкання коду. Плюс PublishPress Capabilities автоматично бекапить ролі за кожної зміни, відкотитися можна за два кліки.
У будь-якому сценарії дотримуйтеся принципу: один інструмент на одне завдання. Не ставте потужний комбайн заради однієї галочки й не пишіть велосипед, якщо готовий плагін робить точно те саме, але швидше й безпечніше.
Окремо варто продумати версіонування. Код із functions.php живе в репозиторії теми, зміни відстежуються через Git, і під час перенесення сайту ролі перестворяться автоматично на хуку after_switch_theme. Плагінний підхід такої прозорості не дає: ролі зберігаються в базі даних, і під час розгортання staging-копії або перенесення на новий домен їх потрібно відтворювати вручну або писати скрипт міграції. Цей фактор часто стає вирішальним на користь коду для команд, які практикують CI/CD і деплой через Git.



