长尾站靠累计大量小查询取胜。但只有结构在 50 篇之前就规划好——分类写进 schema、slug 由正则强校验、内链策略由脚本审计——才能赢。
问题背景
长尾站不是”一个博客发很多帖子”。它是一个结构化的内容数据库:每篇文章打一个具体查询,内链围绕 pillar 主题聚合,URL 和分类结构告诉搜索引擎这个站到底是干什么的。第一天把这些规划好多花一个周末;写了 200 篇再回头改可能要花一个月。
判断标准
- 已经验证过这个方向至少有 200 个不同的长尾查询。
- 主题天然能拆成 4-8 个共享受众但问题不同的子方向。
- 能一句话说清楚自己和前三名竞品的差异。
- 有现实的产出节奏(每周 1-3 篇,能持续 9 个月以上)。
- 能承诺一种永远不改的 slug 规范。
快速结论
第一篇之前定好子主题分类和 slug 规则,第 20 篇之前定好内链策略。这两件事后面几乎不可能重构。
开始前准备
- 至少 200 个候选长尾 query 已识别(见
judge-search-demand-before-building)。 - 4-8 个 hub 列表草拟好。
- slug 正则已选好并冻结。
实操步骤
- 方向拆成 4-8 个 hub。 每个 hub 至少能规划出 20 个长尾子题。hub 列表写进内容 schema 防 typo:
// src/content/config.ts
const HUBS = ['indie-dev', 'ai-tools', 'prompt-library',
'troubleshooting', 'ai-applications'] as const;
schema: z.object({
// ...
category: z.enum(HUBS),
primaryKeyword: z.string().min(3),
targetQuery: z.string().optional(), // 这篇为之存在的长尾短语
pillar: z.string().optional(),
}),
- 选定 slug 规范并冻结。 kebab-case、不带日期、不带分类前缀。schema 正则强校验:
urlSlug: z.string().regex(/^[a-z0-9][a-z0-9-]{2,80}[a-z0-9]$/, 'kebab-case only')
CI 里再禁日期前缀:
ls src/content/articles/zh/*/ | grep -E '^[0-9]{4}-' && echo "FAIL: slug 带日期" && exit 1
-
URL 结构选好。 扁平(
/articles/slug/)以后好重构;嵌套(/hub/slug/)主题信号更强但锁死。独立站默认扁平。选一次写进CONTENT.md。 -
内容计划做成数据,不是 Trello。 每个 hub 一个 CSV 或 YAML:
slug,hub,targetQuery,pillar,status,publishedAt,linksTo,linksFrom
firebase-custom-domain,indie-dev,firebase 自定义域名,firebase-hosting-go-live-checklist,published,2026-05-17,"firebase-cache-and-deploy-update;what-is-firebase-hosting",firebase-hosting-go-live-checklist
firebase-cache-and-deploy-update,indie-dev,firebase 缓存,firebase-hosting-go-live-checklist,published,2026-05-17,"firebase-custom-domain",firebase-route-404-causes
# ...
-
pillar 后写。 先发 5-7 篇 cluster;从中沉淀出 pillar。每个 hub 一篇 pillar。
-
内链是硬规则。 每篇新文至少链 2 篇老文,至少 1 篇老文反链。prebuild 强制:
// scripts/check-internal-link-density.mjs(节选)
import { readFileSync } from 'node:fs';
const md = readFileSync(file, 'utf8');
const outLinks = (md.match(/\]\(\/[a-z]+\/articles\//g) || []).length;
if (outLinks < 2) {
console.error(`内链太薄: ${file} 只有 ${outLinks} 条`);
process.exit(1);
}
- sitemap 按深度分 priority。 pillar 0.8、cluster 0.6、标签 0.3——给爬虫提示:
// astro.config.mjs
sitemap({
serialize(item) {
if (item.url.includes('/category/')) item.priority = 0.8;
else if (item.url.includes('/articles/')) item.priority = 0.6;
else if (item.url.includes('/tag/')) item.priority = 0.3;
return item;
},
}),
- 每 30 天复盘。 拉 Search Console pages 报告,曝光 < 5 的标记待刷新,把真实出现的新长尾 query 补进计划:
curl -X POST "https://www.googleapis.com/webmasters/v3/sites/$SITE/searchAnalytics/query" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
--data '{"startDate":"2026-04-22","endDate":"2026-05-22",
"dimensions":["query","page"],"rowLimit":500}' \
| jq -r '.rows[] | [.clicks,.impressions,.keys[0],.keys[1]] | @tsv' \
| sort -k2 -rn | head -30
执行检查清单
- hub 在 schema 里是
enum。 - slug 正则强制 kebab-case 且禁日期前缀。
- 内容计划是 CSV/YAML,不是只在脑子里。
- prebuild 在内链过薄时挂构建。
- sitemap priority 反映 pillar vs cluster。
上线后验证
- 60 天后每篇 cluster 都至少被 1 篇 pillar 链入并自身链出 2 篇。
- 没有孤儿文章(
audit-pillars.mjs验证)。 - Search Console “Discovered – currently not indexed” 保持在 10% 以下。
容易踩的坑
- 跳过分类直接想到啥写啥,最后变成 100 篇孤儿文章。
- slug 里加日期(
/2026-how-to-...),内容更新时被迫重写。 - URL 嵌套太深(
/cat/sub/sub/slug/),改分类就死链。 - 内链规则还没建立就让 AI 一口气生成 50 篇。
- 把”长尾”当成”低质”理由发薄稿——2026 年的 Google 在长尾领域也读得出薄。
- 内容计划在 Trello 没有导出——300 张卡之后就 grep 不动了。
FAQ
- 写多少篇能看到流量: 2026 年常见的数字是 40-60 篇结构良好、相互内链的文章,前提是方向合适、站点上线 4 个月以上。
- 扁平还是嵌套 URL: 独立站推荐扁平,hub 可以随时调整而不破链。除非你的 hub 真的永久不变,再考虑嵌套。
- 能不能用 AI 写初稿: 你完全懂的主题可以;你没法 fact-check 的主题坚决不行。无论哪种都需要人工编辑。
- 什么时候在分类之上加标签系统: 大概 100 篇之后、读者需要分类之外的横向切分时。更早加就是过度设计。
- 内容计划放 Notion / Airtable / 仓库?: 仓库。
content-plan/下 CSV 或 YAML。要 grep 得动、diff 得了、脚本能读。