Tags
The Markdown mark, a black rounded rectangle enclosing an M and a downward arrow, on a white card

Reaching a bigger audience while your own copy stays primary — rel=canonical and full-text RSS

What backlinks and rel=canonical do, why Zenn and Qiita change the plan, and the pipeline that makes republishing an article a paste rather than a project.

On this page

Introduction

I had done everything a search engine asks for. The site was submitted to Google and Bing, it had a sitemap, structured data, a robots.txt naming every AI crawler, and clean HTML on every page. The only thing missing was the one thing none of that produces: other sites linking to mine.

The obvious answer is to post the same article somewhere with more readers, and it comes with a trap I did not understand well enough to avoid. Two copies of one article compete, and the bigger site usually wins, with your own words. The tag that prevents this is rel=canonical, and asking which platforms support it turned up the finding that shaped everything after: Zenn and Qiita cannot set it at all.

This article covers what a backlink and a canonical actually do, what those platform limits force, and the two things this blog had already shipped that turned republishing from a project into a paste.

A backlink is a link from someone else’s site to yours. That is the definition, and its weight comes from who is doing the linking.

Search engines treat a link as a small vote. A new domain with no votes at all is not penalised so much as unknown, and being unknown is what limits how often a crawler bothers coming back. Every other piece of SEO work makes a page legible once a crawler arrives. A backlink is part of what makes it arrive.

That is why it stayed outstanding after everything else was done. A sitemap is a file I can generate. Structured data is markup I can emit. A link from another site is a decision somebody else makes, and the only honest way to influence it is to put the writing where people who might link to it already are.

A backlink is a link. Nothing is duplicated to make one. Someone writes “see this” and points at your address, and that is the mechanism. It is worth stating plainly, because the next section is about republishing and the two are easy to read as the same move.

They are not. Republishing puts a copy of the article on a platform that already has readers, and it is that copy which creates the problem rel=canonical exists to solve. A shared link makes no copy, so there is nothing to compete with and no canonical to set.

What you do Copies the article Needs a canonical What it is for
Share the link no no reach, and being discovered
Comment with the link where it helps no no reach, on a domain already trusted
Republish the full text yes yes that platform’s readers
Someone else links to you no no the ranking signal itself

Links from social platforms are almost all nofollow. Facebook, X and LinkedIn mark outbound links that way by default. Google changed nofollow from an instruction to a hint in September 2019 and extended that to crawling and indexing the following March, so such a link is not worth nothing. It is also not worth planning around.

What a share reliably does is put the writing in front of someone who has a site of their own. Their link is the followed one. That is the only route to the last row of that table, and it is not a route anything described here can automate.

What rel=canonical does

rel=canonical is one line in the <head> of a page:

<link rel="canonical" href="https://oharu121.com/blog/some-article/">

It means: this page you are reading is a copy, and that address is the original. A search engine that honours it folds the two together and treats the original as the one to show.

Without it, two pages holding the same text look like two unrelated pages that happen to match. The engine picks one, and it picks on trust, which a large platform has more of than a personal blog does.

One article, two copies, one tagTwo scenarios with the same pair of copies. Without a canonical tag, a search engine sees two unrelated pages holding the same text and picks whichever site it trusts more, which is the larger one. With a canonical tag on the republished copy pointing at the original, the two are treated as one article, and the original is the one that appears in results while the copy still brings its readers.No canonical tagyour blogthe originalthe bigger sitethe copysearch enginethe bigger sitethe copytwo unrelated pages, same text — it picks the site it trusts moreCanonical points homeyour blogthe originalthe bigger sitethe copyrel=canonical →search engineyour blogthe originalone article with two addresses — the original is the one shown
Nothing about the two copies changes. One tag decides which of them is treated as the article.

Two things are worth being precise about, because both are easy to overstate.

It is a hint, not an instruction. Google’s documentation is explicit that a canonical is one signal among several, and a strong enough contrary signal can override it. In practice it is honoured, and it is the only lever you get.

It does not send readers anywhere. A canonical is invisible to the person reading the copy. They stay on the platform, and that is fine: the link back is what you wanted from the republication, not the pageview.

Zenn and Qiita cannot send one

The agent’s first recommendation was to cross-post to dev.to, Zenn and Qiita with a canonical pointing home, flagged as unverified. Checking it changed the plan.

dev.to supports a canonical URL per post, as a canonical_url field, and can also import from an RSS feed and set it automatically.

Zenn does not. An investigation of exactly this found that Zenn’s published pages carry a canonical pointing at Zenn’s own URL regardless of what the source frontmatter says. Writing one changes nothing that a crawler sees.

Qiita has no user-settable canonical either.

Canonical support decides what you postThree platforms against what each allows. dev.to supports a canonical URL set per post and can import from a feed, so the full article can be republished there safely. Zenn cannot: its published pages carry a canonical pointing at Zenn regardless of what the source file says. Qiita has no user-settable canonical either. On both of those the safe move is a short summary linking back, because the full text would compete against the original.Can declare your copy?So postdev.toyes, per postthe full articleZennno, always itselfa summary and a linkQiitano setting existsa summary and a linkThe rule is not about size. It is about whether the platform will say the article is yours.
Not a question of platform size. A question of whether the platform will say the article is yours.

Had that recommendation shipped unchecked, the result would have been the opposite of the goal: the full text of every article handed to two sites with far more authority, with nothing anywhere saying which copy came first.

What the limit forces is a split rather than a retreat. Where a canonical is available, republish in full. Where it is not, post a short summary and link to the original. The summary still reaches those readers and still earns the link; it just declines to enter a competition it would lose.

What this blog had already built for something else

Two earlier changes turned out to matter here, and neither was made for this.

A Markdown twin of every article. Each article is served twice: once as a page, and once as plain Markdown at the same address with .md on the end. That was built so answer engines get the prose without a navigation shell wrapped around it. It also happens to be exactly what you paste into another editor.

Full text in the RSS feeds. Items used to carry a 160-character summary and a link. They now carry the article in full, because a platform importer reading a summary-only feed produces a stub.

One source file, three outputs, three destinationsA single MDX file per article produces three things. The rendered page is what readers and search engines get. The Markdown twin at the same address with a dot md suffix is plain text, ready to paste into another editor. The feed now carries that same text in full, which is what a platform importer can pull. The page serves the site, the twin serves a manual repost, and the feed serves an automatic one.one .mdx filethe pagereaders, crawlersthe site itselfthe .md twinpaste it anywherea manual repostthe feedfull text, 20 itemsan importerNone of the three were built for republishing. All three turned out to serve it.
One source file already produced all three. Only the last one was added deliberately for this.

The feed change had a constraint the twins did not. compiledContent() is unsupported for MDX and every article here is MDX, so the usual route does not exist. The agent’s approach reuses the transform that already produces the twins and renders its output with Astro’s own markdown processor:

processor ??= createMarkdownProcessor({});
const { code } = await (await processor).render(mdxToMarkdown(body));

The feed inherits what the twin loses. A diagram arrives as its caption and a photograph as its alt text, because neither has an address that survives leaving the page. Prose, headings, tables and code all pass through. That is a large improvement on two sentences and it is not the same as the page.

Two bugs in the feed, and what they have in common

The feed shipped with two defects the agent wrote, and both were found by review rather than by any check.

Root-relative links leaked. One article links to its own part one as /blog/…. A browser resolves that against the page it is on. A feed reader has no such page, so it resolves against its own origin and 404s. One per feed, in all three languages.

The verification had claimed this was clear. It searched for ./ while the link was /, so the check could not see that shape at all.

A stray control character would have made the feed unparseable. The Markdown transform masks code spans with NUL sentinels before rewriting tags, and restores them at the end. In a .md file a leftover sentinel is cosmetic. In XML it is fatal, and nothing in the build validates the feed:

a NUL inside an element parses: FAIL — not well-formed (invalid token)

pnpm check and pnpm build would both have stayed green while every reader failed to parse the feed.

Both now handled: href="/…" and src="/…" are resolved against the site origin, and the XML-forbidden control range is stripped. What the two share is that the thing which would have caught them was written by the same person, at the same time, with the same blind spot. A check and the code it checks agreeing is not evidence.

The runbook

For an article that is ready to republish.

On a platform that supports a canonical, republish in full. The Markdown twin is already the paste:

Terminal window
curl -sS https://oharu121.com/blog/<slug>.md | pbcopy

Delete the twin’s header block, including its --- separator, which would otherwise collide with the platform’s own frontmatter delimiters. Then set the canonical:

---
title: <the title>
published: true
canonical_url: https://oharu121.com/blog/<slug>/
tags: seo, astro, webdev
---

Verify it took. View source on the published post and look for a <link rel="canonical"> pointing at your address. If it is missing, the frontmatter did not parse, which is usually the leftover ---.

On a platform that cannot, post two or three paragraphs and link to the original. On this blog the Japanese and Traditional Chinese translations already exist, so the summary can be written in the reader’s language and point at that locale’s URL.

Where a link is worth more than a repost, comment on the issue where someone hit the problem the article solves. The comment has to stand on its own; the link is the long-form version, not the payload.

What to expect

Worth being blunt, because the honest answer is unsatisfying.

A backlink is not a switch. Nothing about this makes an article rank tomorrow. What it changes is whether a crawler has a reason to come back, and that compounds slowly.

The referral traffic arrives first and the search effect much later, if it arrives at all. The platform readers are immediate. Anything downstream depends on whether one of them writes something and links to you, which is not something a pipeline can cause.

What the tooling actually bought is the cost of trying. Republishing was previously a copy-paste-reformat job per article per platform, which is exactly the sort of chore that quietly stops happening. It is now a curl and a frontmatter block. The pipeline does not make republishing work better. It makes it cheap enough to keep doing.

Summary

  • A backlink is a link from someone else’s site, and it is the one part of this nobody can generate. Everything else makes a page legible once a crawler arrives.
  • Sharing a link and republishing an article are different moves. Only republishing makes a copy, and only a copy needs a canonical. Social links are almost all nofollow, which since 2019 is a hint rather than an instruction: worth doing for reach, not worth counting as a ranking signal.
  • rel=canonical declares which copy is the original, so republishing does not put you in competition with yourself. It is a hint rather than an instruction, and it moves no readers.
  • Two of the three obvious platforms cannot set it. Zenn’s pages point their canonical at Zenn whatever the source says, and Qiita has no setting. Full text goes where a canonical is possible; a summary and a link go everywhere else.
  • The Markdown twin and the full-text feed were built for answer engines and turned out to be the syndication pipeline. One is a paste, the other is what an importer reads.
  • A check written alongside the code it checks shares its blind spot. The feed’s own verification searched for ./ while the broken link was /.
  • Expect the cost of trying to drop, not the results to arrive. That is still the useful change, because the version that costs an afternoon per platform is the version that does not happen.

References

Share this article