Отказ от SEO-плагинов и переход на собственное SEO в WordPress

Отказ от SEO-плагинов: ручная настройка WordPress

Я давно присматривался к SEO-плагинам: Yoast, Rank Math, All in One SEO. Удобно, красиво, но есть проблема — в бесплатных версиях они ограничивают возможности. А покупать PRO-версии или ставить ломаные — не мой путь. Я хочу контролировать каждый тег, каждую мету, каждую строчку кода. И я решил: сделаю всё сам, вручную, через дочернюю тему.

Это оказалось не так страшно, как звучит. Да, пришлось разбираться с хуками, фильтрами, nonce и экранированием. Но зато теперь я точно знаю, как работает SEO на моём сайте. И могу менять что угодно без оглядки на разработчиков плагинов.

Сегодня расскажу, как я это сделал. По шагам. С кодом, который можно сразу скопировать и использовать.

Создание дочерней темы

Что такое дочерняя тема и зачем она нужна?

Дочерняя тема — это тема-наследница. Она берёт все стили и шаблоны от родительской темы, но позволяет добавлять свой код без риска потерять изменения при обновлении родительской темы. Я вношу все изменения ТОЛЬКО в дочернюю тему.

Шаг 1. Создаю папку для дочерней темы

Через FTP или файловый менеджер хостинга я перешёл в папку:

text
/wp-content/themes/

Создал новую папку с именем:

text
название-родительской-темы-child

Пример: для темы Twenty Twenty-Five папка называется twentytwentyfive-child.

Шаг 2. Создаю файл style.css

Внутри папки дочерней темы создал файл style.css со следующим содержимым:

css
/*
Theme Name: Название вашей дочерней темы
Template: название-родительской-темы
Description: Дочерняя тема для [Название родительской темы], созданная для ручного SEO
Author: Ваше имя
Version: 1.0
*/

/* Импорт стилей родительской темы */
@import url("../название-родительской-темы/style.css");

/* Здесь потом будем добавлять свои стили (если понадобятся) */

Пояснение:

  • Theme Name — название, которое увидите в админке WordPress.

  • Template — ОБЯЗАТЕЛЬНО должно совпадать с именем папки родительской темы (например, twentytwentyfive).

  • @import — подключает все стили родительской темы, чтобы внешний вид не сломался.

Шаг 3. Создаю файл functions.php

В той же папке создал файл functions.php:

php
<?php
/**
 * Функции дочерней темы
 * Подключаем стили родителя и дочерние стили (если появятся)
 */
function child_enqueue_styles() {
    // Регистрируем стиль родительской темы
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
}
add_action( 'wp_enqueue_scripts', 'child_enqueue_styles' );

Пояснение: этот файл говорит WordPress загружать стили родительской темы правильным способом (более надёжно, чем @import в CSS).

Шаг 4. Активирую дочернюю тему

Зашёл в админку WordPress → «Внешний вид» → «Темы».

Нашёл свою дочернюю тему и нажал «Активировать».

Сайт выглядит так же, как и раньше.

Базовые SEO-настройки (файл functions.php)

ВСЕ ДАЛЬНЕЙШИЕ ИЗМЕНЕНИЯ вносятся в файл functions.php дочерней темы. Я открыл его и добавлял каждый следующий блок кода в конец файла (перед закрывающим ?> если он есть, или просто в конец).

Блок 1. Управление заголовками (Title) и мета-описаниями (Description)

Этот код добавляет на страницу редактирования каждого поста два новых поля: «SEO-заголовок» и «SEO-описание». Если заполнить эти поля, они будут использованы в заголовке страницы и в мета-теге description. Если поля пустые — заголовок строится автоматически, а описание генерируется из контента.

php
// ========== НАЧАЛО БЛОКА: заголовки и описания ==========

/**
 * 1. Добавляем мета-боксы для SEO-заголовка и SEO-описания
 */
function seo_add_meta_boxes() {
    add_meta_box(
        'seo_meta_box',
        'SEO-настройки',
        'seo_meta_box_html',
        'post',
        'normal',
        'high'
    );
}
add_action( 'add_meta_boxes', 'seo_add_meta_boxes' );

/**
 * 2. Выводим HTML-поля внутри мета-бокса
 */
function seo_meta_box_html( $post ) {
    $seo_title = get_post_meta( $post->ID, '_seo_title', true );
    $seo_desc   = get_post_meta( $post->ID, '_seo_description', true );
    
    wp_nonce_field( 'seo_save_meta_box_data', 'seo_meta_box_nonce' );
    
    echo '<p><label for="seo_title_field">SEO-заголовок (Title):</label><br>';
    echo '<input type="text" id="seo_title_field" name="seo_title_field" value="' . esc_attr( $seo_title ) . '" size="70" placeholder="Введите заголовок для SEO (до 60 символов)" /></p>';
    
    echo '<p><label for="seo_description_field">SEO-описание (Description):</label><br>';
    echo '<textarea id="seo_description_field" name="seo_description_field" rows="3" cols="70" placeholder="Введите описание для SEO (до 160 символов)">' . esc_textarea( $seo_desc ) . '</textarea></p>';
}

/**
 * 3. Сохраняем данные при сохранении поста
 */
function seo_save_meta_box_data( $post_id ) {
    if ( ! isset( $_POST['seo_meta_box_nonce'] ) ||
         ! wp_verify_nonce( $_POST['seo_meta_box_nonce'], 'seo_save_meta_box_data' ) ) {
        return;
    }
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return;
    }
    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }
    if ( isset( $_POST['seo_title_field'] ) ) {
        update_post_meta( $post_id, '_seo_title', sanitize_text_field( $_POST['seo_title_field'] ) );
    }
    if ( isset( $_POST['seo_description_field'] ) ) {
        update_post_meta( $post_id, '_seo_description', sanitize_textarea_field( $_POST['seo_description_field'] ) );
    }
}
add_action( 'save_post', 'seo_save_meta_box_data' );

/**
 * 4. Изменяем заголовок страницы (Title)
 */
function seo_custom_title( $title ) {
    if ( is_singular() ) {
        $post_id = get_queried_object_id();
        $seo_title = get_post_meta( $post_id, '_seo_title', true );
        if ( ! empty( $seo_title ) ) {
            return $seo_title;
        }
    }
    return $title;
}
add_filter( 'pre_get_document_title', 'seo_custom_title', 10, 1 );

/**
 * 5. Добавляем мета-тег description в <head>
 */
function seo_add_description_meta() {
    if ( is_singular() ) {
        $post_id = get_queried_object_id();
        $seo_desc = get_post_meta( $post_id, '_seo_description', true );
        if ( ! empty( $seo_desc ) ) {
            echo '<meta name="description" content="' . esc_attr( $seo_desc ) . '" />' . "\n";
            return;
        }
        $post = get_post( $post_id );
        if ( $post ) {
            $content = strip_shortcodes( $post->post_content );
            $content = wp_strip_all_tags( $content );
            $content = trim( preg_replace( '/\s+/', ' ', $content ) );
            $excerpt = mb_substr( $content, 0, 160, 'UTF-8' );
            if ( ! empty( $excerpt ) ) {
                echo '<meta name="description" content="' . esc_attr( $excerpt ) . '" />' . "\n";
            }
        }
    }
}
add_action( 'wp_head', 'seo_add_description_meta', 5 );

// ========== КОНЕЦ БЛОКА ==========

Что делает этот блок:

  • Добавляет поля «SEO-заголовок» и «SEO-описание» в редактор постов.

  • Сохраняет введённые значения в базу данных.

  • Подставляет их в <title> и <meta name="description">.

  • Если поля пустые — автоматически генерирует описание из первых 160 символов контента.

Блок 2. Управление индексацией архивов

Этот код добавляет на все архивные страницы (рубрики, метки, даты, авторские архивы) мета-тег noindex, follow, чтобы поисковики не индексировали эти страницы, но продолжали переходить по ссылкам.

php
// ========== НАЧАЛО БЛОКА: управление индексацией архивов ==========

function seo_archive_noindex() {
    if ( is_archive() || is_tag() || is_category() || is_date() || is_author() ) {
        echo '<meta name="robots" content="noindex, follow" />' . "\n";
    }
    if ( is_paged() && ! is_singular() ) {
        echo '<meta name="robots" content="noindex, follow" />' . "\n";
    }
}
add_action( 'wp_head', 'seo_archive_noindex', 5 );

// ========== КОНЕЦ БЛОКА ==========

Что делает этот блок:

  • Закрывает от индексации все архивы (рубрики, метки, даты, авторов).

  • Закрывает от индексации страницы пагинации (кроме пагинации внутри постов).

Блок 3. Канонические ссылки для пагинации

php
// ========== НАЧАЛО БЛОКА: канонические ссылки для пагинации ==========

function seo_canonical_for_paged() {
    if ( is_paged() ) {
        $base_url = get_pagenum_link( 1 );
        echo '<link rel="canonical" href="' . esc_url( $base_url ) . '" />' . "\n";
    }
}
add_action( 'wp_head', 'seo_canonical_for_paged', 3 );

// ========== КОНЕЦ БЛОКА ==========

Что делает этот блок: Указывает поисковикам, что все страницы пагинации (например, /page/2/) — это вариант первой страницы, чтобы избежать дублей.

Блок 4. Канонические ссылки без параметров

Этот блок удаляет все GET-параметры из канонической ссылки (например, ?utm_source=...), чтобы поисковик всегда знал основную версию страницы.

php
// ========== НАЧАЛО БЛОКА: канонические ссылки без параметров ==========

function seo_add_canonical_without_params() {
    $protocol = is_ssl() ? 'https://' : 'http://';
    $host = $_SERVER['HTTP_HOST'];
    $request_uri = $_SERVER['REQUEST_URI'];
    $path = strtok( $request_uri, '?' );
    $canonical_url = $protocol . $host . $path;
    $current_url = $protocol . $host . $request_uri;
    if ( $canonical_url !== $current_url ) {
        echo '<link rel="canonical" href="' . esc_url( $canonical_url ) . '" />' . "\n";
    }
}
add_action( 'wp_head', 'seo_add_canonical_without_params', 1 );

// ========== КОНЕЦ БЛОКА ==========

Что делает этот блок: Добавляет каноническую ссылку на чистый URL (без параметров) для всех страниц, к которым обращаются с параметрами в адресной строке.

Open Graph и Twitter Cards

Эти теги нужны для красивого отображения ссылок в социальных сетях и мессенджерах (Telegram, ВКонтакте, Facebook, Twitter и других).

php
// ========== НАЧАЛО БЛОКА: Open Graph и Twitter Cards ==========

function seo_add_social_meta() {
    global $post;

    $site_name = get_bloginfo( 'name' );
    $site_description = get_bloginfo( 'description' );
    $default_image = ''; // Сюда можно вставить URL стандартной картинки

    $title = $site_name;
    $description = $site_description;
    $image = $default_image;
    $url = get_permalink();
    $type = 'website';

    if ( is_singular() ) {
        $post_id = get_queried_object_id();
        $url = get_permalink( $post_id );
        $type = 'article';

        $seo_title = get_post_meta( $post_id, '_seo_title', true );
        if ( ! empty( $seo_title ) ) {
            $title = $seo_title;
        } else {
            $title = get_the_title( $post_id ) . ' — ' . $site_name;
        }

        $seo_desc = get_post_meta( $post_id, '_seo_description', true );
        if ( ! empty( $seo_desc ) ) {
            $description = $seo_desc;
        } else {
            $content = strip_shortcodes( $post->post_content );
            $content = wp_strip_all_tags( $content );
            $content = trim( preg_replace( '/\s+/', ' ', $content ) );
            $description = mb_substr( $content, 0, 200, 'UTF-8' );
            if ( empty( $description ) ) {
                $description = $site_description;
            }
        }

        if ( has_post_thumbnail( $post_id ) ) {
            $image = get_the_post_thumbnail_url( $post_id, 'full' );
        } else {
            $pattern = '/<img[^>]+src="([^">]+)"/';
            preg_match( $pattern, $post->post_content, $matches );
            if ( ! empty( $matches[1] ) ) {
                $image = $matches[1];
            }
        }
    } elseif ( is_front_page() || is_home() ) {
        $title = $site_name;
        $description = $site_description;
        $url = home_url( '/' );
        $type = 'website';
    } else {
        $title = wp_get_document_title();
        $description = $site_description;
        $url = get_permalink();
        $type = 'website';
    }

    // РАСКОММЕНТИРУЙТЕ И УКАЖИТЕ СВОЙ URL, ЕСЛИ ХОТИТЕ СТАНДАРТНУЮ КАРТИНКУ-ЗАГЛУШКУ:
    // if ( empty( $image ) ) $image = 'https://ваш-сайт.ru/wp-content/uploads/logo.png';

    $title = esc_attr( $title );
    $description = esc_attr( $description );
    $image = esc_url( $image );
    $url = esc_url( $url );

    echo "\n<!-- Open Graph / SEO Meta -->\n";
    echo '<meta property="og:title" content="' . $title . '" />' . "\n";
    echo '<meta property="og:description" content="' . $description . '" />' . "\n";
    echo '<meta property="og:type" content="' . $type . '" />' . "\n";
    echo '<meta property="og:url" content="' . $url . '" />' . "\n";
    echo '<meta property="og:site_name" content="' . esc_attr( $site_name ) . '" />' . "\n";
    echo '<meta property="og:locale" content="' . get_locale() . '" />' . "\n";

    if ( ! empty( $image ) ) {
        echo '<meta property="og:image" content="' . $image . '" />' . "\n";
        echo '<meta property="og:image:width" content="1200" />' . "\n";
        echo '<meta property="og:image:height" content="630" />' . "\n";
    }

    echo "\n<!-- Twitter Card -->\n";
    echo '<meta name="twitter:card" content="summary_large_image" />' . "\n";
    echo '<meta name="twitter:title" content="' . $title . '" />' . "\n";
    echo '<meta name="twitter:description" content="' . $description . '" />' . "\n";
    if ( ! empty( $image ) ) {
        echo '<meta name="twitter:image" content="' . $image . '" />' . "\n";
    }
    // РАСКОММЕНТИРУЙТЕ, ЕСЛИ У ВАС ЕСТЬ АККАУНТ В TWITTER:
    // echo '<meta name="twitter:site" content="@ваш_аккаунт" />' . "\n";
}
add_action( 'wp_head', 'seo_add_social_meta', 3 );

// ========== КОНЕЦ БЛОКА ==========

Что делает этот блок:

  • Генерирует Open Graph-теги (og:titleog:descriptionog:imageog:url и др.) для соцсетей и мессенджеров.

  • Генерирует Twitter Cards для корректного отображения в Twitter/X.

  • Берёт данные из SEO-полей, если они заполнены, или генерирует автоматически.

Schema-разметка (JSON-LD) для статей

Schema-разметка помогает поисковым системам лучше понимать содержимое страницы: что это за статья, кто автор, когда опубликована, есть ли изображение.

php
// ========== НАЧАЛО БЛОКА: Schema-разметка JSON-LD ==========

function seo_add_schema_org() {
    if ( ! is_singular() ) {
        return;
    }

    global $post;
    $post_id = $post->ID;

    $site_name = get_bloginfo( 'name' );
    $site_url = home_url( '/' );
    $post_title = get_the_title( $post_id );
    $post_url = get_permalink( $post_id );
    $post_date = get_the_date( 'c', $post_id );
    $post_modified = get_the_modified_date( 'c', $post_id );
    $author_name = get_the_author_meta( 'display_name', $post->post_author );
    $author_url = get_author_posts_url( $post->post_author );

    $image_url = '';
    if ( has_post_thumbnail( $post_id ) ) {
        $image_url = get_the_post_thumbnail_url( $post_id, 'full' );
    } else {
        $pattern = '/<img[^>]+src="([^">]+)"/';
        preg_match( $pattern, $post->post_content, $matches );
        if ( ! empty( $matches[1] ) ) {
            $image_url = $matches[1];
        }
    }

    $seo_desc = get_post_meta( $post_id, '_seo_description', true );
    if ( ! empty( $seo_desc ) ) {
        $description = $seo_desc;
    } else {
        $content = strip_shortcodes( $post->post_content );
        $content = wp_strip_all_tags( $content );
        $content = trim( preg_replace( '/\s+/', ' ', $content ) );
        $description = mb_substr( $content, 0, 200, 'UTF-8' );
    }

    $schema = array(
        '@context' => 'https://schema.org',
        '@type'    => 'Article',
        'headline' => $post_title,
        'description' => $description,
        'mainEntityOfPage' => array(
            '@type' => 'WebPage',
            '@id'   => $post_url,
        ),
        'datePublished' => $post_date,
        'dateModified'  => $post_modified,
        'author' => array(
            '@type' => 'Person',
            'name'  => $author_name,
            'url'   => $author_url,
        ),
        'publisher' => array(
            '@type' => 'Organization',
            'name'  => $site_name,
            'url'   => $site_url,
        ),
    );

    if ( ! empty( $image_url ) ) {
        $schema['image'] = array(
            '@type'  => 'ImageObject',
            'url'    => $image_url,
            'width'  => 1200,
            'height' => 630,
        );
    }

    echo "\n<!-- Schema.org JSON-LD -->\n";
    echo '<script type="application/ld+json">' . json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . '</script>' . "\n";
}
add_action( 'wp_head', 'seo_add_schema_org', 4 );

// ========== КОНЕЦ БЛОКА ==========

Что делает этот блок: Добавляет структурированные данные Schema.org для статей (тип Article) — это помогает поисковикам лучше понимать содержимое и может улучшить отображение в выдаче.

Хлебные крошки (BreadcrumbList Schema)

Этот блок добавляет микроразметку для хлебных крошек — цепочки навигации «Главная → Рубрика → Пост».

php
// ========== НАЧАЛО БЛОКА: хлебные крошки (BreadcrumbList) ==========

function seo_add_breadcrumb_schema() {
    $breadcrumbs = array();

    $home_url = home_url( '/' );
    $home_title = get_bloginfo( 'name' );
    $breadcrumbs[] = array(
        '@type' => 'ListItem',
        'position' => 1,
        'name' => $home_title,
        'item' => $home_url,
    );

    if ( is_singular() ) {
        $post_id = get_queried_object_id();
        $post_type = get_post_type( $post_id );

        if ( $post_type == 'post' ) {
            $categories = get_the_category( $post_id );
            if ( ! empty( $categories ) ) {
                $cat = $categories[0];
                $cat_link = get_category_link( $cat->term_id );
                $breadcrumbs[] = array(
                    '@type' => 'ListItem',
                    'position' => 2,
                    'name' => $cat->name,
                    'item' => $cat_link,
                );
            }
            $breadcrumbs[] = array(
                '@type' => 'ListItem',
                'position' => count( $breadcrumbs ) + 1,
                'name' => get_the_title( $post_id ),
            );
        } elseif ( $post_type == 'page' ) {
            $breadcrumbs[] = array(
                '@type' => 'ListItem',
                'position' => 2,
                'name' => get_the_title( $post_id ),
            );
        } else {
            $breadcrumbs[] = array(
                '@type' => 'ListItem',
                'position' => 2,
                'name' => get_the_title( $post_id ),
            );
        }
    } elseif ( is_category() ) {
        $cat_id = get_queried_object_id();
        $cat = get_category( $cat_id );
        $breadcrumbs[] = array(
            '@type' => 'ListItem',
            'position' => 2,
            'name' => $cat->name,
        );
    } elseif ( is_tag() ) {
        $tag_id = get_queried_object_id();
        $tag = get_tag( $tag_id );
        $breadcrumbs[] = array(
            '@type' => 'ListItem',
            'position' => 2,
            'name' => $tag->name,
        );
    } elseif ( is_author() ) {
        $author = get_queried_object();
        $breadcrumbs[] = array(
            '@type' => 'ListItem',
            'position' => 2,
            'name' => 'Автор: ' . $author->display_name,
        );
    } elseif ( is_date() ) {
        $breadcrumbs[] = array(
            '@type' => 'ListItem',
            'position' => 2,
            'name' => 'Архив дат',
        );
    } elseif ( is_search() ) {
        $breadcrumbs[] = array(
            '@type' => 'ListItem',
            'position' => 2,
            'name' => 'Результаты поиска: ' . get_search_query(),
        );
    } elseif ( is_404() ) {
        $breadcrumbs[] = array(
            '@type' => 'ListItem',
            'position' => 2,
            'name' => 'Страница не найдена',
        );
    }

    if ( count( $breadcrumbs ) > 1 ) {
        $schema = array(
            '@context' => 'https://schema.org',
            '@type' => 'BreadcrumbList',
            'itemListElement' => $breadcrumbs,
        );
        echo "\n<!-- Breadcrumb Schema -->\n";
        echo '<script type="application/ld+json">' . json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . '</script>' . "\n";
    }
}
add_action( 'wp_head', 'seo_add_breadcrumb_schema', 4 );

// ========== КОНЕЦ БЛОКА ==========

Что делает этот блок: Добавляет структурированные данные для хлебных крошек — это помогает поисковикам понять структуру сайта и может улучшить сниппеты в выдаче.

XML-карта сайта (Sitemap)

Этот код создаёт динамическую XML-карту сайта, доступную по адресу https://ваш-сайт.ru/sitemap.xml.

php
// ========== НАЧАЛО БЛОКА: XML-карта сайта ==========

function seo_add_sitemap_rewrite() {
    add_rewrite_rule(
        '^sitemap\.xml$',
        'index.php?seo_sitemap=1',
        'top'
    );
}
add_action( 'init', 'seo_add_sitemap_rewrite' );

function seo_add_sitemap_query_var( $vars ) {
    $vars[] = 'seo_sitemap';
    return $vars;
}
add_filter( 'query_vars', 'seo_add_sitemap_query_var' );

function seo_sitemap_handler() {
    if ( get_query_var( 'seo_sitemap' ) != 1 ) {
        return;
    }

    header( 'Content-Type: application/xml; charset=utf-8' );
    header( 'X-Robots-Tag: noindex, follow' );
    header( 'Cache-Control: no-cache, must-revalidate' );
    header( 'Expires: Thu, 01 Jan 1970 00:00:00 GMT' );

    echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";

    // Главная страница
    $home_url = home_url( '/' );
    echo '<url>';
    echo '<loc>' . esc_url( $home_url ) . '</loc>';
    echo '<priority>1.0</priority>';
    echo '<changefreq>daily</changefreq>';
    echo '<lastmod>' . date( 'Y-m-d' ) . '</lastmod>';
    echo '</url>' . "\n";

    // Все опубликованные посты
    $posts = get_posts( array(
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'posts_per_page' => -1,
        'orderby'        => 'modified',
        'order'          => 'DESC',
    ) );

    foreach ( $posts as $post ) {
        $url = get_permalink( $post->ID );
        $lastmod = get_the_modified_date( 'Y-m-d', $post->ID );
        echo '<url>';
        echo '<loc>' . esc_url( $url ) . '</loc>';
        echo '<priority>0.8</priority>';
        echo '<changefreq>weekly</changefreq>';
        echo '<lastmod>' . $lastmod . '</lastmod>';
        echo '</url>' . "\n";
    }

    // Все опубликованные страницы (Pages)
    $pages = get_pages( array(
        'post_status' => 'publish',
        'hierarchical' => 0,
    ) );

    foreach ( $pages as $page ) {
        if ( get_option( 'page_on_front' ) == $page->ID ) {
            continue;
        }
        $url = get_permalink( $page->ID );
        $lastmod = get_the_modified_date( 'Y-m-d', $page->ID );
        echo '<url>';
        echo '<loc>' . esc_url( $url ) . '</loc>';
        echo '<priority>0.6</priority>';
        echo '<changefreq>monthly</changefreq>';
        echo '<lastmod>' . $lastmod . '</lastmod>';
        echo '</url>' . "\n";
    }

    echo '</urlset>';
    exit;
}
add_action( 'template_redirect', 'seo_sitemap_handler' );

// ========== КОНЕЦ БЛОКА ==========

Что делает этот блок: Создаёт динамическую XML-карту сайта, которая автоматически обновляется при публикации новых постов. Включает главную страницу, все посты и все страницы (Pages).

Важно: После добавления этого кода зайдите в админку → «Настройки» → «Постоянные ссылки» и нажмите «Сохранить изменения» — это обновит правила ЧПУ.

Файл robots.txt

Создайте в корневой папке сайта (там же, где лежат wp-config.php и wp-load.php) файл robots.txt со следующим содержимым:

text
User-agent: *
Allow: /wp-content/uploads/
Disallow: /wp-admin/
Disallow: /wp-includes/
Disallow: /wp-content/plugins/
Disallow: /wp-content/themes/
Disallow: /wp-login.php
Disallow: /wp-register.php
Disallow: /wp-json/
Disallow: /xmlrpc.php
Disallow: /?s=*
Disallow: /search/
Disallow: /page/
Disallow: /tag/
Disallow: /category/
Disallow: /author/
Disallow: /date/
Disallow: /feed/
Disallow: /comments/feed/
Disallow: /trackback/
Disallow: /*/feed
Disallow: /*?*
Disallow: /*.pdf$

# Разрешаем индексацию только основных страниц с контентом
Allow: /$

# Карта сайта (ЗАМЕНИТЕ НА СВОЙ ДОМЕН)
Sitemap: https://ваш-сайт.ru/sitemap.xml

Что делает этот файл:

  • Закрывает от индексации служебные папки (/wp-admin//wp-includes/ и др.).

  • Закрывает архивы (рубрики, метки, авторы, даты), поиск, пагинацию и страницы с параметрами.

  • Указывает поисковикам путь к карте сайта.

Важно: Замените https://ваш-сайт.ru на адрес вашего сайта.

Настройка ЧПУ (постоянных ссылок)

Зайдите в админку WordPress → «Настройки» → «Постоянные ссылки».

Выберите вариант «Название записи» (Post name).

Нажмите «Сохранить изменения».

Почему это важно: ЧПУ вида https://сайт/название-статьи/ лучше для SEO, чем https://сайт/?p=123.

Заполнение SEO-полей, Отрывка и SEO для изображений

9.1. SEO-заголовок и SEO-описание

Для каждой записи (поста) и страницы:

  • Откройте запись в редакторе.

  • Прокрутите вниз до блока «SEO-настройки».

  • Заполните поле «SEO-заголовок (Title)» — рекомендуемая длина до 60 символов.

  • Заполните поле «SEO-описание (Description)» — рекомендуемая длина 150–160 символов.

Совет: Заголовок должен содержать ключевое слово и быть привлекательным для клика. Описание — кратко и ёмко передавать суть страницы.

9.2. Отрывок (Excerpt)

Отрывок — это краткая выжимка из поста, которая отображается на главной странице, в архивах и в результатах внутреннего поиска. Его тоже нужно заполнять.

Где находится: В редакторе поста, обычно под основным полем ввода текста (вкладка «Отрывок»). Если её нет — включите через «Настройки экрана» в правом верхнем углу.

Рекомендуемая длина: 25–35 слов (примерно 150–160 символов).

Зачем заполнять:

  • Улучшает внешний вид анонсов на сайте.

  • Помогает посетителям быстрее понять, о чём статья.

  • Если SEO-описание не заполнено, WordPress может использовать отрывок как мета-описание.

9.3. SEO для изображений

Правильное оформление изображений — важная часть SEO. Для каждого изображения в посте:

  • Заполните атрибут alt (альтернативный текст) — он должен описывать содержание изображения и содержать ключевое слово (если уместно).

  • Дайте файлу осмысленное имя перед загрузкой (например, seo-nastrojka-wordpress.jpg, а не IMG_1234.jpg).

  • Используйте миниатюру поста (Featured Image) — она будет использоваться в Open Graph и Schema-разметке.

Как заполнить alt в WordPress:

  • При вставке изображения в пост заполните поле «Альтернативный текст».

  • Или в медиатеке откройте изображение и заполните поле «Alt-текст».

Финальная проверка и отправка sitemap

10.1. Проверьте работу всех мета-тегов

Откройте любую страницу сайта, нажмите правой кнопкой мыши → «Посмотреть код страницы» и проверьте наличие:

  • <title> — ваш SEO-заголовок.

  • <meta name="description"> — ваше SEO-описание.

  • Open Graph-теги (og:titleog:descriptionog:image).

  • Twitter Cards.

  • Schema-разметка (application/ld+json).

  • Каноническая ссылка (<link rel="canonical">).

10.2. Проверьте sitemap.xml

Откройте в браузере https://ваш-сайт.ru/sitemap.xml — должен открыться XML-файл со списком всех страниц.

10.3. Проверьте robots.txt

Откройте https://ваш-сайт.ru/robots.txt — должен открыться текстовый файл с вашими правилами.

10.4. Отправьте sitemap в поисковые системы

Яндекс.Вебмастер:

  • Зайдите в панель Яндекс.Вебмастера.

  • Выберите свой сайт → раздел «Индексирование» → «Sitemap-файлы».

  • Добавьте адрес: https://ваш-сайт.ru/sitemap.xml.

  • Нажмите «Добавить».

Google Search Console:

  • Зайдите в Search Console → выберите сайт.

  • В левом меню «Sitemap» (или «Карты сайта»).

  • Введите sitemap.xml и нажмите «Отправить».

Полный список файлов и их назначение

Файл Местоположение Назначение
style.css /wp-content/themes/название-темы-child/ Стили дочерней темы, подключение родительских стилей
functions.php /wp-content/themes/название-темы-child/ ГЛАВНЫЙ ФАЙЛ — содержит весь SEO-код (заголовки, описания, OG, Schema, sitemap и др.)
robots.txt Корень сайта (/public_html/ или /) Управление индексацией для поисковых роботов

Что делать, если возникли вопросы?

Если какой-то шаг непонятен или код не работает — спросите у DeepSeek или другого ИИ-помощника. Опишите проблему максимально подробно:

  • Что вы сделали?

  • Что ожидали увидеть?

  • Что увидели вместо этого?

  • Приложите код (если есть) и сообщение об ошибке (если есть).

ИИ-помощники отлично справляются с отладкой PHP-кода и могут подсказать, где допущена ошибка.

А также можете написать мне https://vk.ru/milyutink — я обязательно постараюсь помочь!

Почему я не стал продавать плагины и начал их отдавать бесплатно.

Читай также: Почему я взял паузу в разработке и начал писать статьи

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *