Panduan JavaScript SEO

cara pastikan mesin pencari dapat crawl, render, dan indeks JavaScript-dependent konten — nyata tautan, parity, lazy-memuat, infinite scroll, soft-404s, dan testing.

Pertama kali diterbitkan: 23 Jun 2026 · Terakhir diperbarui: 3 Agu 2026 · Advanced
Bahasa
1 sinyal bukti di halaman ini

JavaScript SEO adalah tentang whether mesin pencari dapat crawl, render, dan indeks konten itu depends pada JavaScript. Google dapat run JS — failure modes adalah more spesifik: parity (raw vs rendered), interaction (Google doesn't scroll atau click), state ( renderer adalah stateless), dan timing. pertahankan tautan sebagai nyata anchors, don't block JS/CSS, prefer SSR/prerendering untuk konten itu harus peringkat, dan watch infinite scroll — sebuah tall render viewport dapat get two halaman terindeks sebagai one.

TL;DR — Google dapat run Anda JavaScript, so “can Google read JS?” (terjemahan) “dapat Google read JS?” adalah wrong pertanyaan. failure modes adalah parity (raw vs. rendered DOM), interaction (Google doesn’t scroll atau click), state ( renderer adalah stateless), dan timing. pertahankan tautan sebagai nyata <a href> anchors, don’t block JS/CSS, lazy-muat pada viewport not interaction, kembalikan nyata statuses untuk client-side 404s, dan remember sebuah raw noindex dapat mencegah rendering sebelum JavaScript dapat hapus ini. Combine directives itu adalah actually processed, tetapi melakukan not assume sebuah universal raw/rendered winner. Watch infinite scroll terutama: sebuah tall render viewport dapat trigger loader dan merge two URLs ke one terindeks halaman. untuk renderer internals dan which rendering mode untuk pick, see rendering.

dapat Google read JavaScript? Yes — itu’s not pertanyaan

Google can run your JavaScript — the real risks are parity, interaction, state, and timing. Sumber: /technical-seo/javascript-seo/

Three stages run left to right: crawl, render, and index. The render stage branches into four failure modes: parity, where the rendered DOM may not match expectations; interaction, where content requires a scroll or click; state, where content relies on cookies or storage that the renderer clears; and timing, where content is deferred behind slow JavaScript.

© Patrick Stox LLC · CC BY 4.0 ·

Google processes JavaScript apps di three phases: “Google processes JavaScript web apps in three main phases: 1. Crawling 2. Rendering 3. Indexing.” (terjemahan) “Google processes JavaScript web apps di three main phases: 1. crawling 2. rendering 3. pengindeksan.” middle phase runs Anda JS di sebuah evergreen, headless Chrome untuk bangun DOM itu gets terindeks. “Rendering is important because websites often rely on JavaScript to bring content to the page, and without rendering Google might not see that content.” (terjemahan) “rendering adalah penting because situs web sering rely pada JavaScript untuk bring konten untuk halaman, dan without rendering Google mungkin not see itu konten.”

Evidence for this claim Google processes JavaScript web apps in three main phases: crawling, rendering, and indexing; without rendering, Google might not see JavaScript-provided content. Scope: Google Search's processing of JavaScript pages; successful rendering does not guarantee indexing or ranking. Confidence: high · Verified: Google Search Central: Understand the JavaScript SEO basics

So Google dapat run Anda JavaScript. berguna pertanyaan adalah more spesifik:

  • Parity — melakukan rendered DOM actually berisi what Anda think ini melakukan?
  • Interaction — melakukan anything memerlukan sebuah scroll/click Google won’t perform?
  • State — adalah Anda relying pada cookies/localStorage stateless renderer clears?
  • Timing — adalah critical konten deferred behind slow atau late JavaScript?

pada timing specifically: Google queues sebuah di-crawl halaman (one itu dikembalikan sebuah 200) untuk rendering, dan “the page may stay on this queue for a few seconds, but it can take longer than that.” (terjemahan) “ halaman dapat stay pada ini queue untuk sebuah few seconds, tetapi ini dapat take longer daripada itu.” There’s no published fixed delay atau timeout — dan sebuah halaman itu mengembalikan sebuah non-200 status, atau itu starts out dengan sebuah noindex directive, dapat skip render queue alih-alih wait untuk JavaScript untuk perubahan ini.

Evidence for this claim Google queues crawled pages with a 200 response for rendering; the page may stay in that queue for a few seconds but can take longer, with no published fixed delay or timeout, and non-200 or initial noindex responses may skip rendering. Scope: Google Search's documented render-queue behavior; not a guaranteed or universal timing figure. Confidence: high · Verified: Google Search Central: Understand the JavaScript SEO basics

mechanics dari how Google renders — Web rendering Service, statelessness, caching, “two waves” (terjemahan) “two waves” myth — live pada rendering halaman. Here I’ll focus pada practical masalah dan fixes.

tautan harus menjadi nyata <a href> anchors

ini adalah single sebagian besar umum JS-SEO bug. “Google can only discover your links if they are <a> HTML elements with an href attribute.” (terjemahan) “Google dapat hanya menemukan Anda tautan jika mereka adalah <sebuah> HTML elements dengan sebuah href attribute.” sebuah clickable <div> dengan sebuah onclick handler adalah invisible untuk Google sebagai sebuah tautan — ini won’t menjadi diikuti, dan halaman itu depend pada ini untuk penemuan dapat go uncrawled. ini adalah perfectly fine untuk inject tautan dengan JavaScript, sebagai panjang sebagai mereka end up sebagai nyata <a href> anchors di rendered DOM. itu rendered anchors adalah parsed setelah JavaScript runs, though — landing di rendered DOM membuat sebuah tautan discoverable, ini adalah not sebuah promise itu URL gets di-crawl, terindeks, atau treated yang sama sebagai sebuah tautan present di raw HTML.

Evidence for this claim Google can reliably discover links only when they are HTML anchor elements with an href attribute. Scope: Link discovery by Google Search; this does not claim that every discovered URL will be crawled or indexed. Confidence: high · Verified: Google Search Central: Make your links crawlable

Lazy-dimuat dan interaction-gated konten

renderer doesn’t behave like sebuah curious pengguna: “Google Search does not interact with your page.” (terjemahan) “Google Search melakukan not interact dengan Anda halaman.” No scrolling, no clicking, no hovering. So apa pun konten itu hanya memuat pada one dari itu events won’t menjadi seen.

Google’s guidance: muat konten when ini enters viewport, not when pengguna acts — “make sure that your lazy-loading implementation loads all relevant content whenever it is visible in the viewport,” (terjemahan) “pastikan itu Anda lazy-memuat implementation memuat semua relevant konten whenever ini adalah terlihat di viewport,” dan “don’t add lazy-loading to content that is likely to be immediately visible when a user opens a page.” (terjemahan) “don’t tambahkan lazy-memuat untuk konten itu adalah mungkin untuk menjadi immediately terlihat when sebuah pengguna opens sebuah halaman.” gunakan IntersectionObserver atau native loading="lazy" untuk images — tidak pernah sebuah scroll atau click handler — so konten memuat selama sebuah normal render.

Evidence for this claim Google Search does not interact with a page, so lazy-loaded content should load when it becomes visible in the viewport rather than requiring user interaction. Scope: Google Search's documented rendering behavior for lazy-loaded content; other crawlers can behave differently. Confidence: high · Verified: Google Search Central: Fix lazy-loaded content

Infinite scroll: when two halaman get terindeks sebagai one

Google's tall render viewport can trigger an infinite-scroll loader and merge two pages into one indexed URL. Sumber: /technical-seo/javascript-seo/

A normal browser viewport stops after the first page, but Google's render viewport expands much taller. The expansion reaches an infinite-scroll trigger, fires the loader without a real user scroll, and appends the next page into the same DOM. Google then indexes both pages' content under one URL.

© Patrick Stox LLC · CC BY 4.0 ·

ini adalah one almost nobody menjelaskan, dan ini adalah worth whole bagian.

Googlebot dapat render di sebuah viewport considerably taller daripada sebuah typical browser window. Google doesn’t publish sebuah exact render viewport size — dan ini dapat perubahan — so don’t design terhadap sebuah spesifik angka; test Anda own implementation instead. What penting adalah mechanism: jika Anda infinite-scroll loader fires berdasarkan scroll position atau viewport height, sebuah taller-daripada-expected rendering viewport dapat trigger loader selama rendering itself — dan next artikel atau product halaman’s konten gets appended ke yang sama DOM. Now two distinct URLs’ konten memiliki telah rendered together, dan Google dapat indeks them sebagai one halaman. di my own experience, “occasionally, two pages get indexed as one” (terjemahan) “occasionally, two halaman get terindeks sebagai one” — I’ve memiliki halaman reported sebagai “not indexed” (terjemahan) “not terindeks” itu adalah actually terindeks sebagai bagian dari lainnya halaman (biasanya previous post di feed), because “when Google resized the viewport to be longer … it triggered the infinite scroll and loaded another article in when it was rendering.” (terjemahan) “when Google resized viewport untuk menjadi longer … ini triggered infinite scroll dan dimuat lainnya artikel di when ini adalah rendering.” Confirm whether Anda own setup melakukan ini oleh memeriksa pemeriksaan URL’s rendered HTML untuk sebuah halaman Anda’d expect untuk stop pendek — don’t assume sebuah size dan don’t assume Anda’re safe.

ada two layers untuk getting ini right.

membuat infinite scroll search-friendly di pertama place. mendukung paginated memuat underneath infinite scroll. setiap chunk seharusnya memiliki “its own persistent, unique URL,” (terjemahan) “-nya own persistent, unique URL,” konten pada setiap URL seharusnya stay yang sama setiap time ini memuat, Anda harus hindari relative parameters like ?date=yesterday, Anda harus “link sequentially to the individual URLs so that search engines can discover the URLs in a paginated set,” (terjemahan) “tautan sequentially untuk individual URLs so itu mesin pencari dapat menemukan URLs di sebuah paginated set,” dan when sebuah baru chunk memuat pada scroll Anda harus “update the displayed URL using the History API.” (terjemahan) “update displayed URL menggunakan History API.” gunakan nyata <a href> pagination tautan dan unique URLs — “don’t use URL fragment identifiers” (terjemahan) “don’t gunakan URL fragment identifiers” ( bagian setelah sebuah #) untuk halaman angka, because Google ignores them. sebagai I say di my JavaScript SEO guide, “if you have an infinite scroll setup, I still recommend a paginated page version so that Google can still crawl properly.” (terjemahan) “jika Anda memiliki sebuah infinite scroll setup, I masih recommend sebuah paginated halaman versi so itu Google dapat masih crawl properly.”

jika sebuah buggy loader adalah actively merging halaman, fastest fix adalah blunt: “block the JavaScript file that handles the infinite scrolling so the functionality can’t trigger.” (terjemahan) “block JavaScript file itu handles infinite scrolling so functionality dapat’t trigger.” jika loader dapat’t run selama render, ini dapat’t append next halaman’s konten, dan setiap URL renders sebagai itself again.

Soft-404s setelah client-side routing

Single-halaman apps dapat swap konten tanpa mengubah HTTP kode status, so sebuah “not found” (terjemahan) “tidak ditemukan” view dapat masih kembalikan 200. Google dapat classify itu respons sebagai sebuah soft 404 setelah evaluating dikembalikan konten, tetapi sebuah static fetch alone cannot prove itu Google memiliki dibuat itu classification. Two fixes: navigate dengan History API, dan untuk sebuah genuine not-ditemukan state either route untuk sebuah URL itu mengembalikan sebuah nyata 404 status atau tambahkan sebuah noindex tag. dan don’t lean pada URL fragments untuk routing — “the AJAX-crawling scheme has been deprecated since 2015, so you can’t rely on URL fragments to work with Googlebot.” (terjemahan) “ AJAX-crawling scheme memiliki telah deprecated since 2015, so Anda dapat’t rely pada URL fragments untuk berfungsi dengan Googlebot.”

sebuah client-side redirect memiliki yang sama evidence masalah: initial respons dapat remain 200 until JavaScript runs. Google mendukung JavaScript redirects hanya sebagai sebuah fallback when server-side atau meta-refresh redirects adalah not mungkin. Report static status dan observed rendered navigation separately; melakukan not rewrite HTTP status di audit atau panggil setiap rendered URL perubahan sebuah redirect.

Don’t block JavaScript atau CSS di robots.txt

Google won’t render JavaScript dari blocked files atau pada blocked halaman. sebuah robots.txt aturan itu disallows Anda bundle (atau /_next/, /static/, /assets/ directory ini lives di) dapat break rendering entirely — Google fetches shell, dapat’t run scripts, dan indeks sebuah empty halaman. periksa pemeriksaan URL’s halaman resources untuk anything blocked.

DOM parity dan stage-aware robots directives

Compare Anda raw HTML (View Source) terhadap rendered HTML (pemeriksaan URL). konten itu hanya exists di rendered HTML masih indeks — jika ini renders. konten di neither doesn’t exist untuk Google.

There’s one stage-order risk Google documents directly: “When Google encounters the noindex tag, it may skip rendering and JavaScript execution, which means using JavaScript to change or remove the robots meta tag from noindex may not work as expected.” (terjemahan) “When Google encounters noindex tag, ini dapat skip rendering dan JavaScript execution, which berarti menggunakan JavaScript untuk perubahan atau hapus robots meta tag dari noindex dapat not berfungsi sebagai expected.” jika Anda raw HTML ships sebuah initial noindex Anda dimaksudkan untuk swap out dengan JavaScript, Google dapat act pada itu raw noindex dan tidak pernah run script itu akan memiliki dihapus ini.

melakukan not turn ini ke sebuah universal “rendered wins” (terjemahan) “rendered wins” aturan. Reconciliation adalah field-spesifik:

FieldWhat raw/rendered comparison dapat establish
Main konten dan tautanGoogle dapat gunakan konten dan nyata <a href> tautan produced selama rendering jika rendering succeeds. Raw availability reduces itu dependency.
judul dan deskripsiGoogle dapat process JavaScript-set metadata, tetapi judul tautan dan snippets adalah selected dari several sources. tampilkan both states; melakukan not claim rendered, pertama, atau last nilai adalah guaranteed.
Robots directivessebuah raw noindex dapat cause Google untuk skip rendering, so JavaScript removal dapat tidak pernah menjadi seen. menambahkan restrictions later adalah not evidence itu sebuah earlier restriction adalah cancelled.
CanonicalGoogle’s JavaScript guidance says not untuk set one nilai di source dan lalu perubahan ini dengan JavaScript. gunakan one metode dan verify one rendered-head declaration.
HTTP status dan redirectJavaScript cannot perubahan respons status sudah diterima. Record static status dan apa pun observed rendered navigation sebagai separate facts.

itu matrix adalah why sebuah auditor seharusnya pertahankan source, rendered, respons-header, dan observed-search state distinct alih-alih collapsing them ke one “effective” (terjemahan) “effective” nilai.

Pick sebuah rendering mode itu puts konten di DOM

sebagian besar JS-SEO risk comes down untuk how HTML adalah produced. pendek versi: SSR, static/prerendering, dan hydration semua put konten di (atau quickly ke) DOM, which reduces how much Anda visibilitas depends pada renderer succeeding; full client-side rendering leaves more riding pada rendering completing correctly, pada time, setiap time. Dynamic rendering adalah sebuah workaround, not sebuah peer option — sebagai dari Google’s guidance last updated December 2025, ini describes dynamic rendering sebagai sebuah workaround alih-alih sebuah panjang-istilah solusi dan recommends rendering sisi server, static rendering, atau hydration instead. sebagai I put ini di my JavaScript SEO guide, “any kind of SSR, static rendering, and prerendering setup is going to be fine for search engines.” (terjemahan) “apa pun jenis dari SSR, static rendering, dan prerendering setup adalah going untuk menjadi fine untuk mesin pencari.” full menu — CSR, SSR, SSG, hydration, ISR, edge, streaming, dan dynamic rendering — dengan sebuah trade-off table adalah pada rendering halaman. Google separately describes rendering sisi server atau pre-rendering sebagai sebuah baik idea untuk pengguna dan crawler. Evidence for this claim Google describes server-side rendering or pre-rendering as a good idea because it makes a website faster for users and crawlers. Scope: Google Search guidance for JavaScript sites; the source does not prescribe one framework or guarantee indexing. Confidence: high · Verified: Google Search Central: Understand the JavaScript SEO basics

cara test

pemeriksaan URL di Search Console adalah sumber kebenaran: run sebuah live test, lalu lihat rendered HTML, screenshot, dan halaman resources / console messages untuk see what dimuat dan what failed. Rich hasil Test gives sebuah quick rendered-HTML periksa. di scale, gunakan crawler itu executes JavaScript (Ahrefs situs Audit, Screaming Frog di JS-rendering mode) untuk diff raw vs. rendered di seluruh situs.

A render diff is diagnostic, not a score: investigate essential elements that appear only after JavaScript—or disappear after rendering.

An illustrative page has 1 title in both raw and rendered HTML, 18 headings in raw HTML and 19 rendered, 42 internal links in raw HTML and 71 rendered, 0 product descriptions in raw HTML and 12 rendered, and 6 canonical tags in raw HTML but only 1 rendered. These counts are synthetic.

JavaScript adalah not buruk untuk SEO, dan ini adalah not evil. ini adalah hanya berbeda dari what banyak SEOs adalah digunakan untuk. berfungsi dengan Anda developers, get Anda penting konten ke DOM, dan let Google’s own alat — not Anda assumptions — menjadi arbiter dari what rendered.

Where untuk go next: JavaScript SEO cluster

ini hub adalah map. setiap topic below adalah -nya own deep dive:

rendering dan architecture

  • SEO untuk sebuah CMS headless — how decoupled frontends affect crawling, rendering, metadata, sitemaps, dan tag canonical; which rendering mode untuk pick; dan headless-spesifik failure modes Anda perlu know.

framework-spesifik guides

  • React SEO — why CSR-pertama React membuat pengindeksan risk, how Google renders React apps, React Router dan History API, react-helmet-async untuk meta tags, dan when untuk reach untuk Next.js.
  • Angular SEO — Angular’s SPA defaults, @angular/ssr (Angular Universal’s successor), dibangun-di judul dan Meta services, prerendering, dan incremental hydration di modern Angular.
  • Next.js SEO — halaman Router vs App Router, Metadata API, next/image dan CWV, ISR timing dan Googlebot, sitemaps, dan paling umum Next.js SEO mistakes.
  • Nuxt SEO — SSR oleh default, useSeoMeta(), Nuxt’s rendering modes, @nuxtjs/seo module ecosystem, dan how Nuxt compares untuk plain Vue untuk indexability.
  • Vue SEO — Vue 3’s CSR default dan what itu berarti untuk crawler, createWebHistory(), @unhead/vue, prerendering options without sebuah meta-framework, dan when Nuxt adalah right panggil.
  • Svelte SEO — Svelte vs SvelteKit, SSR oleh default di SvelteKit, <svelte:head>, adapter-static + ssr: false trap, adapter choices, dan AI crawler implications.
  • Astro SEO — zero-JS oleh default, islands architecture, @astrojs/sitemap, astro:assets, View Transitions dan History API, server Islands fallback perilaku, dan Astro’s Core Web Vitals advantages.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.