WordPress 里 SEO 插件、schema 插件、llms.txt 生成器同时开着,怎么配置才不重复输出

简介: 页面跑了一段时间,某天打开 view-source,会发现 head 里躺着三块 Organization、两块 WebSite,robots.txt 里三行 Sitemap: 指向三个不同地址。站点不报错,页面也正常,可这些输出互相不认账。 解析方遇到同一页面里多份同类型的结构化数据,会自己挑一份用,你没法指定它挑哪份。这类重复多数不是插件写错了,而是分工没定下来:每一个输出面,整站只应该有一个 owner。

页面跑了一段时间,某天打开 view-source,会发现 head 里躺着三块 Organization、两块 WebSite,robots.txt 里三行 Sitemap: 指向三个不同地址。站点不报错,页面也正常,可这些输出互相不认账。

解析方遇到同一页面里多份同类型的结构化数据,会自己挑一份用,你没法指定它挑哪份。这类重复多数不是插件写错了,而是分工没定下来:每一个输出面,整站只应该有一个 owner。

先把现状量出来,别急着关开关

挑一个有代表性的页面(首页、一篇文章、一个产品或服务详情页各一次),在终端里跑:

# 每种 @type 在这个页面出现了几次
curl -sL https://example.com/ | grep -o '"@type":[[:space:]]*"[^"]*"' \
  | sort | uniq -c | sort -rn

# head 里到底有几块 JSON-LD
curl -sL https://example.com/ | grep -c 'application/ld+json'

# 谁在声明 sitemap
curl -sL https://example.com/robots.txt

# llms.txt 存不存在、内容是谁的
curl -sIL https://example.com/llms.txt | head -5
curl -sL https://example.com/llms.txt | head -20

计数里出现两次以上的 @type 就是待处理项。注意不同模板挂的组件可能不一样,产品页重复了不代表文章页也重复。

按输出面划 owner

不管装的是哪几个插件,判断逻辑是同一套:一个面,一个负责人,其余的要么关掉,要么退到不输出的位置。

输出面 owner 其他组件怎么处理
title / meta description / canonical / OG 标签 主 SEO 插件 第二个组件里对应的模块关掉,别让它也输出
XML sitemap 主 SEO 插件(或你手写的那份) 关掉 WordPress 内核 sitemap,只留一份入口
Organization / WebSite 一个 schema 输出者 另一个关掉;关不掉就用下文的兜底
Article / Product / FAQPage 等 与内容类型绑定的那一个 同一页面里搜一遍,确认没有两处都在输
llms.txt 只留一个生成者 插件生成的和手写的二选一,别并存
robots.txt 里的 Sitemap: 行 一行(最多两行指向同一份索引) 检查是不是三个插件各写一行

划 owner 的时候优先看“谁更懂这个页面的内容”。产品页的价格、库存这些字段,交给跟商品数据同源的那个组件;组织信息这种全站唯一的,交给主 SEO 插件或者你手写的一份就行。

把 WordPress 内核那份 sitemap 关掉

WordPress 内核从较早的版本开始自带 sitemap,和 SEO 插件的那份并存时,/wp-sitemap.xml 和 /sitemap_index.xml 会各说各的。加一行过滤就行,放进子主题的 functions.php 或者一个 mu-plugin:

add_filter( 'wp_sitemaps_enabled', '__return_false' );

这是运行时过滤,不用改 rewrite 规则,也不用重建固定链接。清一次页面缓存和 CDN 缓存再验证。

llms.txt 只留一个生成者

llms.txt 是个纯文本文件,格式很松:一级标题写站点名,一段引用块写这个站做什么、服务谁,下面按二级标题分组列链接和一句话说明。

想自己生成,加一条 rewrite 规则,输出纯文本:

add_action( 'init', function () {
   
    add_rewrite_rule( '^llms\.txt$', 'index.php?aum_llms=1', 'top' );
} );

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

add_action( 'template_redirect', function () {
   
    if ( '1' !== get_query_var( 'aum_llms' ) ) {
   
        return;
    }
    nocache_headers();
    header( 'Content-Type: text/plain; charset=utf-8' );

    echo "# 站点名\n\n";
    echo "> 一句话说明这个站做什么、服务哪类客户、覆盖哪些地区。\n\n";
    echo "## 主要页面\n";
    echo "- [关于](/about): 谁在做、怎么联系\n";
    echo "- [服务](/services): 提供什么、怎么报价、交期多久\n";
    echo "- [常见问题](/faq): 交付范围、修改次数、售后怎么走\n";
    exit;
} );

规则加完,去后台「设置 → 固定链接」点一次保存把 rewrite 刷掉,否则会 404。

这里有个容易踩的坑:如果网站根目录下还放着一份静态的 llms.txt 文件,请求会先命中静态文件还是先命中 PHP 路由,取决于 Web 服务器的匹配顺序。表现是你在插件后台改了内容,访问到的却还是那份旧的。改之前先用 curl -sI 看一眼响应头,确认命中的是哪一层。

我们的 AumViso 把 llms.txt、schema、sitemap 拆成各自独立的输出面,正因为它一次能覆盖这几样,和主 SEO 插件撞车的概率也高。插件页在:

https://aumcreate.com/plugins/aumviso?utm_source=aliyun&utm_medium=content&utm_campaign=aliyun-geo-suite-overlap-config

装之前先把上面的 owner 表填完,装完再把主 SEO 插件里对应的 sitemap 和 schema 输出关掉,剩下那一个手写的 llms.txt 路由也一并移除。

重复的 JSON-LD 块:先用这段兜底

插件内部过滤器的名字各不相同,改配置之前先上一段不依赖任何插件内部 API 的去重器,把整页输出接过来,同类型只保留第一次出现的块。

/**
 * 整页兜底:同一个 @type 只保留第一个 JSON-LD 块。
 * 放在子主题 functions.php 或 mu-plugin 里。
 */
add_action( 'template_redirect', function () {
   
    if ( is_admin() || wp_doing_ajax() || is_feed() ) {
   
        return;
    }

    $seen = array();

    ob_start( function ( $html ) use ( &$seen ) {
   
        return preg_replace_callback(
            '#<script[^>]*type=(["\'])application/ld\+json\1[^>]*>(.*?)</script>#is',
            function ( $m ) use ( &$seen ) {
   
                $data = json_decode( trim( $m[2] ), true );
                if ( null === $data ) {
   
                    return $m[0]; // 解析不了的块原样放行,别动它
                }

                $types = aum_collect_types( $data );
                $fresh = array_diff( $types, $seen );

                if ( empty( $fresh ) ) {
   
                    return ''; // 这一块的类型全都出现过了,整块丢掉
                }

                $seen = array_merge( $seen, $fresh );
                return $m[0];
            },
            $html
        );
    } );
} );

function aum_collect_types( $data ) {
   
    $out = array();
    if ( is_array( $data ) ) {
   
        if ( isset( $data['@type'] ) ) {
   
            foreach ( (array) $data['@type'] as $t ) {
   
                $out[] = $t;
            }
        }
        foreach ( $data as $v ) {
   
            if ( is_array( $v ) ) {
   
                $out = array_merge( $out, aum_collect_types( $v ) );
            }
        }
    }
    return array_values( array_unique( $out ) );
}

这段只做整块去重,不做块内合并:一个 @graph 里同时有 WebPage 和 Organization,而 Organization 已经被前面某块输出过,这一整块仍然会保留,重复也就留着。所以它适合当过渡期的止血带,不适合长期跑——整页缓冲会额外吃内存,和某些缓存组件配合时还要注意执行顺序。真正的解法还是把 owner 定下来,让重复从源头不再产生。

改完怎么验收

回到最开始那几条命令,逐条对一遍:

  • 每种 @type 的计数是 1,Product、Article 这类要看具体页面,首页不该出现。
  • curl -s https://example.com/ | grep -c 'application/ld+json' 的结果和页面实际需要输出的块数对得上,不是 5 块、6 块。
  • robots.txt 里指向 sitemap 的行只有一条,最多两条但都指向同一份索引。
  • /sitemap.xml 和 /sitemap_index.xml 只活一个,里面的 URL 数量和实际已发布的页面数在一个量级。
  • /llms.txt 返回 200,内容是最新的,末尾没有两份内容拼接的痕迹。
  • 结构化数据里写的价格、评分、面包屑,和页面上肉眼可见的内容一致。对不上的字段比重复更麻烦。
  • 用 Google 的富媒体搜索结果测试或者 Schema Markup Validator 各跑一页,看有没有“检测到多个实体”之类的提示。

关掉某个输出之后记得清缓存:页面缓存、对象缓存、CDN 三层都可能留着旧 HTML,改完没生效多半是这层没过。

最后一条经验:超过两个组件同时输出同一个面的时候,不要靠过滤器一个个打补丁。把不负责这个面的组件停掉,比写十行 array_diff 稳。

相关文章
|
云安全 安全 网络安全
|
7天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
2007 1
|
14天前
|
JSON 程序员 数据格式
最新版Notepad++下载、安装、配置保姆级教程(附官网安装包)
Notepad++ 是一款免费开源、轻量快速的 Windows 文本编辑器,支持多标签、语法高亮、代码折叠与宏录制,体积小、启动快、资源占用低,兼容 x64/x32/ARM 架构,是程序员和文字工作者的高效利器。
3160 0
|
13天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
2270 44
|
10天前
|
Web App开发 人工智能 前端开发
2026 年 AI 浏览器怎么选?Ego Lite、Tabbit、Chrome DevTools MCP 深度对比,开发者到底该用哪个?
2026年AI浏览器选型指南:Ego Lite专注多Agent协同(Mac优先),Tabbit国产首选,原生支持Windows与Codex控制;Chrome DevTools MCP非浏览器而是开发者利器,深度集成Console/Network/Performance调试能力,让AI真正“看懂并验证”前端代码。
1421 3
|
7天前
|
安全 应用服务中间件 Go
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
PHP2Shell 双 RCE 已遭在野利用:WordPress、Drupal 全在射程内,nginx 其实另有洞。拆成因与修复顺序
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
|
8天前
|
开发者 索引
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
Open Plugin Market 是一个开放插件索引平台,收录800+优质DSH插件,支持分类浏览、智能推荐与随机发现。无需安装市场,粘贴索引地址即可一键接入,网页版直访 dshopen.org,助力小开发者被看见。(239字)
1711 1
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
|
6天前
|
人工智能 Linux API
Magpie, 轻量本地AI网关!免费Token用不完!
Magpie 是开源AI编程模型调度网关,上线一月获1.8万Star。它通过本地高性能网关统一托管多平台API密钥、账号与免费额度,实现跨Agent的模型秒级切换、静默额度轮换与资源复用,显著降低碎片化管理成本。(239字)
Magpie, 轻量本地AI网关!免费Token用不完!
|
6天前
|
安全 程序员 应用服务中间件
PHP 被曝两大致命漏洞,请所有程序员抓紧做这件事!
PHP 官方发布了紧急安全更新,一口气修复了两个严重漏洞。如果网站和服务器用了 PHP 应该怎么处理?漏洞的原理是什么?本文给你讲清楚
698 0

热门文章

最新文章