Інтеграція CMS Headless WordPress (WP REST API + фронтенд)

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Інтеграція CMS Headless WordPress (WP REST API + фронтенд)
Складна
від 1 тижня до 3 місяців
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Інтеграція Headless WordPress (WP REST API + фронтенд)

Headless WordPress — архітектура, де WordPress керує контентом і надає його через API. Фронтенд повністю окремий: Next.js, Nuxt, React SPA або будь-який інший стек. Редактори працюють у знайомому інтерфейсі WordPress, розробники отримують свободу вибору технологій на фронте.

Коли це оправдано

Headless додає складність. Оправдано, коли:

  • вже є React/Next.js-фронтенд і потрібна CMS під нього;
  • контент потрібно видавати на кілька платформ (сайт + мобільний додаток + розсилка);
  • потрібна ISR/SSG на Next.js з оновленням без повного розгортання;
  • команда фронтендерів не хоче працювати з PHP-шаблонами.

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

WP REST API: базові ендпоінти

WordPress REST API включений з коробки з версії 4.7. Базовий URL: https://site.com/wp-json/wp/v2/.

# Список постів
GET /wp-json/wp/v2/posts?per_page=10&page=1&_fields=id,title,slug,date,excerpt

# Один пост за slug
GET /wp-json/wp/v2/posts?slug=my-post-slug

# Сторінки
GET /wp-json/wp/v2/pages?slug=about

# Таксономії
GET /wp-json/wp/v2/categories
GET /wp-json/wp/v2/tags?post=123

# Custom Post Type (повинен бути зареєстрований з show_in_rest=true)
GET /wp-json/wp/v2/portfolio?per_page=6&acf_format=standard

Параметр _fields критично важливий — за замовчуванням відповідь містить десятки полів, більшість яких не потрібні:

GET /wp-json/wp/v2/posts?_fields=id,title,slug,date,featured_media,excerpt,_links

Налаштування WordPress для headless

Відключити тему (фронтенд не потрібен):

// functions.php
add_action('template_redirect', function () {
    if (!is_admin() && !is_user_logged_in()) {
        // Перенаправити все фронтенд-запити на фронтенд-домен
        if (!str_starts_with($_SERVER['REQUEST_URI'], '/wp-json')) {
            wp_redirect('https://frontend.site.com' . $_SERVER['REQUEST_URI'], 301);
            exit;
        }
    }
});

CORS для запитів з фронтенда:

add_action('rest_api_init', function () {
    remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');

    add_filter('rest_pre_serve_request', function ($value) {
        $allowed_origins = [
            'https://frontend.site.com',
            'http://localhost:3000',
        ];

        $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
        if (in_array($origin, $allowed_origins, true)) {
            header("Access-Control-Allow-Origin: {$origin}");
            header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
            header('Access-Control-Allow-Headers: Authorization, Content-Type');
            header('Access-Control-Allow-Credentials: true');
        }
        return $value;
    });
}, 15);

Розширення REST API своїми даними

ACF-поля в REST API через плагін acf-to-rest-api або вручную:

// Додати ACF-поля в ответ REST API для portfolio
add_action('rest_api_init', function () {
    register_rest_field('portfolio', 'acf', [
        'get_callback' => function ($post) {
            return get_fields($post['id']);
        },
        'schema' => ['type' => 'object'],
    ]);

    // Додати URL зображення прямо в ответ
    register_rest_field('post', 'featured_image_url', [
        'get_callback' => function ($post) {
            $id = $post['featured_media'];
            if (!$id) return null;

            $img = wp_get_attachment_image_src($id, 'large');
            return $img ? $img[0] : null;
        },
        'schema' => ['type' => ['string', 'null']],
    ]);
});

Кастомний ендпоінт для нестандартних запитів:

add_action('rest_api_init', function () {
    register_rest_route('app/v1', '/home', [
        'methods'  => 'GET',
        'callback' => function (WP_REST_Request $request) {
            return rest_ensure_response([
                'hero'     => get_fields(get_option('home_hero_page_id')),
                'featured' => array_map(
                    fn($post) => [
                        'id'    => $post->ID,
                        'title' => get_the_title($post),
                        'slug'  => $post->post_name,
                        'image' => get_the_post_thumbnail_url($post, 'medium'),
                    ],
                    get_posts(['post_type' => 'portfolio', 'posts_per_page' => 3])
                ),
            ]);
        },
        'permission_callback' => '__return_true',
    ]);
});

Інтеграція з Next.js

// lib/wordpress.ts
const WP_API = process.env.WP_API_URL; // https://cms.site.com/wp-json/wp/v2

export interface WpPost {
    id: number;
    slug: string;
    title: { rendered: string };
    excerpt: { rendered: string };
    date: string;
    featured_image_url: string | null;
    acf?: Record<string, unknown>;
}

export async function getPosts(params: {
    perPage?: number;
    page?: number;
    category?: number;
} = {}): Promise<{ posts: WpPost[]; total: number; totalPages: number }> {
    const url = new URL(`${WP_API}/posts`);
    url.searchParams.set('per_page', String(params.perPage ?? 10));
    url.searchParams.set('page',     String(params.page     ?? 1));
    url.searchParams.set('_fields',  'id,slug,title,excerpt,date,featured_image_url,acf');
    if (params.category) {
        url.searchParams.set('categories', String(params.category));
    }

    const res = await fetch(url.toString(), {
        next: { revalidate: 60 }, // ISR: оновлювати не чаще одного разу на хвилину
    });

    if (!res.ok) throw new Error(`WP API error: ${res.status}`);

    return {
        posts:      await res.json(),
        total:      Number(res.headers.get('X-WP-Total')),
        totalPages: Number(res.headers.get('X-WP-TotalPages')),
    };
}

export async function getPostBySlug(slug: string): Promise<WpPost | null> {
    const res = await fetch(
        `${WP_API}/posts?slug=${slug}&_fields=id,slug,title,content,date,featured_image_url,acf`,
        { next: { revalidate: 300 } }
    );
    const data = await res.json();
    return data[0] ?? null;
}

Терміни

Налаштування WordPress під headless (CORS, ACF в API, кастомні ендпоінти) — 6–8 годин. Інтеграція з Next.js (клієнт API, ISR, preview mode) — 1–1,5 робочих дня. Вебгаки on-demand revalidation — 3–4 години.