WordPress分类目录SEO自定义TDK现代化方案:termmeta API+REST字段+Yoast共存策略

WordPress分类目录SEO自定义TDK现代化方案:termmeta API+REST字段+Yoast共存策略
张文保 更新 35 分钟阅读 2,256 阅读
本文目录
  1. WordPress 分类的"分类元数据"机制
  2. 现代化代码:term_meta + 后台编辑界面
  3. 与 Yoast / RankMath 共存的兼容性
  4. 优先用插件
  5. 共存策略:检测插件存在跳过自定义
  6. REST API 暴露分类 SEO 字段
  7. 与 Schema 结构化数据协同
  8. 批量为已有分类生成 SEO 字段
  9. 用 AI 批量生成更高质量的 SEO 内容
  10. 性能影响
  11. 跨语言 / 多站点扩展
  12. 调试与排查
  13. 后台填了字段前台不显示
  14. 标题没生效
  15. 常见问题解答
  16. 用 termmeta 而不是 options 真的有差别吗?
  17. 这套代码与 Yoast / RankMath 冲突怎么办?
  18. 分类描述(自带 description 字段)和 SEO description 哪个更好?
  19. 能不能给标签(tag)也加 SEO 字段?
  20. 批量分类生成 SEO 后,怎么验证生效?
  21. WordPress 自定义 post type 的分类(如 Product Category)也能用吗?
  22. 分类页的 canonical URL 怎么处理?
  23. 分类下文章数为 0 时还要 SEO 吗?
  24. 能给每个分类加封面图吗?
  25. 分类页面对 SEO 真的重要吗?
  26. 权威参考资料
摘要:很多教程把WordPress分类的SEO字段塞进wp_options,其实4.4起的wp_termmeta表规范得多。本文给出现代化方案——后台加TDK编辑界面、保存到term_meta、与Yoast和RankMath共存的兼容、REST API暴露分类SEO字段、与Schema协同,再讲批量为已有分类生成SEO字段、用AI批量生成更高质量内容、性能影响和跨语言多站点扩展。

WordPress 默认的分类(Category)和标签(Tag)页面只有"分类名 + 上下级关系"——前台 <title> 直接用分类名,<meta description><meta keywords> 完全没有,对 SEO 极不友好:每个分类页拿不到独立 TDK,权重传递低、SERP 不给点击率。

网传的修法是自己写 seocategory.php 给分类编辑页加 SEO 字段——但 2026 年这套代码有几个明显的过时点:用了已被弃用的 get_option() 误用、没用 WordPress 4.4+ 推荐的 termmeta API、不支持 Gutenberg block 编辑器的现代化字段交互。这一篇把"WP 分类自定义 TDK"重写成 2026 年标准做法:用 termmeta + REST API field + 与 Yoast/RankMath 共存的兼容写法。

WordPress 分类的"分类元数据"机制

WordPress 4.4 引入了 termmeta 表(wp_termmeta),专门存"分类/标签"的额外字段——比 wp_options 当 KV 存储更规范。术语层级关系:

层级API
分类法(taxonomy)wp_term_taxonomyregister_taxonomy()
具体分类(term)wp_termswp_insert_term() / get_term()
分类元数据wp_termmetaadd_term_meta() / update_term_meta() / get_term_meta()
文章 ↔ 分类关系wp_term_relationshipswp_set_object_terms()

原帖把 SEO 字段存到 wp_options 表(cat_set_$cat_id)——能用但不规范,且 wp_options 表是全站共享,分类删除时清理不掉。正确做法是用 termmeta API

现代化代码:term_meta + 后台编辑界面

functions.php 或独立 mu-plugin 放下面这段:

// === WordPress 分类自定义 SEO TDK ===

// 1. 在分类编辑页加 SEO 字段
add_action('category_edit_form_fields', 'mysite_category_seo_fields', 10, 2);
function mysite_category_seo_fields($term, $taxonomy) {
    $seo_title       = get_term_meta($term->term_id, 'seo_title', true);
    $seo_description = get_term_meta($term->term_id, 'seo_description', true);
    $seo_keywords    = get_term_meta($term->term_id, 'seo_keywords', true);
    ?>
    <tr class="form-field">
        <th><label for="seo_title">SEO 标题</label></th>
        <td>
            <input type="text" name="seo_title" id="seo_title" value="<?php echo esc_attr($seo_title); ?>" size="50">
            <p class="description">留空则自动用:分类名 + 站点名</p>
        </td>
    </tr>
    <tr class="form-field">
        <th><label for="seo_description">SEO 描述</label></th>
        <td>
            <textarea name="seo_description" id="seo_description" rows="3" cols="50"><?php echo esc_textarea($seo_description); ?></textarea>
            <p class="description">Meta description,建议 120-160 字符</p>
        </td>
    </tr>
    <tr class="form-field">
        <th><label for="seo_keywords">SEO 关键词</label></th>
        <td>
            <input type="text" name="seo_keywords" id="seo_keywords" value="<?php echo esc_attr($seo_keywords); ?>" size="50">
            <p class="description">多关键词用英文逗号分隔,3-5 个为宜</p>
        </td>
    </tr>
    <?php
}

// 2. 保存分类时写入 termmeta
add_action('edited_category', 'mysite_save_category_seo', 10, 2);
function mysite_save_category_seo($term_id, $tt_id) {
    if (!current_user_can('manage_categories')) return;

    if (isset($_POST['seo_title'])) {
        update_term_meta($term_id, 'seo_title', sanitize_text_field($_POST['seo_title']));
    }
    if (isset($_POST['seo_description'])) {
        update_term_meta($term_id, 'seo_description', sanitize_textarea_field($_POST['seo_description']));
    }
    if (isset($_POST['seo_keywords'])) {
        update_term_meta($term_id, 'seo_keywords', sanitize_text_field($_POST['seo_keywords']));
    }
}

// 3. 前台分类页的 <title> 与 meta 输出
add_filter('document_title_parts', 'mysite_category_title');
function mysite_category_title($parts) {
    if (is_category()) {
        $term = get_queried_object();
        $custom_title = get_term_meta($term->term_id, 'seo_title', true);
        if (!empty($custom_title)) {
            $parts['title'] = $custom_title;
        } else {
            // 兜底:分类名 + 共 N 篇文章
            $parts['title'] = $term->name . ' 相关文章合集(共 ' . $term->count . ' 篇)';
        }
    }
    return $parts;
}

// 4. 输出 meta description / keywords
add_action('wp_head', 'mysite_category_meta', 1);
function mysite_category_meta() {
    if (!is_category()) return;
    $term = get_queried_object();

    $description = get_term_meta($term->term_id, 'seo_description', true);
    if (empty($description)) {
        // 兜底:用分类的描述(在分类编辑页有原生 description 字段)
        $description = $term->description ?: '保哥笔记 ' . $term->name . ' 分类下共 ' . $term->count . ' 篇文章合集。';
    }
    $description = wp_trim_words(strip_tags($description), 80, '...');

    $keywords = get_term_meta($term->term_id, 'seo_keywords', true);
    if (empty($keywords)) {
        $keywords = $term->name;
    }

    echo '<meta name="description" content="' . esc_attr($description) . '">' . "\n";
    echo '<meta name="keywords" content="' . esc_attr($keywords) . '">' . "\n";
}

关键设计:

  • 用 term_meta 而不是 options:分类删除时元数据自动级联删除(wp_delete_term 会调 delete_term_meta),不留垃圾;
  • 权限校验current_user_can('manage_categories') 防止越权写入;
  • sanitize 转义:sanitize_text_field 防 XSS;
  • document_title_parts filter:标准的 WP 5.0+ 标题修改 hook,不直接覆盖 wp_title();
  • 三级回退:自定义 → 分类原生 description → 自动拼接默认值。

与 Yoast / RankMath 共存的兼容性

WordPress 圈最常用的 SEO 插件 Yoast 和 RankMath 都自带"分类 SEO 字段"功能——它们存在 wp_termmeta 表里的 key 是各自约定的:

插件title 字段 keydescription 字段 key
Yoast SEO_yoast_wpseo_title_yoast_wpseo_metadesc
RankMathrank_math_titlerank_math_description
SEOPress_seopress_titles_title_seopress_titles_desc
本文方案seo_titleseo_description

如果同时装 Yoast 和自写代码会冲突——两边都改 wp_head 里的 meta,输出两份。两种处理:

优先用插件

如果决定用 Yoast / RankMath,不要再写自定义代码——直接在插件后台填字段即可。Yoast / RankMath 的 SEO 字段 UI 和兜底逻辑比本文写的更完善。

共存策略:检测插件存在跳过自定义

add_action('wp_head', 'mysite_category_meta', 1);
function mysite_category_meta() {
    if (!is_category()) return;

    // 如果装了 Yoast 或 RankMath,跳过自定义输出
    if (defined('WPSEO_VERSION') || defined('RANK_MATH_VERSION')) {
        return;
    }

    // ... 自定义输出
}

这样自写代码只在没装 SEO 插件的轻量站才生效,避免与插件双重输出。

REST API 暴露分类 SEO 字段

WordPress 5.0+ 的 Gutenberg / 移动应用 / 第三方对接都依赖 REST API。要让 /wp-json/wp/v2/categories 返回这些 SEO 字段:

add_action('rest_api_init', function () {
    register_rest_field('category', 'seo', [
        'get_callback' => function ($object) {
            return [
                'title'       => get_term_meta($object['id'], 'seo_title', true),
                'description' => get_term_meta($object['id'], 'seo_description', true),
                'keywords'    => get_term_meta($object['id'], 'seo_keywords', true),
            ];
        },
        'update_callback' => function ($value, $object) {
            if (!current_user_can('manage_categories')) return new WP_Error('rest_cannot_update', '无权限', ['status' => 403]);

            if (isset($value['title']))       update_term_meta($object->term_id, 'seo_title', sanitize_text_field($value['title']));
            if (isset($value['description'])) update_term_meta($object->term_id, 'seo_description', sanitize_textarea_field($value['description']));
            if (isset($value['keywords']))    update_term_meta($object->term_id, 'seo_keywords', sanitize_text_field($value['keywords']));
            return true;
        },
        'schema' => [
            'description' => '分类 SEO 字段',
            'type'        => 'object',
            'context'     => ['view', 'edit'],
        ],
    ]);
});

这样 GET /wp-json/wp/v2/categories/123 会多出 seo 字段;POST/PUT 同 URL 能改这些字段(前提是有 manage_categories 权限)。

与 Schema 结构化数据协同

给分类页加 CollectionPage Schema 让 Google 更精准识别:

add_action('wp_head', 'mysite_category_schema', 2);
function mysite_category_schema() {
    if (!is_category()) return;
    $term = get_queried_object();

    $schema = [
        '@context'    => 'https://schema.org',
        '@type'       => 'CollectionPage',
        'name'        => get_term_meta($term->term_id, 'seo_title', true) ?: $term->name,
        'description' => get_term_meta($term->term_id, 'seo_description', true) ?: $term->description,
        'url'         => get_term_link($term),
        'mainEntity'  => [
            '@type'         => 'ItemList',
            'numberOfItems' => (int)$term->count,
        ],
    ];
    echo '<script type="application/ld+json">' . wp_json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '</script>' . "\n";
}

批量为已有分类生成 SEO 字段

站点已有 100 个分类不可能手动一个个填。批量补充 SEO 字段的脚本:

// 一次性脚本:扫所有分类,为没填 SEO 的分类自动生成
$terms = get_terms(['taxonomy' => 'category', 'hide_empty' => false]);
foreach ($terms as $term) {
    if (!get_term_meta($term->term_id, 'seo_title', true)) {
        update_term_meta($term->term_id, 'seo_title', $term->name . ' 相关文章合集(' . $term->count . ' 篇)');
    }
    if (!get_term_meta($term->term_id, 'seo_description', true)) {
        $desc = $term->description ?: ('保哥笔记 ' . $term->name . ' 分类下共 ' . $term->count . ' 篇深度技术与实战内容。');
        update_term_meta($term->term_id, 'seo_description', $desc);
    }
    if (!get_term_meta($term->term_id, 'seo_keywords', true)) {
        update_term_meta($term->term_id, 'seo_keywords', $term->name);
    }
}
echo "完成,处理 " . count($terms) . " 个分类\n";

这段脚本可以做成 WP-CLI 命令长期跑——新建分类时自动跑一次填充默认值。

用 AI 批量生成更高质量的 SEO 内容

简单的"分类名 + 共 N 篇" 是最低标准,但点击率不高。用 GPT API 生成质量更高的:

// 调 OpenAI / Claude API 给分类生成 SEO 文案
function generate_category_seo_with_ai($term_name, $term_count) {
    $prompt = "请为博客分类“{$term_name}”生成 SEO meta description(≤ 155 字符),重点突出 SEO/技术/实战角度。";

    $response = wp_remote_post('https://api.openai.com/v1/chat/completions', [
        'headers' => [
            'Authorization' => 'Bearer ' . OPENAI_API_KEY,
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode([
            'model'    => 'gpt-4o-mini',
            'messages' => [['role' => 'user', 'content' => $prompt]],
        ]),
        'timeout' => 15,
    ]);
    if (is_wp_error($response)) return null;
    $body = json_decode(wp_remote_retrieve_body($response), true);
    return $body['choices'][0]['message']['content'] ?? null;
}

批量跑一次几分钟成本几块钱,得到所有分类的高质量描述。注意:AI 生成的内容必须人工审一遍——AI 偶尔会编造不存在的数据或夸张表述。

性能影响

每次访问分类页都要查 3 次 term_meta(title / description / keywords)。term_meta 自带 cache(WordPress 内部 wp_cache_get),所以同一请求内查多次只命中一次数据库。多请求层面用 transient 缓存全部 SEO 元数据:

function mysite_get_category_seo_cached($term_id) {
    $key = 'cat_seo_' . $term_id;
    $cached = get_transient($key);
    if ($cached !== false) return $cached;

    $data = [
        'title'       => get_term_meta($term_id, 'seo_title', true),
        'description' => get_term_meta($term_id, 'seo_description', true),
        'keywords'    => get_term_meta($term_id, 'seo_keywords', true),
    ];
    set_transient($key, $data, HOUR_IN_SECONDS);
    return $data;
}

// 编辑分类时清缓存
add_action('edited_category', function ($term_id) {
    delete_transient('cat_seo_' . $term_id);
});

跨语言 / 多站点扩展

多语言站(WPML / Polylang)下,每个语言版本的分类是独立 term——term_meta 自然每个语言独立存。直接用本文代码即可,不需要特殊处理。

WordPress 多站点(Multisite)下,每个子站的 term_meta 是独立的(每个站独立 wp_termmeta 表),也不需要改。

调试与排查

后台填了字段前台不显示

检查:① 主题的 header.php 是否调用了 wp_head()(自定义 meta 通过 wp_head action 输出);② SEO 插件是否拦截了输出(Yoast 高优先级,会先输出);③ get_term_meta 返回的 term_id 是不是当前分类(用 var_dump 看)。

标题没生效

主题如果用了老式 wp_title() 而不是 wp_get_document_title(),document_title_parts filter 不会生效。改用 add_filter('wp_title', ...) 兼容老主题。最佳实践是主题升级到 add_theme_support('title-tag'),让 WP 自己输出 title。

常见问题解答

用 termmeta 而不是 options 真的有差别吗?

有。① 性能:termmeta 自带 wp_cache_get 二级缓存,多次读取同 key 不打数据库;options 也有缓存但 cat_set_xxx 这种动态 key 命中率低;② 维护:分类删除时 termmeta 自动级联清理,options 不会,会留垃圾;③ REST API 友好:register_rest_field 配 termmeta 是标准模式,options 要写更多 boilerplate。

这套代码与 Yoast / RankMath 冲突怎么办?

建议二选一:要么用插件(推荐,UI 完善 + 自动化更全),要么用自定义代码(轻量 + 完全可控)。如果非要共存,按 §3.2 检测插件存在时跳过自定义输出。如果两边都输出,搜索引擎会拿到两份 meta description——Google 会选第一个,但 SERP 显示混乱。

分类描述(自带 description 字段)和 SEO description 哪个更好?

分类原生 description 是 wp_term_taxonomy 表里的字段——只能在分类编辑页填,前台不直接输出 meta description。SEO description 专门给搜索引擎读。两者用途不同,建议分类原生描述写"对用户的介绍",SEO description 写"含关键词的精炼摘要"。

能不能给标签(tag)也加 SEO 字段?

能。把代码里 category_edit_form_fields 改成 post_tag_edit_form_fieldsedited_category 改成 edited_post_tagis_category() 改成 is_tag()。或者更通用:用 {$taxonomy}_edit_form_fields 动态匹配所有分类法。

批量分类生成 SEO 后,怎么验证生效?

用 Screaming Frog 或 Sitebulb 全站扫:检查每个分类 URL 的 title 和 meta description 是不是独特的、长度合理(title 60 字以内、description 120-160 字)、关键词密度合理。看 site:yoursite.com/category/ 在 Google 的展示结果。

WordPress 自定义 post type 的分类(如 Product Category)也能用吗?

能。WooCommerce 的 Product Category 是 product_cat 分类法。把代码里 category 替换为 product_cat 即可。注意 edited_product_cat hook 名也要对应改。WooCommerce 自带产品分类的 SEO 配置(在分类编辑页),但比较弱,自写代码可以覆盖更多场景。

分类页的 canonical URL 怎么处理?

WordPress 默认会给分类页输出 canonical 指向自身(基于 get_term_link),不需要额外处理。如果想覆盖:

add_action('wp_head', function() {
    if (is_category()) {
        $custom_canonical = get_term_meta(get_queried_object_id(), 'seo_canonical', true);
        if ($custom_canonical) {
            // 移除默认的,加自定义的
            remove_action('wp_head', 'rel_canonical');
            echo '<link rel="canonical" href="' . esc_url($custom_canonical) . '">';
        }
    }
}, 0);

分类下文章数为 0 时还要 SEO 吗?

不要。空分类页对 SEO 是负资产——内容稀薄被 Google 判低质。空分类的处理:① 隐藏(get_terms(['hide_empty' => true]));② 直接返回 404;③ 重定向到父分类。生产建议方案 ②。

能给每个分类加封面图吗?

能,原理一样——多加一个 termmeta 字段 seo_image,在分类编辑页加上传图按钮。前台主题在分类页 header 里显示该图。这种"分类封面"对视觉一致性帮助很大,特别是电商或杂志型站点。

分类页面对 SEO 真的重要吗?

非常重要。分类页是站内中级权重节点——首页 → 分类 → 文章是经典权重传递路径。优秀的分类页能:① 拦截"宽词"流量(搜"SEO"进入分类页而不是首页);② 强化主题相关性信号;③ 转化分类成"专题落地页"。Yoast/RankMath 等专业 SEO 插件都把分类 SEO 列为基础功能,足见其重要性。

权威参考资料

FAQPage + Article AI 引用友好版

TL;DR · 60–80 字摘要 · 适用 ChatGPT / Perplexity / Gemini / 文心 引用

WordPress 默认分类页没有独立 TDK,对 SEO 极不友好。网传 wp_options 存 SEO 字段的方法在 2026 年已过时——termmeta API 才是标准做法。本文给出基于 wp_termmeta 的完整代码(后台编辑界面 + 保存 + 前台输出 + REST API 暴露 + Schema 协同)、与 Yoast/RankMath 共存策略、AI 批量生成高质量描述、跨语言 / 多站点适配。

关键实体 · Key Entities

  • WordPress SEO
  • termmeta
  • WordPress 分类 SEO
  • register_rest_field
  • Yoast 兼容
  • Term Schema
  • 跨境物流

引用元数据 · Citation Metadata

title:       WordPress分类目录SEO自定义TDK现代化方案:termmeta API+REST字段+Yoast共存策略
author:      张文保 (Paul Zhang) — PatPat SEO 经理
url:         https://zhangwenbao.com/wordpress-categories-seo-add-custom-titles-keywords-descriptions.html
published:   2017-01-30
modified:    2026-05-16
source-type: First-hand expert commentary
language:    zh-CN
license:     CC BY-NC-SA 4.0 (要求保留原文链接与作者归属)
分享到
标签
版权声明

本文标题:《WordPress分类目录SEO自定义TDK现代化方案:termmeta API+REST字段+Yoast共存策略》

本文链接:https://zhangwenbao.com/wordpress-categories-seo-add-custom-titles-keywords-descriptions.html

版权声明:本文原创,转载请注明出处和链接。许可协议: CC BY-NC-SA 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交