Articles
中
Define URL mappings before replacing strings0%
x

Bilingual SEO Migrations: Testing 301, Canonical, and hreflang

Development

Evan LongPublished 2026-10-09Updated 2026-10-09

Renaming guides to articles and opening the new page completes only part of a migration. Old links must reach the same article, metadata must agree on its new address, and sharing images must still resolve. This describes the implementation and reusable acceptance checks on this site. Local output checks cannot establish production crawling or indexing.

Define URL mappings before replacing strings

Article slugs remain unchanged, while /zh/guides and /en/guides move to /zh/articles and /en/articles. An old detail page must reach its matching article, not the archive homepage. Query parameters survive so previously shared source information is retained.

The rules distinguish pages from files. Bare /articles/codex-subscription redirects to default English; /articles/image.jpg is a public asset and must not acquire an /en prefix. Article and OG image directories moved too, with permanent redirects retained for legacy resources.

The www legacy route changes host and directory in one hop. Matching is limited to the actual guides path, so /guides-old does not accidentally redirect. These are acceptance examples rather than navigation links.

Migration mappings and expected responses
Request exampleResultAcceptance condition
/zh/guides/codex-subscription301 → /zh/articles/codex-subscriptionSame locale and article; destination 200
/zh/guides?page=2301 → /zh/articles?page=2Query retained; 200 only if page two exists
/articles/codex-subscription301 → /en/articles/codex-subscriptionDefault-language entry
/og/guides/old-image.jpg301 → /og/articles/old-image.jpgTest an asset that actually exists
/guides-old404No accidental prefix match
Google: URL migration and redirects

Self-canonical translations, reciprocal language annotations

Complete Chinese and English articles have independently useful content. Each canonical points to its own new URL, while hreflang identifies the equivalent translation. Canonicalizing every Chinese article to English sends a different consolidation signal; it is not a replacement for language annotations.

The code below shows the Chinese article’s target markup. Its English counterpart includes the same reciprocal alternate set, with an English self-canonical. This site chooses English for x-default because that is the default entry. It does not represent a third translation or a choice every bilingual site must copy.

Use consistent absolute production URLs. Exclude localhost, www, legacy directories, and mismatched languages. Review the pair of articles, not merely whether the word hreflang appears on one of them.

html
<link rel="canonical"
  href="https://evanlong.me/zh/articles/codex-subscription">
<link rel="alternate" hreflang="zh-CN"
  href="https://evanlong.me/zh/articles/codex-subscription">
<link rel="alternate" hreflang="en"
  href="https://evanlong.me/en/articles/codex-subscription">
<link rel="alternate" hreflang="x-default"
  href="https://evanlong.me/en/articles/codex-subscription">
Google: reciprocal localized-page annotations

Generate the article and its metadata from the same record

Article records store translated titles, descriptions, dates, topics, and images. Lists, detail pages, generateMetadata, and sitemap consume those records. Editing a title therefore updates the H1, search title, OG / Twitter title, and Article headline without maintaining separate copies. A metadata helper adds the brand suffix without adding it to the visible title.

This is a consistency strategy, not a ranking guarantee. Inspect returned HTML: canonical, og:url, language URLs, and JSON-LD url / mainEntityOfPage should agree. Authors, dates, and images should match visible content. Do not invent reviews, sales, or HowTo steps to seek additional search presentation.

Sharing and reading images have different roles. OG cards here use 1200×630 images; article screenshots retain their real dimensions with descriptive alt text, captions, dates, and source links. Pricing screenshots preserve the reviewed state; text explains the possibility of change. Alt text describes the image rather than listing purchase keywords.

Browse articles2026-10-09

Image preview

Local article index captured on 2026-10-09. Different topics share the list and pagination rules, with links to each article's English and Chinese versions.

Google: Article markup and content

Pagination represents different content

The homepage displays three articles and the archive uses ten per page with ordinary previous / next links. If page two exists, /articles?page=2 canonicalizes to itself. ?page=1 redirects to the clean first-page URL. Canonicalizing every page to page one obscures the different article sets.

There are currently five articles, so page two returns 404. Preserving a query in a migration does not make every page number valid. With eleven articles, verify page two, language switching with page=2, and paginated sitemap entries. Future filters and sorting need their own indexing decisions rather than automatically inheriting pagination rules.

Test tooling must distinguish historical examples from active legacy URLs. This article explains /guides migration, so rejecting HTML merely for containing that string would reject useful case-study prose. Check canonical, sitemap, image src, and internal navigation for stale paths instead.

Google: pagination links, URLs, and canonicals

Check responses before release, crawling after release

Locally, check legacy status and Location, destination 200, reciprocal languages, working images, and 404 for missing slugs. The command below is a production check to run after deployment; replace the origin with localhost:3000 for local work. A browser displaying the final page after following redirects does not reveal every intermediate response.

After release, inspect representative new URLs in Search Console for crawling, selected canonical, and sitemap state, then observe replacement of legacy paths. Redirects and sitemap support the migration; passing locally cannot prove Google has crawled the pages or that rankings improved. Avoid another rename simply because results have not changed yet.

shell
curl -sS -o /dev/null -D - \
  'https://evanlong.me/zh/guides/codex-subscription?utm_source=test'

# Run after this migration is deployed.
# Expected: 301, then a Location ending in
# /zh/articles/codex-subscription?utm_source=test
# Check the destination separately: it should return 200.
Google: post-migration monitoring

A shop click is not a paid order

A subscription article can answer a commercial search question while design and development articles remain useful in their own right. Place a purchase action after the relevant decision, such as finding that a membership is needed, instead of advertising in every section. First complete the task that brought the reader to the article.

This site’s shop_click event records public page paths, placement, and product identifiers without query strings or order materials. It shows where a visitor clicked, not whether they paid. A personal site and shop subdomain do not automatically share a complete purchasing attribution path.

For one landing page and reporting period, separate search impressions and clicks, article visits, product-link clicks, and attributable paid orders. In a hypothetical 100 visits with eight product clicks, the measured link-click rate is 8%; without attributed orders it is not an 8% purchase conversion rate. Small samples also cannot establish a winning title from one or two clicks. Change one identifiable problem and observe the metric it should affect.

Read on

More articles
Type hierarchy and readable column widthProduct design2026-10-09
Codex limits and upgrade costsSubscription guides2026-10-09
Why Claude Code still produces an API billSubscription guides2026-10-09