[{"data":1,"prerenderedAt":343},["ShallowReactive",2],{"blog-cls-chat-widget-fix":3,"blog-prev-cls-chat-widget-fix":113,"blog-next-cls-chat-widget-fix":246},{"id":4,"title":5,"author":6,"body":7,"canonical":97,"category":98,"cover":97,"date":99,"description":100,"draft":101,"extension":102,"keywords":97,"meta":103,"navigation":104,"noindex":101,"ogImage":97,"path":105,"seo":106,"seoDescription":97,"seoTitle":97,"stem":107,"tags":108,"updated":97,"__hash__":112},"blog\u002Fblog\u002Fcls-chat-widget-fix.md","客服组件把 CLS 顶到零点二八，我们最后是这么治的","元析智能",{"type":8,"value":9,"toc":87},"minimark",[10,14,17,21,24,27,31,34,37,41,44,47,50,53,56,59,62,75,78,81,84],[11,12,13],"p",{},"今年 11 月我们接了一个 B2B SaaS 的移动端 CLS 问题，0.28，折腾了三个星期才压到 0.03。最后发现是两个\"看不见\"的组件在挪页面：cookie 同意条和客服窗口。",[11,15,16],{},"这类问题麻烦在于责任不清：开发觉得不是自己写的代码，市场觉得组件是现成的，谁都不认领。",[18,19,20],"h2",{"id":20},"症状和一次误判",[11,22,23],{},"GSC 报告里移动端 CLS 0.28，桌面端 0.06。Lighthouse 报的位移元素是 hero 下面那段介绍文字。前端第一反应是图片没尺寸，补了两张图的宽高，分数一动不动。",[11,25,26],{},"我们用 Performance 录了 10 次移动端加载，Experience 轨道上有三次明显位移，时间点都在 1.8 秒之后。这个时间点说明不是资源加载，是 JS 执行后插进来的东西。",[18,28,30],{"id":29},"真凶一cookie-同意条","真凶一：cookie 同意条",[11,32,33],{},"合规组件在 DOMContentLoaded 后往 body 顶部插了一条 64 像素高的同意条，整页下移。更糟的是它异步加载，有时 1.2 秒到，有时 2.6 秒到，Lighthouse 跑五次有两次抓不到。",[11,35,36],{},"改法：把同意条改成 fixed 定位放底部，不占文档流；或者在 HTML 里预留 64 像素占位。我们选 fixed，因为它本来就是临时提示，挡在底部比推开整页合理。",[18,38,40],{"id":39},"真凶二客服窗口","真凶二：客服窗口",[11,42,43],{},"客服组件打开时，它的 iframe 从 0 高度撑到 420 像素。窗口本身是 fixed，但它内部有个\"推荐问题\"列表是普通文档流，加载完把窗口里的标题顶下去。这部分位移照样被算进 CLS。",[11,45,46],{},"改法是给 iframe 容器写死高度加 overflow，内部列表自己滚动。改完客服窗口打开时页面纹丝不动。",[18,48,49],{"id":49},"结果和流程上的收获",[11,51,52],{},"三周后移动端 CLS 从 0.28 到 0.03，桌面端从 0.06 到 0.01。",[11,54,55],{},"比数字更有用的是一条规矩：任何第三方组件上线前，必须用移动端 4G 跑五次加载，看有没有位移。这条已经写进客户的验收清单，后面新接的客服系统也是这么过的。",[18,57,58],{"id":58},"一个可复用的检查办法",[11,60,61],{},"我们把这个流程做成了三步，客户自己也能跑：",[63,64,65,69,72],"ol",{},[66,67,68],"li",{},"Chrome DevTools 打开移动端模拟、4G 加 4 倍 CPU 降速，连续刷新五次",[66,70,71],{},"每次录 Performance，只看 Experience 轨道上的 Layout Shift，记下位移元素和时间点",[66,73,74],{},"把时间点和网络面板里第三方脚本的加载时间对照，谁在后面就是谁",[11,76,77],{},"这个办法不依赖任何付费工具，前端和后端都能上手。真正难的是第五次才复现出来的那种问题——所以次数不能省，一次两次不够。",[18,79,80],{"id":80},"顺带修掉的一个坑",[11,82,83],{},"排查时我们还发现客服组件的脚本和 cookie 组件各自引入了同一份 polyfill，重复下载 34KB。换掉之后移动端 LCP 也顺带好了 0.2 秒。第三方组件的代价通常不止位移一项，趁着排查一起看。",[11,85,86],{},"如果你也在查 CLS，别只盯自己的代码。现在页面上一半的位移来自别人塞进来的东西，而且它们往往在页面\"看起来加载完了\"之后才动手。",{"title":88,"searchDepth":89,"depth":89,"links":90},"",2,[91,92,93,94,95,96],{"id":20,"depth":89,"text":20},{"id":29,"depth":89,"text":30},{"id":39,"depth":89,"text":40},{"id":49,"depth":89,"text":49},{"id":58,"depth":89,"text":58},{"id":80,"depth":89,"text":80},null,"技术SEO","2025-11-26","一个 B2B SaaS 移动端 CLS 0.28，补了图片宽高完全没用。真凶是 cookie 同意条和客服窗口两个第三方组件，三周压到 0.03，附上我们总结的第三方组件验收规矩。",false,"md",{},true,"\u002Fblog\u002Fcls-chat-widget-fix",{"title":5,"description":100},"blog\u002Fcls-chat-widget-fix",[109,110,111],"CLS","第三方组件","客服系统","W48zf9rIvJk5HxzYTPpfwYADND4us8s3DSRSiEXHhss",{"id":114,"title":115,"author":6,"body":116,"canonical":97,"category":98,"cover":97,"date":235,"description":236,"draft":101,"extension":102,"keywords":97,"meta":237,"navigation":104,"noindex":101,"ogImage":97,"path":238,"seo":239,"seoDescription":97,"seoTitle":97,"stem":240,"tags":241,"updated":97,"__hash__":245},"blog\u002Fblog\u002Fdomain-migration-12-steps.md","换域名的 12 步清单，少一步掉一批词",{"type":8,"value":117,"toc":228},[118,121,125,164,167,206,210,213,216,219,222,225],[11,119,120],{},"换域名不是技术活，是项目管理活。技术部分两小时能做完，项目部分漏一项就要掉一个月的流量。下面是我们自己执行的 12 步，按时间顺序。",[18,122,124],{"id":123},"迁移前-4-周","迁移前 4 周",[63,126,127,134,140,146,152,158],{},[66,128,129,133],{},[130,131,132],"strong",{},"盘点旧站流量","：GSC 和百度搜索资源平台导出近 90 天有点击的 URL，按点击排序，前 500 个是必须优先保住的。",[66,135,136,139],{},[130,137,138],{},"冻结改版","：迁移前后各两周不做内容改版、不改 URL 结构，两件事叠在一起，出问题分不清原因。",[66,141,142,145],{},[130,143,144],{},"建 301 映射表","：旧 URL 一列、新 URL 一列，逐条核对。没有这张表别上线。",[66,147,148,151],{},[130,149,150],{},"测试环境全量爬一遍","：Screaming Frog 爬新站，确认没有 404、没有循环重定向、没有 noindex 残留。",[66,153,154,157],{},[130,155,156],{},"确认基础设施","：新域名的 DNS、SSL 证书、CDN 配置、SPF 记录，提前一周准备好。",[66,159,160,163],{},[130,161,162],{},"通知相关方","：销售、客服、市场手里的旧链接清单，邮件签名、文档站、SDK 里的域名都要列出来。",[18,165,166],{"id":166},"上线当天",[63,168,170,176,182,188,194,200],{"start":169},7,[66,171,172,175],{},[130,173,174],{},"四个组合全做 301","：http 和 https、www 和非 www，四个变体都要跳到新域对应地址。2025 年 6 月一个 B2B 软件站只做了主域名，忘了 www 变体，两个域名同时在线三周，自然流量掉了 62%。",[66,177,178,181],{},[130,179,180],{},"sitemap 换新域名","，robots.txt 里的 Sitemap 声明同步改。",[66,183,184,187],{},[130,185,186],{},"站内绝对链接替换","，包括文档里的硬编码 URL 和邮件模板。",[66,189,190,193],{},[130,191,192],{},"两边资源都保留","：GSC 和百度搜索资源平台同时挂旧域和新域，旧域不要删，观察期至少三个月。",[66,195,196,199],{},[130,197,198],{},"提交改版","：GSC 有换域名的专用入口，百度用抓取诊断逐条验证新 URL 可抓。",[66,201,202,205],{},[130,203,204],{},"更新高权重外链","：能改的合作伙伴链接、目录、社区主页，一周内改完。",[18,207,209],{"id":208},"上线后-8-周","上线后 8 周",[11,211,212],{},"日志里看旧域名是否还有大量 404（说明漏了映射），收录曲线看新域是否在涨、旧域是否在退，排名监控看核心词有没有掉出前 20。前两周流量掉 10% 到 20% 是正常的，别急着回滚。那次掉 62% 的站，补完四个变体的 301 之后第 7 周恢复到原来的 9 成。",[18,214,215],{"id":215},"迁移后最容易漏的两件事",[11,217,218],{},"一是站内绝对链接。后台编辑器里存的内容，很多是硬编码的旧域名，换域名后文章里的图全部裂掉，蜘蛛抓到的也是坏链。上线后拿爬虫扫一遍全站图片和链接，能捞出几百条。",[11,220,221],{},"二是第三方资源。SDK 的默认域名、GitHub 上示例代码里的地址、App 里的接口域名。这些不在网站范围内，但用户和开发者会照着文档复制，旧域名一停服务就报错。",[18,223,224],{"id":224},"一句实话",[11,226,227],{},"迁移期间最容易犯的错是\"顺手优化一下\"。换个域名就别动目录结构，改完目录再改域名，出问题你会查两周。分两次做，每次只改一个变量。",{"title":88,"searchDepth":89,"depth":89,"links":229},[230,231,232,233,234],{"id":123,"depth":89,"text":124},{"id":166,"depth":89,"text":166},{"id":208,"depth":89,"text":209},{"id":215,"depth":89,"text":215},{"id":224,"depth":89,"text":224},"2025-11-25","域名迁移我们做过 9 次，最惨一次掉了 62% 的自然流量，原因是旧域名 301 只做了一半。这份 12 步清单按时间顺序排，从迁移前 4 周的准备到上线后 8 周的观察。",{},"\u002Fblog\u002Fdomain-migration-12-steps",{"title":115,"description":236},"blog\u002Fdomain-migration-12-steps",[242,243,244],"网站迁移","域名",301,"HqMzkGNqGQHUfdqodZHUHklgrXZIpo7hOc7DvMAQOVA",{"id":247,"title":248,"author":6,"body":249,"canonical":97,"category":332,"cover":97,"date":333,"description":334,"draft":101,"extension":102,"keywords":97,"meta":335,"navigation":104,"noindex":101,"ogImage":97,"path":336,"seo":337,"seoDescription":97,"seoTitle":97,"stem":338,"tags":339,"updated":97,"__hash__":342},"blog\u002Fblog\u002Fqa-format-ai-citation.md","问答式内容怎么写才容易被 AI 引用",{"type":8,"value":250,"toc":323},[251,254,257,260,263,266,269,272,275,278,281,284,287,290,293,296,299,302,305,308,311,314,317,320],[11,252,253],{},"AI 引擎偏爱问答，原因很实际：问题句本身就是它要匹配的检索式。你写“关于接口鉴权的说明”，它没法判断这段该配哪个问题；你写“接口鉴权失败 401 怎么办”，匹配是直接的。",[18,255,256],{"id":256},"什么内容适合问答",[11,258,259],{},"操作类、对比类、价格类、选型类，都适合。叙述类、观点类、复盘类，不适合硬套问答。",[11,261,262],{},"我们给一个开发者工具站改过 47 个问题句，集中在文档页和对比页。三个月里，ChatGPT 和 Perplexity 引用这些页面的次数从 2 次增加到 9 次，都是问“XX 怎么配置”“XX 和 YY 区别”这类具体问题。",[18,264,265],{"id":265},"问题句要照抄用户的问法",[11,267,268],{},"不要写“鉴权机制说明”当问题，要写用户真实会打的字：“API 返回 401 是什么原因”。带上主语和场景，问法越像搜索框里的，匹配越准。",[11,270,271],{},"怎么拿到真实问法：搜索后台的查询词、客服工单标题、知乎提问、必应和谷歌的“其他人还问”。",[18,273,274],{"id":274},"答案第一句就是答案",[11,276,277],{},"每个答案的前 40 到 60 个字必须直接给结论，后面再补前提和例外。",[11,279,280],{},"反例：“这个问题的原因是多方面的，需要结合具体情况分析……”这种开头在 AI 摘录里会被整段跳过。",[11,282,283],{},"正例：“401 通常是 token 过期或签名不对。先看响应头的 WWW-Authenticate 字段，它一般会写明是哪种。”",[18,285,286],{"id":286},"一个页面放几个问答",[11,288,289],{},"3 到 8 个。少于 3 个没必要单独做 Q&A 区块，超过 10 个该拆页。",[11,291,292],{},"每个问题之间要有区分度。同一个页面里放“XX 是什么”和“XX 的定义”，等于自己跟自己抢。",[18,294,295],{"id":295},"结构标记和标题",[11,297,298],{},"FAQ 用 H3 提问，答案紧跟段落，别把答案拆成列表。可以加 FAQPage 结构化数据，但别指望它带来富摘要，它的价值在让引擎更容易切分内容。",[11,300,301],{},"顺带一句，问答区块放在页面正文之后，别放最前面。正文给读文章的人，问答给搜具体问题的人。",[18,303,304],{"id":304},"常见的一个误区",[11,306,307],{},"很多站把问答当装饰，页面底部挂五条“XX 是什么”“XX 有什么用”的通用问题。这种问答对引用没有帮助，因为它问的不是具体问题，答案也只能是概念复述。",[11,309,310],{},"有效的问答是带条件的：“免费版够 10 个人用吗”“换服务器后 license 要重新激活吗”。这类问题的答案有明确边界，引擎才敢引用。",[18,312,313],{"id":313},"改完怎么验证",[11,315,316],{},"我们每月查一次：把 20 个目标问题原样丢给 ChatGPT 和 Perplexity，记录有没有引用我们的页面。这个动作 2025 年 9 月就固定下来了，每月大约花 40 分钟。",[11,318,319],{},"连续两个月没被引用的页，回头检查问题句和答案第一句。多数情况是答案写得太绕，前 60 个字里没给结论。",[11,321,322],{},"问答不是排版技巧，是把用户的原话放到页面上。",{"title":88,"searchDepth":89,"depth":89,"links":324},[325,326,327,328,329,330,331],{"id":256,"depth":89,"text":256},{"id":265,"depth":89,"text":265},{"id":274,"depth":89,"text":274},{"id":286,"depth":89,"text":286},{"id":295,"depth":89,"text":295},{"id":304,"depth":89,"text":304},{"id":313,"depth":89,"text":313},"GEO","2025-11-27","AI 引擎喜欢问答，不是因为格式好看，是问题句本身就是检索式。问题要照抄用户问法，答案第一句就给结论。我们给一个开发者工具站加了 47 个问题句，三个月里被引用从 2 次到 9 次。",{},"\u002Fblog\u002Fqa-format-ai-citation",{"title":248,"description":334},"blog\u002Fqa-format-ai-citation",[340,341,332],"问答内容","AI引用","1S3L6PgRYefBBg3LmUSjeZy4PauGPCda0ACrBszKBNc",1794088110535]