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 · Lanjutan
1 sinyal bukti di halaman ini

JavaScript SEO adalah tentang apakah mesin pencari dapat crawl, render, dan indeks konten itu bergantung pada JavaScript. Google dapat jalankan JS — failure modes adalah lebih spesifik: parity (mentah vs dirender), interaction (Google tidak scroll atau click), state ( renderer adalah stateless), dan timing. pertahankan tautan sebagai nyata anchors, jangan block JS/CSS, prefer SSR/prerendering untuk konten itu harus peringkat, dan watch infinite scroll — sebuah tall render viewport dapat mendapatkan dua halaman terindeks sebagai satu.

TL;DR — Google dapat jalankan Anda JavaScript, so “dapat Google baca JS?” (terjemahan) “dapat Google baca JS?” adalah wrong pertanyaan. failure modes adalah parity (mentah vs. dirender DOM), interaction (Google tidak scroll atau click), state ( renderer adalah stateless), dan timing. pertahankan tautan sebagai nyata <a href> anchors, jangan block JS/CSS, lazy-muat pada viewport tidak interaction, kembalikan nyata statuses untuk client-side 404s, dan remember sebuah mentah noindex dapat mencegah rendering sebelum JavaScript dapat hapus ini. Combine directives itu adalah sebenarnya processed, tetapi melakukan tidak assume sebuah universal mentah/dirender winner. Watch infinite scroll terutama: sebuah tall render viewport dapat trigger loader dan gabungkan dua URLs ke satu terindeks halaman. untuk renderer internals dan yang rendering mode untuk pick, see rendering.

dapat Google baca JavaScript? Ya — itu’s tidak pertanyaan

Google dapat jalankan Anda JavaScript — nyata risks adalah parity, interaction, state, dan timing. Sumber: /technical-seo/javascript-seo/

Three stages jalankan left untuk right: crawl, render, dan indeks. render stage branches ke four failure modes: parity, di mana dirender DOM dapat tidak match expectations; interaction, di mana konten memerlukan sebuah scroll atau click; state, di mana konten relies pada cookies atau storage itu renderer clears; dan timing, di mana konten adalah deferred behind slow JavaScript.

© Patrick Stox LLC · CC BY 4.0 ·

«Google processes JavaScript apps in three phases: “Google processes JavaScript web apps in three main phases: 1. Crawling 2. Rendering 3. Indexing.” The middle phase runs your JS in an evergreen, headless Chrome to build the DOM that gets indexed. “Rendering is important because websites often rely on JavaScript to bring content to the page, and without rendering Google might not see that content.”

Bukti untuk klaim ini Google processes JavaScript web apps in three main phases: crawling, rendering, and indexing; without rendering, Google might not see JavaScript-provided content. Cakupan: Google Search's processing of JavaScript pages; successful rendering does not guarantee indexing or ranking. Tingkat keyakinan: tinggi · Diverifikasi: Google Search Central: Understand the JavaScript SEO basics

» (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian dua puluh dua, bagian kecil satu: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.)

So Google dapat jalankan Anda JavaScript. berguna pertanyaan adalah lebih spesifik:

«- Parity — does the rendered DOM actually contain what you think it does? » (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian dua puluh empat, bagian kecil satu: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.) «- Interaction — does anything require a scroll/click Google won’t perform? » (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian dua puluh empat, bagian kecil dua: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.) «- State — are you relying on cookies/localStorage the stateless renderer clears? » (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian dua puluh empat, bagian kecil tiga: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.) «- Timing — is critical content deferred behind slow or late JavaScript? » (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian dua puluh empat, bagian kecil empat: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.)

pada timing secara khusus: Google queues sebuah di-crawl halaman (satu 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 sedikit seconds, tetapi ini dapat take lebih lama daripada itu.” ada Tidak published fixed delay atau timeout — dan sebuah halaman itu mengembalikan sebuah non-200 status, atau itu dimulai out dengan sebuah noindex directive, dapat skip render queue alih-alih tunggu untuk JavaScript untuk perubahan ini.

Bukti untuk klaim ini 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. Cakupan: Google Search's documented render-queue behavior; not a guaranteed or universal timing figure. Tingkat keyakinan: tinggi · Diverifikasi: Google Search Central: Understand the JavaScript SEO basics

mechanics dari bagaimana Google renders — Web rendering Service, statelessness, caching, “dua waves” (terjemahan) “dua waves” myth — langsung pada rendering halaman. Di sini I’ll focus pada practical masalah dan memperbaiki.

tautan harus menjadi nyata <a href> anchors

ini adalah single sebagian besar umum JS-SEO bug. “Google dapat hanya discover Anda links jika they adalah <a> HTML elements dengan 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 tidak akan menjadi diikuti, dan halaman itu bergantung 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 dirender DOM. itu dirender anchors adalah parsed setelah JavaScript berjalan, though — landing di dirender DOM membuat sebuah tautan discoverable, ini adalah tidak sebuah promise itu URL mendapatkan di-crawl, terindeks, atau treated yang sama sebagai sebuah tautan present di mentah HTML.

Bukti untuk klaim ini Google can reliably discover links only when they are HTML anchor elements with an href attribute. Cakupan: Link discovery by Google Search; this does not claim that every discovered URL will be crawled or indexed. Tingkat keyakinan: tinggi · Diverifikasi: Google Search Central: Make your links crawlable

Lazy-dimuat dan interaction-gated konten

renderer tidak behave like sebuah curious pengguna: “Google Search melakukan tidak interact dengan Anda halaman.” (terjemahan) “Google Search melakukan tidak interact dengan Anda halaman.” Tidak scrolling, Tidak clicking, Tidak hovering. So apa pun konten itu hanya memuat pada satu dari itu events tidak akan menjadi seen.

Google’s guidance: muat konten ketika ini enters viewport, tidak ketika pengguna acts — “membuat sure itu Anda lazy-loading implementation loads all relevant konten setiap kali it adalah visible di itu viewport,” (terjemahan) “pastikan itu Anda lazy-memuat implementation memuat semua relevant konten setiap kali 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) “jangan tambahkan lazy-memuat untuk konten itu adalah mungkin untuk menjadi immediately terlihat ketika 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 wajar render.

Bukti untuk klaim ini 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. Cakupan: Google Search's documented rendering behavior for lazy-loaded content; other crawlers can behave differently. Tingkat keyakinan: tinggi · Diverifikasi: Google Search Central: Fix lazy-loaded content

Infinite scroll: ketika dua halaman mendapatkan terindeks sebagai satu

Google's tall render viewport dapat trigger sebuah infinite-scroll loader dan gabungkan dua halaman ke satu terindeks URL. Sumber: /technical-seo/javascript-seo/

sebuah wajar browser viewport berhenti setelah pertama halaman, tetapi Google's render viewport expands banyak taller. expansion reaches sebuah infinite-scroll trigger, fires loader tanpa sebuah nyata pengguna scroll, dan appends berikutnya halaman ke yang sama DOM. Google lalu indeks keduanya halaman' konten di bawah satu URL.

© Patrick Stox LLC · CC BY 4.0 ·

ini adalah satu hampir tidak seorang pun menjelaskan, dan ini adalah worth seluruh bagian.

Googlebot dapat render di sebuah viewport considerably taller daripada sebuah typical browser window. Google tidak publish sebuah tepat render viewport size — dan ini dapat perubahan — so jangan design terhadap sebuah spesifik angka; test Anda own implementation alih-alih. Apa penting adalah mechanism: jika Anda infinite-scroll loader fires berdasarkan scroll position atau viewport height, sebuah taller-daripada-yang diharapkan rendering viewport dapat trigger loader selama rendering itself — dan berikutnya artikel atau product halaman’s konten mendapatkan appended ke yang sama DOM. Now dua distinct URLs’ konten memiliki telah dirender together, dan Google dapat indeks them sebagai satu halaman. di my own experience, “occasionally, two pages get indexed as one” (terjemahan) “occasionally, dua halaman mendapatkan terindeks sebagai satu” — I’ve memiliki halaman reported sebagai “tidak indexed” (terjemahan) “tidak terindeks” itu adalah sebenarnya terindeks sebagai bagian dari lainnya halaman (biasanya sebelumnya post di feed), karena “ketika Google resized itu viewport untuk menjadi lebih lama … it triggered itu infinite scroll dan loaded another artikel di ketika it adalah rendering.” (terjemahan) “ketika Google resized viewport untuk menjadi lebih lama … ini triggered infinite scroll dan dimuat lainnya artikel di ketika ini adalah rendering.” Konfirmasi apakah Anda own setup melakukan ini oleh memeriksa pemeriksaan URL’s dirender HTML untuk sebuah halaman Anda’d expect untuk berhenti pendek — jangan assume sebuah size dan jangan assume Anda’re safe.

ada dua layers untuk getting ini right.

«Make infinite scroll search-friendly in the first place. Support paginated loading underneath the infinite scroll. Each chunk should have “its own persistent, unique URL,” the content on each URL should stay the same each time it loads, you should avoid relative parameters like ?date=yesterday, you should “link sequentially to the individual URLs so that search engines can discover the URLs in a paginated set,” and when a new chunk loads on scroll you should “update the displayed URL using the History API.” Use real <a href> pagination links and unique URLs — “don’t use URL fragment identifiers” (the part after a #) for page numbers, because Google ignores them. As I say in 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) (Ringkasan bahasa Indonesia untuk bagian tiga puluh tujuh, bagian kecil satu: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.)

jika sebuah buggy loader adalah actively merging halaman, fastest perbaiki adalah blunt: “block itu JavaScript file itu menangani itu infinite scrolling so itu functionality tidak dapat trigger.” (terjemahan) “block JavaScript file itu menangani infinite scrolling so functionality dapat’t trigger.” jika loader dapat’t jalankan selama render, ini dapat’t append berikutnya halaman’s konten, dan setiap URL renders sebagai itself again.

Soft-404s setelah client-side routing

Single-halaman apps dapat tukar konten tanpa mengubah HTTP kode status, so sebuah “tidak ditemukan” (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. Dua memperbaiki: navigate dengan History API, dan untuk sebuah genuine tidak-ditemukan state either route untuk sebuah URL itu mengembalikan sebuah nyata 404 status atau tambahkan sebuah noindex tag. dan jangan lean pada URL fragments untuk routing — “itu AJAX-crawling scheme memiliki telah deprecated since 2015, so Anda tidak dapat rely pada URL fragments untuk berfungsi dengan 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: awal respons dapat tetap 200 until JavaScript berjalan. Google mendukung JavaScript redirects hanya sebagai sebuah fallback ketika server-side atau meta-refresh redirects adalah tidak mungkin. Report static status dan observed dirender navigation secara terpisah; melakukan tidak rewrite HTTP status di audit atau panggil setiap dirender URL perubahan sebuah redirect.

jangan block JavaScript atau CSS di robots.txt

Google tidak akan 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 jalankan scripts, dan indeks sebuah empty halaman. periksa pemeriksaan URL’s halaman resources untuk apa pun blocked.

DOM parity dan stage-aware robots directives

Bandingkan Anda mentah HTML (View Sumber) terhadap dirender HTML (pemeriksaan URL). konten itu hanya ada di dirender HTML masih indeks — jika ini renders. konten di neither tidak 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.” If your raw HTML ships an initial noindex you meant to swap out with JavaScript, Google can act on that raw noindex and never run the script that would have removed it. » (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian empat puluh enam, bagian kecil satu: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.)

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

FieldApa mentah/dirender perbandingan dapat establish
Main konten dan tautanGoogle dapat gunakan konten dan nyata <a href> tautan produced selama rendering jika rendering succeeds. Mentah availability reduces itu dependency.
judul dan deskripsiGoogle dapat proses JavaScript-set metadata, tetapi judul tautan dan snippets adalah dipilih dari several sources. tampilkan keduanya status; melakukan tidak claim dirender, pertama, atau terakhir nilai adalah guaranteed.
Robots directivessebuah mentah noindex dapat penyebab Google untuk skip rendering, so JavaScript removal dapat tidak pernah menjadi seen. menambahkan restrictions kemudian adalah tidak evidence itu sebuah sebelumnya restriction adalah cancelled.
CanonicalGoogle’s JavaScript guidance says tidak untuk set satu nilai di sumber dan lalu perubahan ini dengan JavaScript. gunakan satu metode dan verify satu dirender-head declaration.
HTTP status dan redirectJavaScript cannot perubahan respons status sudah diterima. Record static status dan apa pun observed dirender navigation sebagai terpisah facts.

«That matrix is why an auditor should keep source, rendered, response-header, and observed-search state distinct rather than collapsing them into one “effective” value. » (Terjemahan) (Ringkasan bahasa Indonesia untuk bagian empat puluh sembilan, bagian kecil satu: teks sumber dipertahankan agar dapat diperiksa dalam tinjauan penutur asli.)

Pick sebuah rendering mode itu puts konten di DOM

sebagian besar JS-SEO risk muncul down untuk bagaimana HTML adalah produced. pendek versi: SSR, static/prerendering, dan hydration semua put konten di (atau quickly ke) DOM, yang reduces bagaimana banyak Anda visibilitas bergantung pada renderer succeeding; penuh client-side rendering leaves lebih riding pada rendering completing correctly, pada time, setiap time. Dynamic rendering adalah sebuah workaround, tidak sebuah peer option — sebagai dari Google’s guidance terakhir diperbarui December 2025, ini mendeskripsikan dynamic rendering sebagai sebuah workaround alih-alih sebuah panjang-istilah solusi dan recommends rendering sisi server, static rendering, atau hydration alih-alih. sebagai I put ini di my JavaScript SEO guide, “any kind dari SSR, static rendering, dan prerendering setup adalah going untuk menjadi fine untuk penelusuran engines.” (terjemahan) “apa pun jenis dari SSR, static rendering, dan prerendering setup adalah going untuk menjadi fine untuk mesin pencari.” penuh menu — CSR, SSR, SSG, hydration, ISR, edge, streaming, dan dynamic rendering — dengan sebuah trade-off table adalah pada rendering halaman. Google secara terpisah mendeskripsikan rendering sisi server atau pre-rendering sebagai sebuah baik idea untuk pengguna dan crawler. Bukti untuk klaim ini Google describes server-side rendering or pre-rendering as a good idea because it makes a website faster for users and crawlers. Cakupan: Google Search guidance for JavaScript sites; the source does not prescribe one framework or guarantee indexing. Tingkat keyakinan: tinggi · Diverifikasi: Google Search Central: Understand the JavaScript SEO basics

cara test

pemeriksaan URL di Search Console adalah sumber kebenaran: jalankan sebuah pengujian langsung, lalu lihat dirender HTML, screenshot, dan halaman resources / console messages untuk see apa dimuat dan apa failed. Rich hasil Test memberikan sebuah quick dirender-HTML periksa. di scale, gunakan crawler itu executes JavaScript (Ahrefs situs Audit, Screaming Frog di JS-rendering mode) untuk diff mentah vs. dirender di seluruh situs.

sebuah render diff adalah diagnostic, tidak sebuah score: investigate essential elements itu muncul hanya setelah JavaScript—atau disappear setelah rendering.

sebuah illustrative halaman memiliki 1 judul di keduanya mentah dan dirender HTML, 18 heading di mentah HTML dan 19 dirender, 42 tautan internal di mentah HTML dan 71 dirender, 0 product deskripsi di mentah HTML dan 12 dirender, dan 6 tag canonical di mentah HTML tetapi hanya 1 dirender. ini counts adalah synthetic.

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

Di mana untuk go berikutnya: JavaScript SEO cluster

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

rendering dan architecture

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

kerangka kerja-spesifik guides

  • React SEO — mengapa CSR-pertama React membuat pengindeksan risk, bagaimana Google renders React apps, React Router dan History API, react-helmet-async untuk meta tags, dan ketika untuk reach untuk Berikutnya.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.
  • Berikutnya.js SEO — halaman Router vs App Router, Metadata API, next/image dan CWV, ISR timing dan Googlebot, sitemaps, dan paling umum Berikutnya.js SEO mistakes.
  • Nuxt SEO — SSR oleh default, useSeoMeta(), Nuxt’s rendering modes, @nuxtjs/seo module ecosystem, dan bagaimana Nuxt compares untuk plain Vue untuk indexability.
  • Vue SEO — Vue 3’s CSR default dan apa itu berarti untuk crawler, createWebHistory(), @unhead/vue, prerendering options tanpa sebuah meta-kerangka kerja, dan ketika 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.

Tambahkan catatan pakar

Sematkan kutipan pakar

Orang baru? Buat profilnya yang belum diklaim di /admin/experts/ → Sematkan kutipan pakar terlebih dahulu.