Kotonia
ログイン今すぐ始める

Kotonia Articles

Zenn 的 canonical 我以为写了,其实根本没生效

个人开发服务的注册数下降,重新调查流量来源和 canonical 后发现,向 Zenn 全文交叉发布的运营策略存在漏洞。

作者 6分钟阅读
#SEO#个人开发#Zenn#devto#canonical
其他语言日语

最初感到不对劲的,不是注册数。而是“雌小鬼”。

不久前,我制作了一个名为“雌小鬼英语学习”的角色英语会话,并写了篇文章。这是一个与挑衅口吻的角色用英语对话的尖锐企划。说实话,我感觉它能火,并且作为语言学习的钩子,确实能为用户提供价值(关于为何制作这个企划以及效果如何,我写在了用雌小鬼英语会话拿下搜索高位,然后又失去的故事里)。

实际上,尝试成功了一半。对于“雌小鬼英语会话”及类似查询,我的说明页面和自有文章占据了搜索结果的第1和第2位。在 Kotonia 本体之外,这曾是我最强的集客钩子。

然而有一天,当我再次用同样的查询搜索时,自己的文章和说明页面都搜不到了。取而代之的是,本该是交叉发布的 Zenn 文章,独自占据了第1位。

我自己网站上的原文从搜索结果中消失了,只剩下原本打算作为镜像的 Zenn 文章。

这种违和感,是一切调查的入口。

开始调查后,我注意到了另一个症状。个人开发服务的注册数,从某天起就停止了。

最初我怀疑是注册表单的问题。因为最近对 Google 登录和注册相关部分做了修改,我以为是哪里搞坏了注册流程。

但是,查看了生产环境的 analytics 后,发现情况似乎并非如此。

与其说是卡在了注册表单,不如说是在到达注册页面之前的流量就已经断了

于是我开始怀疑文章流量,重新调查了 Zenn、dev.to 和自有博客的 canonical 相关设置。结果发现,自己一直在一个非常糟糕的前提下运营着文章。

这篇文章就是那份调查记录。

这不是指责特定服务的问题,而是我自身运营失误的记录。Zenn 作为技术文章的发布平台很强。但如果你想培养自有服务的 SEO,将同样的正文全文交叉发布是危险的。

发生了什么

我在运营一个名为 Kotonia 的个人开发服务。

周末本来还有一些新注册,但从 2026-05-24(周日)早上开始,新注册就停止了。

通过生产环境的 admin API,排除管理员和我自己的用户 ID 进行确认,发现最后一次新注册是在 2026-05-24 06:21 JST

按天来看,就在那之前还是有注册的。

Date JSTNew users
2026-05-224
2026-05-232
2026-05-244

但是,之后就停了。

我首先怀疑的是注册处理流程。最近在 GitHub 上确实有关于注册的变更。

  • email 的唯一性约束
  • Google OAuth
  • Google 登录时的账户整合
  • 添加落地页
  • 部分 CTA 的变更

不过,看了 analytics 后,呈现出稍微不同的画面。

不是注册表单,而是注册页面的访问消失了

查看 /register/ 的访问情况,结果如下。

Date UTCRegister pageviewsUnique sessionsSignup conversions
2026-05-22332
2026-05-231284
2026-05-24000
2026-05-25000

也就是说,与其说是“来了注册页面但无法注册”,不如说是根本没到注册页面

在这一点上,比起注册表单本身的 bug,上游流量发生变化的可能性更高。

当然,数据统计存在漏洞。通过 Google OAuth 注册时,前端并没有像密码注册那样触发 signup 转化事件。因此转化数据存在部分低估。

但是,由于新用户创建本身也停止了,所以这次归零的主要原因似乎不在这里。

流量是从哪里来的

查看最近 14 天的 top referrer,主要是 direct 和 Google。

ReferrerPageviewsUnique sessions
direct14961
Google11321
zenn.dev41
Bing3-
DuckDuckGo2-
ChatGPT2-

从 Zenn 的直接流入,在可确认的范围内并不大。

所以不能说“因为来自 Zenn 的点击停止了,所以注册停止了”。

但是,文章在搜索方面是如何被处理的,则是另一个问题。既然能看到来自 Google 搜索的流量,那么文章的 canonical、重复正文、外部交叉发布就会产生影响。

于是,我确认了 Zenn 和 dev.to 的处理情况。

我之前的文章运营方式

按照我的设想,运营方式是这样的。

  1. 在 Kotonia 上发布文章全文
  2. 将相同的 Markdown 也放在 Zenn 上
  3. 在 Zenn 侧的 frontmatter 中写入 canonical
  4. 让 Google 将 Kotonia 侧视为规范 URL
  5. 将 Zenn 作为分发渠道使用

我在 Markdown 中写了这样的 frontmatter。

canonical: "https://kotonia.ai/articles/<slug>/"

我以为这样“即使在 Zenn 上放置全文,SEO 上的规范 URL 也会是 Kotonia”。

但是,这里搞错了。

Zenn 的 canonical 并未生效

实际确认已发布的 Zenn 文章的 HTML 时,发现 link rel="canonical" 指向的是 Zenn 自身,而不是 Kotonia。

也就是说,我在 Markdown 中写的 canonical,并没有作为外部 canonical 反映在 Zenn 的公开 HTML 中。我甚至查看了 Zenn 的官方文档、CLI 的 frontmatter 规范、编辑器的类型和验证器,但任何地方都没有指定外部 canonical 的选项。

在用 curl 查看 HTML 的瞬间,我的运营前提就崩塌了。并不是“因为在 Zenn 写了 canonical 所以没问题”。

(关于公开 HTML 的确认步骤、Zenn frontmatter 的准确规范、与 dev.to 的比较以及参考的原始资料,我将其作为纯技术内容单独整理成了一篇 Zenn 文章 → Zenn 的 canonical 对公开 HTML 无效(技术验证)

dev.to 则显示了 canonical

另一方面,在 dev.to 上发布的英语文章中,HTML 上正确地显示了指向 Kotonia 的 canonical。同样是“在 frontmatter 中写 canonical”,效果却因服务而异。

不过,即使 canonical 生效,也不一定意味着自有网站就一定能赢。由于域名权重、发布初期的新鲜度、用户行为等因素,外部域名排在前面也是有可能的。

在弱小的个人开发域名成长起来之前,将全文放在强大的外部域名上这件事本身就存在风险。

哪里出了问题

最糟糕的是,我将 Zenn 同时用作“分发渠道”和“全文镜像”。

Zenn 很强。

在强大的域名上,放置相同的正文,在同一时期,以全文形式。

而且,在公开的 HTML 上,Zenn 自身被设为 canonical。

在这种状态下,Google 认为 Zenn 的文章更接近规范页面也不足为奇。

我本应是在自己的网站上写文章,并将其培养成自有网站的 SEO 资产,但实际上,我可能将正文和搜索评价都拱手让给了强大的外部域名。

这非常痛。

这是注册数下降的原因吗

这里不做断定。

关于这次的注册停止,我不能断言 Zenn 的 canonical 问题是直接原因。

从实际数据来看,来自 Zenn 的直接流入并不大。注册用户的入口也混杂着首页、视频类页面、英语页面、聊天页面等。

所以,我认为这样看待这次事件是准确的。

  • 注册停止的直接原因尚未确定
  • 但是,由于注册页面的访问消失了,所以看起来更像是流量侧的问题,而非注册处理的问题
  • 在调查流量侧的过程中,发现了 Zenn 全文交叉发布运营的巨大漏洞
  • 这与短期的注册数无关,是长期 SEO 上相当重要的问题

感觉不是确定了原因,而是抓住了重要的线索。

今后的运营 — 不以摘要逃避,而是用不同版本来战斗

最初得出的答案是“在 Zenn 上只放摘要,全文放在 Kotonia”。实际上,我曾一度将所有文章缩减为摘要版。

但是,我放弃了这种做法,恢复到了原来的全文。

理由有两个。

其一,我确实从 Zenn 那里获得了益处。作为技术文章的发布平台它很强,而且有人在读。不能因为 canonical 不生效,就把好不容易写好的正文瘦身成摘要来逃避,这在我自己这里说不过去。

另一个理由是,摘要版对读者来说是半吊子。“后续请到自有网站查看”是写作者自己的方便,而不是读者的体验。

于是我改变了方针。全文两边都发。但是,不使用相同的正文。

Google 无视 canonical 而选择强大域名的原因,是因为两个页面是“几乎相同的正文”,所以判断只需保留其中一个。既然如此,只要不让它们成为近似重复(near-duplicate)就行了。

  • Zenn / dev.to: 技术核心版。面向纯粹以技术查询进行搜索的人。包含复现步骤、数字、代码。在符合条款的安全范围内发布全文。
  • Kotonia (/articles): 热情·战略版。即使是相同的题材,也将“为什么个人开发者要攻击这个剩余领域”、“实际需求在哪里”等背后的上下文作为主角。与 Zenn 瞄准的查询和文章结构都不同。

从相同的素材中,写出意图不同的两篇文章。然后通过有机的链接将它们连接起来。从 Zenn 的技术版链接到自有网站:“做出这个判断的战略在这里”;从自有网站链接到 Zenn:“技术细节在这里”。不是依靠 canonical 这种取巧的方法,而是因为内容不同,所以两篇都被索引,两篇都有人读,以这种状态为目标。

我脑海中浮现的是,OSS 社区坦率地撰写微调和模型验证文章的那种风格。毫无保留地展示所有底牌,过程、失败和数字都放出来,并自然地链接到相关文章。那些文章不是靠 canonical 来操纵的,而是靠内容的密度和相互链接来获得阅读的。

对于过于露骨、不想放在产品域名上的示例,我会将其放在不同 slug 下,并置于设置了 noindex 和从 sitemap 中排除的“门”后。在保持索引对象安全的同时,只传递给“想看的人”。这样也能避免 SafeSearch 波及整个产品域名的风险。

数据统计也要修正

在这次的调查中,我发现不仅是 SEO 运营,数据统计也存在漏洞。

至少下次要保存以下数据。

  • 用户创建时的 provider
    • password
    • google
  • 首次流入路径
  • 首次 referrer
  • UTM
  • session_id
  • 注册前点击的 CTA

没有这些,无论注册数是增加还是减少,最终都只能靠推测。

这次也是,虽然从生产数据中看出了很多,但最后一步还是变成了推测。

即使是个人开发,也最好从一开始就保留流量来源和注册路径。

越交给 Agent,越要自己发现违和感

还有一点,虽然有点惭愧,但这是一个很大的反省。

最近的开发,很大程度上交给了 Agent。

与其说是自己写全部代码,不如说是编写 harness、提出方针、委托实现、审查、修改。类似 vibe coding 的时间也增多了。

这真的帮了大忙。开发速度大幅提升。我一个人无法顾及的功能、调查、运营改善,现在都能推进了。

但是,另一方面,我也意识到,越是将工作交给 Agent,就越不能放弃“自己去看并注意到违和感的能力”。

就这次而言,在 Markdown 中写了 canonical 这件事,和公开 HTML 中 rel="canonical" 是如何显示的,是两码事。

Agent 可以写文章。也能整理好投稿步骤。也能写文档。但是,搜索结果中显示的是哪个页面,公开的 HTML 是否真的符合意图,流量下降时哪里不对劲,这些最终都需要自己去怀疑、去查看。

特别是 SEO,仅仅实现正确是不够的。

  • 在公开 HTML 中看起来如何
  • Google 是如何解释的
  • 是否将正文拱手让给了强大的外部域名
  • 注册数和流量是否有异常的断层

这些方面,仅靠代码审查是无法完全覆盖的。

用 Agent 加速开发本身并没有错。不如说,今后也会继续使用。

但是,在与业务和流量直接相关的地方,要亲眼去看实物。在浏览器里看。看 HTML。看 Search Console。看 analytics。

“交给它”和“自己不看”是不同的。

这次的失败,足以让我想起这一点。

学到的教训

这次学到的教训非常简单。

canonical,不是靠“以为写了”,而是要在公开 HTML 中确认。

不是看 Markdown 里有没有写 canonical,而是看实际页面上是如何显示的。

curl -s https://example.com/article \
  | rg 'rel="canonical"'

而且,外部服务的 frontmatter,有时即使写了不支持的键也会被无视。

虽然是理所当然的事情,但在运营流程中很容易被忽视。

特别是在个人开发服务的初期 SEO 中,每一篇文章都是资产。如果要在强大的外部域名上以全文形式放置相同的正文,最好先确认一下,这是否会作为近似重复(near-duplicate)而将自己的搜索评价拱手让人。

我疏忽了这一点。

并且,在 canonical 不生效的方面,不是用摘要来逃避,而是写出意图不同的两篇文章,并用有机链接连接起来。不在两个地方放置相同的正文。这就是我现在的结论。

技术细节分拆到了 Zenn

公开 HTML 的确认步骤(curl)、Zenn frontmatter 的准确规范、与 dev.to 的比较以及参考的原始资料,已作为技术文章单独拆分出来放在了 Zenn。

Zenn 的 canonical 对公开 HTML 无效(技术验证)

这篇文章(Kotonia 版)是记录直到进行上述验证为止的调查,以及我是如何改变运营和思想的。将相同的题材,分为技术参考(Zenn)和决策故事(这里),并用有机链接连接起来。这本身也是一个不依赖 canonical,而让两篇文章都能被阅读的实验。

发布前备忘

  • 发布时,决定注册数等具体数值是直接公开,还是稍微取整。
  • 如果要在 Zenn 上投稿,不要直接转载这篇正文,而是作为技术核心版,以不同的结构重写(避免 near-duplicate)。自有版本和 Zenn 版本通过有机链接相互连接。
  • 这篇文章本身的 canonical 设置在 Kotonia 侧(自有域名内的自我引用 canonical 是正确生效的。这和跨域交给强大的外部域名是两回事)。

Kotonia 将语音 AI、AI 聊天、图像生成和团队协作整合到一个 AI 工作区中。

试用 Kotonia