[{"data":1,"prerenderedAt":374},["ShallowReactive",2],{"blog-url-parameter-governance":3,"blog-prev-url-parameter-governance":192,"blog-next-url-parameter-governance":283},{"id":4,"title":5,"author":6,"body":7,"canonical":176,"category":177,"cover":176,"date":178,"description":179,"draft":180,"extension":181,"keywords":176,"meta":182,"navigation":183,"noindex":180,"ogImage":176,"path":184,"seo":185,"seoDescription":176,"seoTitle":176,"stem":186,"tags":187,"updated":176,"__hash__":191},"blog\u002Fblog\u002Furl-parameter-governance.md","URL 参数治理：筛选、排序、追踪参数要分开处理","元析智能",{"type":8,"value":9,"toc":167},"minimark",[10,14,18,25,31,37,41,49,52,55,58,134,137,141,148,151,154,157,160,163],[11,12,13],"p",{},"参数治理的关键是分类，不是统一 canonical。功能参数、追踪参数、变体参数的处理方式完全不同，混着来一定出问题。",[15,16,17],"h2",{"id":17},"三类参数",[11,19,20,24],{},[21,22,23],"strong",{},"功能型","：筛选、排序、分页。这类参数用户真的会用，蜘蛛也会抓。保留，但要给规则：列表页 canonical 指向不带参数的版本，分页页 canonical 自指（别指向第一页），有独立搜索价值的筛选组合才允许单独成页。",[11,26,27,30],{},[21,28,29],{},"追踪型","：utm 系列、gclid、fbclid、ref、source。对内容没有任何影响，是纯噪声。最优解是在链接生成环节就不加，其次是在服务器或 CDN 层 302 清洗到干净 URL。",[11,32,33,36],{},[21,34,35],{},"变体型","：版本、语言、打印版、移动版。这类本质上不是参数问题，是路径设计问题。已经用参数的做 301 收编到路径，新页面别再犯。",[15,38,40],{"id":39},"_2025-年-12-月那个数据工具站","2025 年 12 月那个数据工具站",[11,42,43,44,48],{},"站内导航链接全都自动带 ",[45,46,47],"code",{},"?source=nav","，加上分享和投放链接，蜘蛛抓到了 3.4 万个带参数的 URL，GSC 里\"重复网页\"报了 2.1 万。客户的第一反应是加 canonical，但问题出在模板。",[11,50,51],{},"我们在模板里去掉 source 参数，nginx 上加一条规则 302 清洗 utm 和 gclid。三周后重复网页降到 4000，蜘蛛对产品页的抓取频次涨了 2.2 倍。",[15,53,54],{"id":54},"怎么查",[11,56,57],{},"日志里把 URL 的查询串提取出来，按参数名统计抓取次数：",[59,60,65],"pre",{"className":61,"code":62,"language":63,"meta":64,"style":64},"language-bash shiki shiki-themes github-light github-dark","grep \"Googlebot\" access.log | awk -F'?' '{print $2}' | cut -d'&' -f1 | sort | uniq -c | sort -rn\n","bash","",[45,66,67],{"__ignoreMap":64},[68,69,72,76,80,83,87,90,94,97,100,102,105,108,111,114,116,119,121,124,127,129,131],"span",{"class":70,"line":71},"line",1,[68,73,75],{"class":74},"sScJk","grep",[68,77,79],{"class":78},"sZZnC"," \"Googlebot\"",[68,81,82],{"class":78}," access.log",[68,84,86],{"class":85},"szBVR"," |",[68,88,89],{"class":74}," awk",[68,91,93],{"class":92},"sj4cs"," -F",[68,95,96],{"class":78},"'?'",[68,98,99],{"class":78}," '{print $2}'",[68,101,86],{"class":85},[68,103,104],{"class":74}," cut",[68,106,107],{"class":92}," -d",[68,109,110],{"class":78},"'&'",[68,112,113],{"class":92}," -f1",[68,115,86],{"class":85},[68,117,118],{"class":74}," sort",[68,120,86],{"class":85},[68,122,123],{"class":74}," uniq",[68,125,126],{"class":92}," -c",[68,128,86],{"class":85},[68,130,118],{"class":74},[68,132,133],{"class":92}," -rn\n",[11,135,136],{},"排前面的参数就是治理重点。Screaming Frog 的 URL 参数报告能看站内链接里有多少带参数，这个数字比日志更能说明问题——站内链接是我们自己能控制的。",[15,138,140],{"id":139},"一个例外值得单独成页的筛选组合","一个例外：值得单独成页的筛选组合",[11,142,143,144,147],{},"不是所有筛选参数都该压掉。如果某个组合有稳定的搜索需求，比如\"北京 + 三年经验\"这类招聘筛选、\"100 人以下团队 + 项目协作\"这类软件筛选，单独做一个静态页比让参数页参与排名更好。判断标准是搜索量：GSC 里这类词每月有几十次展示，就值得做成 ",[45,145,146],{},"\u002Fsolutions\u002Fsmall-team"," 这样的路径页。",[11,149,150],{},"判断做不做，看两件事：这个词有没有独立搜索需求，页面内容能不能撑满 600 字。两个都满足就做成路径页，只有一个满足就留在参数里。",[15,152,153],{"id":153},"规则写在哪",[11,155,156],{},"优先级从高到低：模板生成规则 > 服务器 302 清洗 > canonical > robots 屏蔽。前面能解决的，不要留给后面。canonical 是声明不是限制，蜘蛛可以不遵守；robots 是屏蔽不是清理，被挡的 URL 仍然可能被索引。",[15,158,159],{"id":159},"立场",[11,161,162],{},"参数治理是工程问题，不是 SEO 问题。让前端改参数生成逻辑，比上线后加一百条规则都有效。做 SEO 的人要能跟开发说清楚\"这条链接为什么不能带这个参数\"。",[164,165,166],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":64,"searchDepth":168,"depth":168,"links":169},2,[170,171,172,173,174,175],{"id":17,"depth":168,"text":17},{"id":39,"depth":168,"text":40},{"id":54,"depth":168,"text":54},{"id":139,"depth":168,"text":140},{"id":153,"depth":168,"text":153},{"id":159,"depth":168,"text":159},null,"技术SEO","2026-03-04","三种参数混在一起治理，是软件站重复内容的源头。我们把参数分三类，给每类定规则：哪些进 canonical、哪些交给服务器清洗、哪些在链接生成时就掐掉。",false,"md",{},true,"\u002Fblog\u002Furl-parameter-governance",{"title":5,"description":179},"blog\u002Furl-parameter-governance",[188,189,190],"URL参数","重复内容","canonical","FGb6TFLxOPkM6K52CqiVecaxcw_sCYqynHPYdFtg-HA",{"id":193,"title":194,"author":6,"body":195,"canonical":176,"category":271,"cover":176,"date":272,"description":273,"draft":180,"extension":181,"keywords":176,"meta":274,"navigation":183,"noindex":180,"ogImage":176,"path":275,"seo":276,"seoDescription":176,"seoTitle":176,"stem":277,"tags":278,"updated":176,"__hash__":282},"blog\u002Fblog\u002Fgsc-api-export-script.md","用 GSC API 拉全量数据，别再手点导出了",{"type":8,"value":196,"toc":263},[197,200,203,206,209,212,215,218,221,224,227,230,233,236,239,242,245,248,251,254,257,260],[11,198,199],{},"GSC 网页界面导出有两个硬限制：一次最多 1000 行，数据只保留 16 个月。想按查询加页面组合看，或者想留三年数据做对比，只能走 API。2026 年 3 月我们把三个客户站的数据全部改成 API 拉取，每周自动更新。",[15,201,202],{"id":202},"为什么不用界面导出",[11,204,205],{},"一是行数限制。一个中型站有几十万个查询页面组合，1000 行只是九牛一毛。二是维度限制，界面能导的维度组合有限，想同时看查询和落地页就得靠 API。三是时间，16 个月之后历史数据就没了，想对比去年同期得提前存下来。",[11,207,208],{},"还有个体力问题：每个客户每周手动导一次，一个月就是十几次重复劳动，迟早会忘。",[15,210,211],{"id":211},"准备工作",[11,213,214],{},"在 Google Cloud 里建项目，启用 Search Console API，创建一个服务账号，把服务账号邮箱加到 GSC 的站点用户里，权限给“完全”。这一套二十分钟能配完。",[11,216,217],{},"用服务账号比 OAuth 省事，不需要人授权，适合定时任务。代价是权限管理要谨慎，服务账号泄露等于站点数据泄露。",[15,219,220],{"id":220},"拉什么",[11,222,223],{},"四个维度组合：查询加页面、查询加国家、页面加设备、日期加查询。每个组合分别拉，别指望一次全部拿到。",[11,225,226],{},"日期范围建议按周拉，不要按天，按天拉请求次数多、数据还经常不完整。GSC 数据有 2 到 3 天延迟，拉最近三天基本是空的。",[11,228,229],{},"分页要处理，单次请求有行数上限，返回里带分页游标，循环取完为止。",[15,231,232],{"id":232},"存哪",[11,234,235],{},"我们存 SQLite，一个客户一个库，表结构固定：日期、站点、查询、页面、国家、设备、点击、曝光、排名。每周增量写入，保留全部历史。",[11,237,238],{},"存下来之后能做的事很多：看某个词的排名变化曲线，看某篇文章上线后多久开始有曝光，看品牌词占比的月度趋势。这些在界面里都看不到。",[15,240,241],{"id":241},"拉下来的数据怎么用",[11,243,244],{},"我们最常用的查询是：某篇文章上线 30 天后，它覆盖的查询有多少进了前 20。这个在界面里要一页页翻，在库里一条 SQL 就出来。",[11,246,247],{},"另一个用途是内容复盘。每季度把写过的话题拉出来，看每个词的平均排名和点击，决定下一季度加不加码。",[11,249,250],{},"数据留到三年之后，还能看季节性和算法更新的影响。这些分析都建立在同一张表上，不用每次重新导。",[15,252,253],{"id":253},"三个坑",[11,255,256],{},"第一，配额是每天 2.5 万行，站大、维度多的话一天就可能用完，要错开任务时间。",[11,258,259],{},"第二，不同维度组合的行数不能直接相加，会重复计算。查询加页面和查询加国家是两套口径，混着算总数一定错。",[11,261,262],{},"第三，品牌词要单独标记。我们用正则匹配品牌名，存的时候加一个字段，分析时能一键排除。",{"title":64,"searchDepth":168,"depth":168,"links":264},[265,266,267,268,269,270],{"id":202,"depth":168,"text":202},{"id":211,"depth":168,"text":211},{"id":220,"depth":168,"text":220},{"id":232,"depth":168,"text":232},{"id":241,"depth":168,"text":241},{"id":253,"depth":168,"text":253},"SEO","2026-03-03","界面一次只给 1000 行、只留 16 个月，API 每天能拉 2.5 万行、四个维度自由组合。这篇写服务账号怎么配、拉什么、存哪，以及三个坑。",{},"\u002Fblog\u002Fgsc-api-export-script",{"title":194,"description":273},"blog\u002Fgsc-api-export-script",[279,280,281],"GSC","API","自动化","tvlLNCHhVrKLiUoqwA3egcFMCjoxAm2ULxM7ds4_AR4",{"id":284,"title":285,"author":6,"body":286,"canonical":176,"category":177,"cover":176,"date":363,"description":364,"draft":180,"extension":181,"keywords":176,"meta":365,"navigation":183,"noindex":180,"ogImage":176,"path":366,"seo":367,"seoDescription":176,"seoTitle":176,"stem":368,"tags":369,"updated":176,"__hash__":373},"blog\u002Fblog\u002Ffont-display-swap-vs-optional.md","font-display 选 swap 还是 optional，两周实测的数据",{"type":8,"value":287,"toc":355},[288,295,298,301,304,307,310,313,316,319,322,328,331,334,337,340,343,346,349,352],[11,289,290,291,294],{},"font-display 选 swap 还是 optional，这事没有标准答案，但可以测。今年 2 月我们给两个站各跑了两周，结论是内容站选 optional，营销站选 swap 加 ",[45,292,293],{},"size-adjust","，两者对留存的差别看不出来。",[15,296,297],{"id":297},"三种取值的实际差别",[11,299,300],{},"swap：文字立刻用回退字体渲染，自定义字体到了再换。好处是内容不会空白，坏处是切换时有一次视觉跳动，中文站比英文站明显。",[11,302,303],{},"optional：字体在极短时间内可用才用，超时就用回退字体直到下次访问。好处是几乎不跳动，坏处是首次访问的用户可能一直看到系统字体。",[11,305,306],{},"block：短暂隐藏文字等字体到位。这个基本别用，首屏文字空白三秒比字体丑更糟。",[15,308,309],{"id":309},"两周实测数据",[11,311,312],{},"站 A 是文档站，正文为主。swap 的 LCP P75 是 1.6 秒，optional 是 1.5 秒，差别很小，因为 h1 用哪个字体渲染出来都是最大元素。但 CLS 差别大：swap 是 0.09，optional 是 0.01。",[11,314,315],{},"站 B 是营销首页，大标题承担品牌感受。swap 的 LCP 是 1.9 秒，optional 是 2.3 秒。原因是大标题在 swap 下会被重绘，但至少先出现在首屏；optional 下首次访问看不到自定义字体，下一次访问才生效。CLS 方面 swap 是 0.14，optional 是 0.02。",[15,317,318],{"id":318},"我们的选择",[11,320,321],{},"内容站选 optional。文档、博客、术语表以阅读为主，字体视觉一致性没那么重要，稳定更重要。",[11,323,324,325,327],{},"营销站选 swap，但必须配两件事：字体文件 preload，回退字体加 ",[45,326,293],{}," 校准。这两件做完，swap 的 CLS 从 0.14 降到 0.03 左右。站 B 改完两周，真实数据稳定在 0.04。",[15,329,330],{"id":330},"一个反例",[11,332,333],{},"我见过一个站把所有字体都设成 block，理由是\"避免闪烁\"。结果移动端首屏空白 2.8 秒，用户以为网站挂了。这种做法在 2026 年没有任何理由。",[11,335,336],{},"还有人给所有字体都 preload，一次 preload 四个字体文件，等于把首屏带宽分给四个资源，LCP 反而更差。preload 只给首屏真正用到的那一个。",[15,338,339],{"id":339},"怎么自己测",[11,341,342],{},"不用搞复杂，两个页面、各跑两周，看 GSC 的真实数据就够。重点看两个数：LCP 的 P75 和 CLS 的 P75，别只看实验室。",[11,344,345],{},"如果两周内数据波动超过 20%，说明样本不够，需要更长时间或者更大的流量。这种时候别急着下结论，先看有没有其他改动混进来了。",[15,347,348],{"id":348},"落地时的两个细节",[11,350,351],{},"一是字体文件要和 CSS 在同一层 CDN 上，别一个在源站一个在 CDN，跨层回源会把收益吃掉。我们有个客户字体放在对象存储，没开缓存头，每次访问都要回源，改了缓存策略后 P75 从 700 毫秒降到 90 毫秒。",[11,353,354],{},"二是用 web vitals 的 JS 埋点看真实用户数据，别只看实验室。实验室环境是本地缓存加高速网络，测不出用户手机上的真实情况。我们现在的做法是每周拉一次真实用户数据，超过阈值就回看那次发布改了什么。",{"title":64,"searchDepth":168,"depth":168,"links":356},[357,358,359,360,361,362],{"id":297,"depth":168,"text":297},{"id":309,"depth":168,"text":309},{"id":318,"depth":168,"text":318},{"id":330,"depth":168,"text":330},{"id":339,"depth":168,"text":339},{"id":348,"depth":168,"text":348},"2026-03-05","两个站各跑两周：文档站用 optional，LCP 1.5 秒、CLS 0.01；营销站用 swap，LCP 1.9 秒、CLS 0.14，加上 preload 和 size-adjust 后 CLS 降到 0.03。",{},"\u002Fblog\u002Ffont-display-swap-vs-optional",{"title":285,"description":364},"blog\u002Ffont-display-swap-vs-optional",[370,371,372],"font-display","CLS","字体加载","i91VTSe9rZjqFi8WpwD4uWU9JeBiHiOsWAGAcWVLP0g",1794088107893]