SEO single page application: mengapa SPA gagal berperingkat, bagaimana SSR, static generation, dan prerendering memperbaikinya, serta cara membuat aplikasi Anda terbaca oleh crawler AI.

Singkatnya
single page application (SPA) memuat satu shell HTML dan membangun setiap tampilan dengan JavaScript di browser. Google dapat merender JavaScript, tetapi rendering-nya tertunda dan rapuh, dan crawler di balik ChatGPT, Claude, dan Perplexity sama sekali tidak mengeksekusinya. Agar berperingkat dan dikutip, setiap tampilan SPA membutuhkan URL sendiri, tautan sungguhan dengan href, title dan deskripsi yang unik, kode status yang benar dan, terutama, konten utamanya ada di HTML yang dikirim server, melalui server-side rendering, static generation, atau prerendering.
Ingin tahu lebih banyak? Tanyakan kepada
SEO single page application adalah sekumpulan teknik yang membuat aplikasi JavaScript yang dibangun dengan React, Vue, Angular, atau Svelte semudah di-crawl seperti situs web klasik. Masalahnya terdokumentasi dengan baik: Google menjelaskan di dasar-dasar SEO JavaScript bahwa ia memproses halaman JavaScript dalam tiga fase (crawling, rendering, pengindeksan), dan setiap kelemahan SPA berada di suatu titik dalam alur itu. Panduan ini berfokus pada SPA; untuk situs JavaScript secara umum, baca panduan kami tentang SEO JavaScript.
Situs web tradisional mengembalikan dokumen HTML lengkap untuk setiap URL. SPA mengembalikan dokumen yang hampir sama untuk setiap URL: <div id="root"> kosong, beberapa meta tag, dan bundle JavaScript yang besar. Browser mengunduh bundle, memanggil API, lalu menggambar halaman. Ketika pengunjung mengklik tautan, JavaScript menukar konten tanpa memuat ulang.
Bagi manusia dengan ponsel cepat, hasilnya terasa instan. Bagi crawler, respons pertama adalah shell kosong: tanpa heading, tanpa teks, tanpa tautan. Semuanya bergantung pada apakah bot mengeksekusi JavaScript, dan kapan. Satu fakta itu menjelaskan sebagian besar masalah SEO SPA:
/#/pricing), dan bagian setelah # tidak pernah dikirim ke server, sehingga semua tampilan runtuh menjadi satu URL.<title>, dan jika router tidak memperbaruinya, setiap halaman memakai title yang sama.href: tombol dan handler onClick bernavigasi bagi pengguna tetapi tidak memberi crawler apa pun untuk diikuti.Googlebot pertama-tama mengambil HTML mentah dan membaca tautan serta direktif yang ditemukan di sana. Halaman yang mengembalikan status 200 kemudian dimasukkan ke antrean untuk Web Rendering Service, Chromium headless. Google menyatakan bahwa halaman "mungkin berada di antrean ini selama beberapa detik, tetapi bisa lebih lama dari itu". Setelah dirender, HTML hasilnya diurai lagi untuk konten dan tautan, lalu diindeks.
Empat detail dari dokumentasi Google yang penting bagi SPA:
<a> dengan href yang merupakan tautan andal. Tautan yang disisipkan oleh JavaScript tidak masalah selama mengikuti format itu.pushState) alih-alih rute #. Google menghentikan skema crawling AJAX lamanya (URL #!) pada Oktober 2015.noindex di HTML asli menang. Google dapat melewati rendering saat melihat noindex, jadi menghapusnya dengan JavaScript belakangan tidak berhasil.Konsekuensi praktisnya: Google bisa mengindeks SPA yang dirender di sisi klien, tetapi Anda menambahkan langkah kedua, penundaan, dan titik kegagalan pada setiap halaman. Timeout, panggilan API yang diblokir, atau error JavaScript saat rendering membuat versi yang terindeks kosong. Periksa apa yang dilihat Google dengan alat Inspeksi URL di Search Console, dan baca panduan kami tentang cara kerja pengindeksan Google jika halaman tetap tidak terindeks.
Sebagian besar tidak. Dalam studi yang diterbitkan pada Desember 2024 tentang trafik jaringannya, Vercel dan MERJ menemukan bahwa "tidak ada crawler AI utama yang saat ini merender JavaScript": GPTBot, OAI-SearchBot, dan ChatGPT-User (OpenAI), ClaudeBot (Anthropic), PerplexityBot, Meta-ExternalAgent, dan Bytespider semuanya hanya membaca HTML mentah. Mereka memang mengunduh file JavaScript (sekitar 11.5% permintaan ChatGPT dan 23.8% permintaan Claude) tetapi tidak menjalankannya. Pengecualiannya adalah Gemini, yang mengandalkan infrastruktur rendering Google, dan AppleBot, yang memakai crawler berbasis browser.
Untuk SPA yang dirender di sisi klien, ini berarti crawler AI yang menyuplai ChatGPT, Claude, dan Perplexity melihat halaman kosong. Produk Anda bisa berperingkat di Google dan tetap tidak terlihat di jawaban AI, karena asisten tidak pernah membaca satu kata pun darinya. Hal yang sama berlaku untuk sebagian besar bot pratinjau tautan di jaringan sosial dan aplikasi pesan, yang membaca tag Open Graph di HTML mentah. Setelah konten ada di HTML, periksa juga bahwa robots.txt mengizinkan crawler AI yang Anda inginkan.
Solusinya adalah mengirim HTML sungguhan pada respons pertama. Google menyebut dynamic rendering (menyajikan versi prerender hanya untuk bot) sebagai "solusi sementara dan bukan solusi yang direkomendasikan" dalam dokumentasi dynamic rendering-nya, dan mengarahkan ke server-side rendering, static rendering, atau hydration sebagai gantinya. Definisi di bawah mengikuti referensi Rendering on the Web di web.dev.
| Strategi | Cara kerja | Konten di HTML pertama | Paling cocok untuk | Keterbatasan |
|---|---|---|---|---|
| Client-side rendering (CSR) | Browser membangun halaman dari JavaScript dan API | Tidak | Dasbor dan halaman di balik login | Pengindeksan Google tertunda, tidak terlihat oleh sebagian besar crawler AI |
| Server-side rendering (SSR) | Server merender HTML pada setiap permintaan, lalu JavaScript melakukan hydrate | Ya | Katalog, daftar, konten yang sering berubah atau dipersonalisasi | Biaya server, waktu respons lebih lambat jika tidak di-cache |
| Static generation (SSG) | HTML dibuat saat build untuk setiap URL dan disajikan dari CDN | Ya | Halaman pemasaran, blog, dokumentasi, landing page | Perlu build ulang saat konten berubah (ada opsi inkremental) |
| Prerendering saat build | Browser headless menangkap kondisi awal setiap rute sebagai HTML statis | Ya | SPA yang sudah ada dengan jumlah rute publik terbatas | Data membeku saat build, rute harus didaftar |
| Dynamic rendering | Bot menerima snapshot prerender, pengguna menerima SPA | Ya, hanya untuk bot yang terdaftar | Perbaikan sementara untuk aplikasi lama | Resminya solusi sementara, biaya pemeliharaan, risiko menyajikan konten berbeda kepada bot |
Sebagian besar framework modern memungkinkan Anda memadukan strategi per rute: statis untuk halaman pemasaran, dirender server untuk katalog, dirender klien untuk aplikasi setelah login. Pengaturan hibrida itu memberi crawler HTML lengkap di tempat trafik pencarian terjadi dan mempertahankan pengalaman SPA di tempat yang memberi nilai.
| Library | Framework atau fitur untuk HTML saat pemuatan pertama |
|---|---|
| React | Next.js (server component, SSR, dan static generation), React Router dalam mode framework, Gatsby |
| Vue | Nuxt (universal rendering secara default, static generation tersedia) |
| Angular | Angular SSR (server rendering dan prerendering saat build) |
| Svelte | SvelteKit (server rendering secara default, prerendering per rute) |
| Salah satunya | Astro (HTML statis secara default, island interaktif dimuat hanya jika perlu) |
Situs yang dihasilkan oleh AI website builder layak disebut khusus: banyak yang mengekspor aplikasi React yang dirender di sisi klien. Jika Anda membangun situs dengan salah satunya, lihat catatan kami tentang SEO dan GEO Lovable sebelum menganggap Google dan ChatGPT dapat membacanya.
Gunakan History API (/pricing, jangan pernah /#/pricing), satu URL per konten, dan URL yang sama baik pengunjung datang langsung maupun lewat navigasi dalam aplikasi. Setiap URL harus memuat konten yang benar saat dibuka di tab baru, yang merupakan uji yang dilakukan crawler.
Setiap elemen navigasi yang mengarah ke halaman yang dapat diindeks sebaiknya berupa <a href="/path">. Komponen tautan framework (Link, NuxtLink, routerLink) menghasilkan markup ini; handler klik kustom pada elemen div atau button tidak. Tautan yang baik juga membawa arsitektur situs Anda: jika sebuah halaman tidak ditautkan, crawler jarang menemukannya.
Setiap rute membutuhkan title, meta description, canonical, dan tag Open Graph sendiri, yang sebaiknya dibuat di server. Halaman kami tentang meta tag mendaftar apa yang perlu diatur. Pertahankan satu canonical tag: Google merekomendasikan untuk mengaturnya di HTML, dan jika JavaScript mengubahnya, hasilnya tidak boleh bertentangan dengan yang asli.
Produk yang hilang dan artikel yang dihapus tidak boleh menjawab 200 dengan pesan error. Dengan SSR, kembalikan 404 atau 410 sungguhan dari server. Dalam SPA murni, Google menerima dua alternatif: alihkan dengan JavaScript ke URL yang mengembalikan 404, atau tambahkan meta robots noindex pada tampilan error.
Heading, teks isi, harga, FAQ, dan data terstruktur JSON-LD sebaiknya ada di respons server, bukan dimuat setelah klik atau gulir. Konten di balik tab yang dirender sesuai permintaan, atau di balik tombol "muat lebih banyak", sering terlewat.
Pecah bundle per rute, tunda yang tidak dibutuhkan untuk tampilan pertama, dan hindari merender ulang seluruh halaman saat hydration. Perhatikan bahwa data lapangan Chrome (CrUX) mengaitkan metrik navigasi dalam aplikasi dengan URL yang pertama kali dimuat pengunjung, jadi uji templat utama Anda satu per satu.
Bandingkan tiga versi dari setiap templat utama: HTML mentah (lihat sumber atau ambil halaman dengan alat baris perintah), HTML hasil render Google (Inspeksi URL, lalu "Lihat halaman yang di-crawl"), dan halaman dengan JavaScript dinonaktifkan. Jika teks utama hanya muncul di versi kedua, crawler AI tidak melihatnya. Audit crawlability untuk AI gratis kami dan indexability checker menjalankan pemeriksaan ini pada URL mana pun.
| Gejala | Kemungkinan penyebab | Solusi |
|---|---|---|
| Search Console menampilkan banyak halaman "Di-crawl, saat ini belum diindeks" | HTML kosong atau hampir identik sebelum rendering | SSR, SSG, atau prerendering untuk rute publik |
Setiap hasil pencarian site: menampilkan title yang sama | Title tidak diperbarui per rute | Pengelolaan head tingkat rute di server |
| Hanya beranda yang terindeks | Hash routing atau tautan tanpa href | History API dan tautan <a> sungguhan |
| Halaman error muncul di indeks | Soft 404 (status 200 di mana-mana) | 404 dari server, atau pengalihan JavaScript ke URL 404, atau noindex |
| Berperingkat di Google tetapi tidak pernah dikutip ChatGPT atau Perplexity | Konten baru terlihat setelah JavaScript dieksekusi | Konten di respons HTML pertama |
| Konten lama tampil di tampilan render Google | File JavaScript atau CSS yang di-cache | Nama file dengan fingerprint |
Selama bertahun-tahun, client-side rendering adalah risiko yang bisa dikelola karena Google akhirnya merender JavaScript. Dengan sebagian penemuan kini terjadi di ChatGPT, Claude, Gemini, dan Perplexity, biayanya berubah: halaman yang baru ada setelah JavaScript dieksekusi tidak ada di sumber yang bisa dibaca sebagian besar asisten. Crawlability di HTML mentah telah menjadi syarat pertama generative engine optimization.
Setelah HTML lengkap, sisanya mengikuti aturan yang biasa: halaman yang menjawab satu pertanyaan dengan jelas, dengan fakta bersumber dan data terstruktur, adalah yang dikutip asisten. Fitur optimasi GEO Sorank membantu Anda menulis dan menerbitkan konten itu, dan pelacakan sebutan AI menunjukkan apakah ChatGPT, Claude, dan Gemini mengutip merek Anda setelah perbaikan rendering.
Aturan utama SEO single page application muat dalam satu kalimat: apa pun yang ingin Anda peringkatkan di Google dan dikutip AI harus ada di HTML yang dikirim server. Pertahankan SPA untuk pengalaman setelah login, render halaman publik di server atau saat build, lalu uji apa yang diterima bot sebelum dan sesudah setiap rilis.
Single page application tidak dihukum oleh Google, tetapi pengaturan defaultnya, client-side rendering dengan satu shell HTML, membuat pengindeksan lebih lambat dan kurang andal. Sebagian besar crawler AI tidak mengeksekusi JavaScript, sehingga melihat halaman kosong. Dengan server-side rendering, static generation, atau prerendering pada rute publik, SPA dapat berperingkat sebaik situs web klasik mana pun.
React sendiri netral: yang penting adalah di mana HTML dihasilkan. Aplikasi React yang hanya dirender di browser mengalami masalah SPA yang biasa, sedangkan komponen yang sama yang dirender di server dengan Next.js atau React Router dalam mode framework mengirim HTML lengkap ke crawler. Pilih framework yang mendukung rendering server atau statis untuk halaman yang ingin Anda indeks.
Hanya sebagai langkah sementara. Google menggambarkan dynamic rendering sebagai solusi sementara dan bukan solusi yang direkomendasikan, karena memelihara versi terpisah untuk bot menambah biaya dan risiko. Server-side rendering, static generation, atau prerendering saat build memberi HTML yang sama kepada setiap pengunjung dan merupakan solusi jangka panjang.
MEREKA MENCOBA SORANK SEBELUM ANDA
