SEO 运维
这套系统的 SEO 不是"装个插件"级别的,而是写在架构里:服务端直出、干净 URL、子目录多语言、结构化数据全部自动输出。你要做的只是"填对字段 + 别踩坑"。
一、系统内置了什么
| 能力 | 默认状态 | 说明 |
|---|---|---|
| 服务端直出 HTML | 始终 | 不用 SPA,爬虫拿到的是完整内容 |
| 干净 URL | 始终 | /en/products/cnc-housing.html,无 ?id= |
| canonical 自指 | 始终 | 每个页面自动输出;支持栏目/内容单独覆盖 |
| hreflang 互指 | 多语言时 | 含 x-default,指向默认语言版本 |
| JSON-LD 结构化数据 | 始终 | Organization / WebSite+SearchAction / BreadcrumbList / Product / Article / FAQPage |
| 分语言 sitemap | 开启 | /sitemap.xml 是索引,/sitemap-en.xml 是单语言 |
| robots.txt | 动态生成 | 自动带 Sitemap 声明 |
| 真 404 | 始终 | 不存在的 URL 返回 HTTP 404 + 主题 404 页,不是 200 软 404 |
| 301 跳转表 | 可配 | 后台维护,老站链接迁移不丢权重 |
| 静态化 HTML | 开启 | 整页缓存,TTFB 从 80ms 降到 5ms 级 |
| 图片优化 | 上传即做 | 转 WebP + 三尺寸 + 页面输出 width/height(防 CLS) |
| noindex 控制 | 按内容 | 内容可单独勾选 noindex(草稿、感谢页等) |
二、每个页面输出什么
标题规则
<title>{页面标题} | {站点名称}</title>
| 优先级 | 取值来源 |
|---|---|
| 1(最高) | 内容 / 栏目的 seo_title 字段 |
| 2 | 内容 / 栏目的 title 或 name |
| 3(兜底) | 站点设置里的 site_title |
拼接格式可在后台改:站点设置 → seo_title_format,默认 {title} | {site_name}。首页不拼接,直接用 seo_index_title。
描述与关键词
- 描述优先取
seo_description,没有就取内容摘要summary,再没有就取全站site_description,最后统一截到 300 字符 - 关键词取
seo_keywords,空则用全站site_keywords(Google 已不看 keywords,但 Bing 与部分新兴引擎仍读)
URL 别名(slug)怎么生成
栏目和内容都有一个「URL 别名」字段,它直接决定页面地址。留空时系统自动生成,按外贸 SEO 规则处理:
| 顺序 | 处理方式 | 举例 |
|---|---|---|
| 1 | 手工填了别名 | 只保留 a-z 0-9 -,大写转小写,空格与下划线转 -,其余字符剔除 |
| 2 | 标题含中文 → 自动译成英文再 slug 化 | 「钕铁硼强磁 N35」→ neodymium-magnet-n35 |
| 3 | 翻译不可用 → 中文转拼音 | 「联系我们」→ lian-xi-wo-men |
| 4 | 以上都不行 → 哈希兜底 | p143535addb(保证唯一、不报错,但不建议留着) |
https://site.com/en/products/neodymium-magnet-n35.html
https://site.com/en/news/how-to-choose-magnet-grade.html
Google 把 URL 里的关键词当作弱排名信号,也会在结果页把 URL 显示给用户。
拼音对海外买家完全不可读(lian-xi-wo-men 不如 contact-us),
所以系统优先译英;确实没有翻译引擎时才退回拼音,请人工改成英文。
已收录的页面改别名等于换地址,旧地址会 404 掉权重。改之前先在「301 跳转」里加一条旧 → 新的映射。 另:同一语言下 slug 必须唯一,重复时系统会自动加后缀。
hreflang 怎么配对
栏目表和内容表都有一个 trans_key 字段。两个语言的"同一篇内容"填相同的 trans_key,系统就会自动生成互指的 hreflang 并补上 x-default。
<link rel="alternate" hreflang="en" href="https://site.com/en/products/cnc-housing.html">
<link rel="alternate" hreflang="zh-CN" href="https://site.com/zh-cn/products/cnc-housing.html">
<link rel="alternate" hreflang="x-default" href="https://site.com/en/products/cnc-housing.html">
① 必须**互指**(A 指向 B,B 也要指向 A);② 必须**包含自身**;③ 必须有 x-default。系统已自动处理,你只要保证 trans_key 成对填写。
三、结构化数据
| 类型 | 输出位置 | 来源 |
|---|---|---|
| Organization | 全站 | 站点设置:公司名、logo、电话、邮箱、地址、社交链接 |
| WebSite + SearchAction | 首页 | 自动(站内搜索框) |
| BreadcrumbList | 内页 | 面包屑数据自动转换 |
| Product + Offer | 产品详情 | 型号、价格、货币、库存状态 |
| Article | 新闻/博客详情 | 标题、图片、发布时间、作者 |
| FAQPage | 手动 | Seo::faq(),插件或自定义模板调用 |
验证方式:Google 富媒体结果测试(search.google.com/test/rich-results)粘贴 URL,或浏览器查看源码搜 application/ld+json。
价格必须是数字(不要带 $ 与千分位逗号);priceCurrency 必须与站点货币一致(后台设置 currency,默认 USD)。
四、静态化缓存
开启后,第一次访问生成 HTML 存到 runtime/html/{语言}/{hash}.html,后续访问直接输出文件,不查库、不渲染模板。
| 配置项 | 默认 | 说明 |
|---|---|---|
| 开关 | 开 | 后台 SEO 工具里一键切换 |
| 有效期 TTL | 3600 秒 | config/tw.php 的 html_cache.ttl,0 表示永久 |
| 排除路径 | search / message / api / captcha | 这些页面不缓存(有表单或随机内容) |
| 带参数页面 | 不缓存 | 避免 ?page= 参数污染缓存 |
怎么确认命中了
浏览器 F12 → Network → 刷新首页 → 看响应头有没有 X-TW-Cache: HIT(未命中是 MISS 或没有该头)。也可以在 SEO 工具页看"缓存页面数"。
什么时候必须清缓存
- 改了内容、栏目、站点设置
- 启停插件
- 换了主题
- 改了模板里影响全站的片段(header/footer)
入口:后台右上角「清缓存」或 SEO 工具 → 清理静态化缓存。按语言清理用 HtmlCache::clearLang('zh-cn')。
五、301 跳转
后台 → SEO 工具 → 301 跳转,一条记录四件事:
| 字段 | 说明 |
|---|---|
| 来源路径 | 老 URL 的路径部分,如 /old-products.html(不要写域名) |
| 目标路径 | 新 URL,可写站内路径或完整外链 |
| 状态码 | 301 永久(推荐)/ 302 临时 |
| 状态 | 启用 / 停用 |
命中顺序:请求进来 → 先查跳转表 → 再查静态化缓存 → 再走正常分发。所以跳转永远优先,且跳转本身不缓存。
逐条对应"老 URL → 新 URL",不要把老站所有页面 301 到首页(Google 判定为软 404,等于放弃这些页面的权重)。批量导可以用 SQL 直接写 tw_redirect 表。
六、sitemap 与 robots
| 地址 | 内容 |
|---|---|
/sitemap.xml | 索引文件,列出各语言的子 sitemap |
/sitemap-en.xml | 英文站全部栏目页 + 内容页(含 lastmod 与 priority) |
/sitemap-zh-cn.xml | 中文站同上 |
/robots.txt | 动态生成,含 Sitemap: 声明;后台可关闭 |
提交入口:Google Search Console → 站点地图 → 填 sitemap.xml;Bing Webmaster 同理。提交索引文件即可,子文件会自动被发现。
七、多语言 SEO 要点
- 用子目录,不用子域名:
/zh-cn/能继承主域权重,zh.site.com等于从零开始 - 每语言独立内容,不要机翻整站:Google 对低质量翻译的容忍度极低
- 语言代码规范:
en、zh-cn、de、ar;hreflang 用zh-CN这种带地区的格式(系统按语言的region字段输出) - URL 结构一致:两种语言的 slug 可以不同,但层级要一致(
/en/products/xxx.html↔/zh-cn/products/xxx.html) - RTL 语言(阿拉伯语/希伯来语)会自动输出
dir="rtl",主题 CSS 要用逻辑属性(margin-inline-start而不是margin-left)
八、上线 SEO 检查清单
技术层
- 全站 HTTPS,HTTP 自动 301 到 HTTPS
www与非www只保留一个(另一个 301)- 访问不存在的 URL 返回 真 404(用
curl -I验证状态码) /sitemap.xml、/robots.txt均可访问且内容正确- 关键 CSS 内联或提前加载;字体
display=swap - 所有图片有
alt、有width/height、懒加载(首屏图不要 lazy) - 移动端 100% 可用(Google 移动优先索引)
内容层
- 每个栏目/内容都填了
seo_title(≤ 60 字符)与seo_description(120~155 字符) - H1 全页只有一个,且与 title 不完全重复
- 产品页有型号、MOQ、价格(哪怕写 "Contact us"),便于 Product 结构化数据
- 正文 ≥ 300 字,有内链指向相关产品或栏目
- 无空栏目、无空列表页(宁可先 noindex)
上线后
- Search Console 提交 sitemap,观察"已编入索引"数量
- Bing Webmaster 同步提交(Bing 收录快,且喂给 ChatGPT 搜索)
- 每周看:索引覆盖、Core Web Vitals、查询词排名
- 老站有流量的 URL 全部做了 301,观察 3 周内排名是否恢复
九、常见 SEO 错误
| 错误 | 后果 / 修正 |
|---|---|
| 所有页面 title 一样 | 系统会按页面取,但如果栏目都留空,就全用全站默认 → 逐栏目填 seo_title |
| 空列表页被收录 | Google 判低质 → 给空栏目加 noindex 或先不发布 |
| 分页页 index,follow 且 canonical 指向第一页 | 正确做法:分页页 canonical 自指(系统已这样做) |
| 机翻内容全站铺开 | 极易被判 spam → 至少保证核心产品页人工翻译 |
| sitemap 里混入 noindex 页面 | 系统已过滤草稿与 noindex,别手工改 |
| 老站直接换域名不做 301 | 权重清零 → 用跳转表逐条映射 |
| 静态化开了但改内容不清理 | 用户和爬虫看到的都是旧内容 → 后台改完就点清缓存 |
十、版本与升级
框架与后台 UI 都是新版本,不需要定期升级。真遇到更新时:
| 组件 | 当前 | 怎么办 |
|---|---|---|
| ThinkPHP | 8.1.4(已是最新稳定) | 8.1.x 小版本可跟,替换 vendor/topthink/framework 后重建 autoload;8.2 以上主版本不升 |
| LayUI | 2.12.0 | 整目录替换 public/static/layui 即可;2.13 有 element 拆分破坏性变更,升级后必须验证后台菜单与表单 |
- 先备份(目录 + 数据库)
- 在测试站升级,跑一遍:首页 / 列表 / 详情 / 搜索 / 询盘 / 后台登录 / 上传 / 静态化
- 无误后再动正式站;出问题用备份回滚
能用就别升。升级的唯一理由是安全补丁或你需要的新特性。