A fictional business. The figures are a modelled scenario, not a client result.
종이연 코믹스 · 서울Paperkite Comics · Webcomic platform · Seoul
+9,600indexed episodes
모든 이야기는 문제에서 시작한다Every story starts with a problem
문제The challenge
Infinite-scroll reader pages with client-side rendering meant Google indexed only series covers, never episodes, in Korean, English or Indonesian.
Paperkite publishes 140 series in Korean, with English and Indonesian translations a week behind. Readers loved the endless vertical scroll; crawlers got an empty page and a cover image. Search traffic came almost entirely from series names — nobody searching for “episode 41” or a genre in Bahasa ever found them.
그래서 우리는 뷰어를 열었다So we opened up the reader
진단Audit & diagnosis
Render snapshots of 2,000 sampled episodes, four weeks of server logs and a full hreflang crawl across all three languages.
The reader route returned a 2 KB HTML shell; panels, title and episode number arrived only after a 1.4 MB client bundle ran. Googlebot's rendered snapshot timed out on 71% of sampled episodes.
Episode 2 onwards loaded on scroll via fetch with no URL change. 11,600 of 12,000 episodes had no crawlable link pointing at them anywhere on the site.
Every translated episode declared the Korean series cover as its alternate, and ID pages lacked a return tag: 3,140 hreflang errors, with Indonesian readers landing on Korean pages.
A scroll listener re-measured every panel image on each frame, and the next-episode button waited on an analytics call. p75 INP on mobile sat at 620 ms.
Comment pagination (?page=2…40) canonicalised to the series cover, telling Google every episode and every comment page was a duplicate of it.
크롤러의 시선What Googlebot received
<h1>Paper Kite · Episode 41</h1>
<p>The wind changes over Namsan…</p>
<img alt="Panel 1: Ha-eun lifts the kite"
width="720" height="1180" …>
<nav>
<a href="…/ep-40">Previous</a>
<a href="…/ep-42">Next</a>
</nav>
<a href="…/archive?page=1">All episodes</a>Title, synopsis, alt text and neighbour links in the first response. Indexable on the first crawl.
작전 개시The plan
전략Strategy
Built on our Signal technical SEO plan: four tactics, shipped language by language so each fix could be measured on its own.
Tactic 01
Moved the reader to server components: episode title, number, synopsis, panel alt text and next/previous links are in the first HTML byte. The panel images stream lazily below the first three.
Tactic 02
Each episode got its own clean URL (/series/slug/ep-41) with plain <a> links to neighbours, plus a paginated series archive at 50 episodes per page. Scroll still feels endless, but the URL updates with history.replaceState as each episode boundary passes.
Tactic 03
Rebuilt the hreflang cluster per episode — ko, en, id and x-default — generated from the translation table so every alternate is reciprocal. Untranslated episodes simply omit their tag instead of pointing at a cover.
Tactic 04
Replaced the per-frame scroll listener with an IntersectionObserver, reserved panel heights from stored dimensions, deferred analytics with requestIdleCallback and split the comments widget out of the reader bundle.
한 화, 세 언어One episode, three languages
제41화 · 바람의 방향
드디어… 바람이 바뀌었어!
<head> · /ko/series/paper-kite/ep-41
<link rel="canonical" href="/ko/series/paper-kite/ep-41"> <link rel="alternate" hreflang="ko" href="/ko/series/paper-kite/ep-41"> <link rel="alternate" hreflang="en" href="/en/series/paper-kite/ep-41"> <link rel="alternate" hreflang="id" href="/id/series/paper-kite/ep-41"> <link rel="alternate" hreflang="x-default" href="/ko/series/paper-kite/ep-41">
Every version lists every other — and itself. Before, all three pointed at the Korean series cover.
연재 일정8 months, one episode at a time
제1화 · 진단
Render snapshots of 2,000 sampled episodes, log-file analysis, and a hreflang crawl across all three languages.
420 episodes indexed
제2화 · 설계
Episode URL scheme, archive pagination and canonical rules agreed with the engineering team; redirect map for legacy hash URLs.
610 episodes indexed
제3화 · 서버
Reader moved to server components for Korean first. Rendered HTML now carries title, number and neighbour links.
1,450 episodes indexed
제4화 · 번역
Reciprocal ko / en / id / x-default clusters generated from the translation table; Indonesian sitemap split out.
3,200 episodes indexed
제5화 · 속도
Scroll listener removed, analytics deferred, comments split out. p75 INP drops below 250 ms.
5,400 episodes indexed
제6화 · 확장
Server rendering rolled out to EN and ID readers; archive pages submitted in per-language sitemaps.
7,600 episodes indexed
제7화 · 정리
Comment pagination given self-canonicals and noindex beyond page 5; orphaned episodes linked from archive pages.
9,100 episodes indexed
제8화 · 완결
10,020 episodes indexed. Monitoring alerts on render-snapshot size and hreflang error counts, handed over to the in-house team.
10,020 episodes indexed
8개월 후…8 months later…
결과Results
Indexed episodes at the end of each month (modelled Search Console coverage).
420 → 10,020
Indexed episodes
+264%
Organic readers
620ms → 160ms
INP
-96%
Hreflang errors
Modelled scenario for a fictional business — not a client result. Rankings and traffic are never guaranteed; see our Terms.
검색 순위Rankings by language
| Query | Lang | Monthly searches | Before | After |
|---|---|---|---|---|
| 로맨스 판타지 웹툰 무료 | KO | 22,000 | not ranked | 4 |
| 종이연 웹툰 41화 | KO | 3,600 | not ranked | 1 |
| webtoon romance fantasy free | EN | 14,800 | 48 | 6 |
| read korean webcomic english | EN | 9,900 | not ranked | 9 |
| baca komik korea bahasa indonesia | ID | 18,100 | not ranked | 3 |
| webtoon gratis episode terbaru | ID | 12,100 | 62 | 7 |
| slice of life webtoon recommendations | EN | 5,400 | 31 | 5 |
다음 화에 계속To be continued — in your story
Pages Google can’t render, languages that point at each other wrong, readers who tap and wait. Signal fixes the plumbing.