JavaScript'in SEO üzerindeki etkisi çoğu zaman yanlış çerçevelenir. Soru "JavaScript SEO'yu bozuyor mu" değil, "JavaScript hangi koşullarda SEO sorununu gizliyor" olmalıdır. Bir sayfa kaynak kodunda hatasız görünebilir; meta etiketleri doğru, başlık yapısı tutarlı, içerik yerli yerinde. Ama aynı sayfa render edildiğinde bambaşka bir görünüm ortaya çıkabilir. Sorun HTML'de değil, HTML'in nasıl ve ne zaman üretildiğindedir.
JavaScript kaynaklı sorunların tespiti standart araçlarla her zaman mümkün olmaz. Bir tarayıcı JavaScript'i devre dışı bırakarak çalıştığında gördüğü ile tarayıcının render ettiği sayfa çoğu durumda farklıdır. Bu fark, tarama raporlarına doğrudan yansımaz; raporlar temiz görünürken sorun gerçek anlamda var olmaya devam eder. Teknik bir SEO denetiminde JavaScript kaynaklı sorunlar üzerinde ne kadar durulduğu, denetimin ne kadarının gerçekten faydalı olduğunu belirler.
Hangi sorun türlerinin JavaScript'e özgü olduğunu, hangi koşullarda ortaya çıktığını ve hangi araç kombinasyonuyla yüzeye çıkarılabileceğini anlamak, teknik denetimin kalitesini doğrudan etkiler.
Client-side routing yönlendirmeleri Googlebot'tan gizli kalır
Single Page Application (SPA) mimarisi, URL'leri JavaScript'le değiştirir. Kullanıcı bir bağlantıya tıkladığında HTTP isteği olmaz, yeni bir HTML belgesi yüklenmez; mevcut sayfa güncellenir ve adres çubuğundaki URL JavaScript tarafından değiştirilir. React Router, Vue Router, Angular Router gibi kütüphaneler bu işi büyük ölçüde history.pushState ile yapar. Kullanıcı bakış açısından bu sorunsuz işler. Googlebot açısından ise her zaman aynı sonuç alınmaz.
Googlebot bir SPA'ya girdiğinde genellikle ilk yüklenen HTML'yi görür. JavaScript çalıştıktan sonra üretilen navigasyonları, yani farklı route'lar arasındaki geçişleri, her zaman ayrı sayfa olarak işleyemez. Bu durum, birden fazla route'a sahip bir uygulamada bazı URL'lerin Search Console'da hiç görünmemesine ya da yalnızca kök URL'nin indekslenmesine yol açar.
Hash tabanlı routing da ek bir sorun kaynağıdır. /#/hakkimizda gibi yapılandırılan URL'lerde fragment kısmı sunucuya iletilmez. Google bu URL'leri farklı sayfalar olarak indekslemez; Googlebot herkese açık sayfalar için öncelikle sunucu yanıtına bakar ve # sonrasını bu yanıtta aramaz. Böyle bir yapıda tüm içerik tek URL altında toplanır; route sayısı ne kadar olursa olsun.
Bunu tespit etmek için Search Console'daki URL kapsama raporunda beklenmedik "keşfedilmedi" ya da "tarandı fakat indekslenmedi" durumları incelenir. Birden fazla route içeren bir SPA'da her route'un URL'i site: operatörüyle arama sonuçlarında ayrı ayrı kontrol edilebilir. Yalnızca kök URL'nin indekslendiği görülüyorsa, client-side routing sorununun varlığı güçlü biçimde işaret edilmektedir.
Lazy-load içerik tarama anında görünür alanın dışında kalır
Lazy-load, sayfanın ilk yüklenişinde yalnızca görünür alandaki içeriği hemen getirir; görünür alan dışındakileri kullanıcı o bölgeye scroll ettikçe yükler. Performans açısından mantıklıdır: bant genişliğini korur, ilk yükleme süresini kısaltır, Core Web Vitals metriklerine olumlu katkı yapar. Googlebot ise tarama sırasında scroll işlemi yapmaz.
Eski lazy-load uygulamalarının büyük çoğunluğu scroll event'e doğrudan bağlıydı. Kullanıcının sayfayı aşağı kaydırmasıyla tetiklenen scroll eventi içeriği yüklerdi. Googlebot bu eventi üretmediği için içerik hiç yüklenmezdi. Günümüzde Intersection Observer API bu yaklaşımın büyük ölçüde yerini almıştır ve Google bu yöntemi daha güvenilir biçimde işleyebilir. Ancak her projenin Intersection Observer'a geçiş yaptığı varsayılamaz; özellikle daha eski kod tabanlarında ya da üçüncü taraf bileşen kullanan yapılarda scroll event bağımlı lazy-load hâlâ yaygındır.
Pratikte bu şu sonucu doğurur: Bir sayfanın ana içeriği, kritik H2 başlıkları ya da önemli iç linkleri sayfa ortasına ya da altına konumlandırılmışsa ve scroll tabanlı lazy-load ile yükleniyorsa, Googlebot bu içeriği hiç görmüyor olabilir. İçerik kaynak kodunda mevcuttur ama render edilmiş hâlde tarama anında görünür değildir. Bu farkın nasıl gözlemleneceği ve kaynak kod ile render edilmiş DOM arasındaki uyuşmazlıkların nasıl yorumlanacağı rendered HTML kontrolü yazısında ayrıntılı incelenmiştir.
Hızlı bir ön kontrol için Chrome DevTools üzerinden JavaScript tamamen devre dışı bırakılarak sayfa yüklenir. Bu hâlde görünmeyen içerik alanları doğrudan JavaScript bağımlıdır. img etiketlerindeki loading="lazy" niteliği yalnızca görseller için kullanılıyorsa genellikle sorun yaratmaz; Google bu standart niteliği tanır. Ama içerik blokları için özel JS çözümleri devredeyse durum farklılaşır.
JavaScript bağımlı iç linkler tarama haritasına girmeyebilir
Bir bağlantının Googlebot tarafından keşfedilmesi için yalnızca sayfada bulunması yetmez; bağlantının <a href="..."> etiketiyle ve çözümlenmiş bir URL değeriyle DOM'da mevcut olması gerekir. JavaScript ile üretilen bağlantılar bu koşulu her zaman karşılamaz.
Sık karşılaşılan ilk senaryo, onclick event handler'larıyla tanımlanan navigasyonlardır. Görsel olarak tıklanabilir bir bağlantı gibi davranır; kullanıcı tıkladığında JavaScript bir yönlendirme gerçekleştirir. Ama HTML'de href niteliği yoktur ya da javascript:void(0) gibi anlamlı bir URL içermez. Googlebot tıklama event'ini işlemez; bu bağlantı Googlebot için fiilen mevcut değildir.
İkinci senaryo, JavaScript ile DOM'a enjekte edilen menülerdir. Hamburger menüler, dropdown navigasyonlar ya da belirli bir koşul gerçekleştiğinde oluşturulan bağlantı grupları çoğu zaman JavaScript tarafından DOM'a eklenir. Eğer Googlebot sayfa render tamamlanmadan taramasını sonlandırırsa ya da ilgili JS bloğunu çalıştırmazsa, menüdeki bağlantılar hiç görülmez. Büyük sitelerde bu durum, kategori sayfalarına ya da kritik iç sayfalara giden bağlantıların tamamen tarama haritası dışında kalmasına yol açabilir. İç link yapısı analizi yaparken bu farkın gözden kaçması, yanlış bir bağlantı haritasına dayalı kararlar verilmesine yol açar.
Üçüncü senaryo, fetch ya da AJAX ile yüklenen içerik içindeki bağlantılardır. Sayfa açıldığında bir API çağrısıyla ek içerik çekiliyorsa ve bu içeriğin barındırdığı bağlantılar kritikse, Googlebot'un bu bağlantıları görüp görmediği ayrıca doğrulanmalıdır. API yanıtı JSON olarak gelip tarayıcıda DOM'a yazılıyorsa, sunucu tarafında pre-render yoksa Googlebot bu içeriğe erişemez.
Tespit için en etkili yaklaşım, aynı siteyi hem JavaScript devre dışı hem JavaScript etkin modda tarayıp çıktıları karşılaştırmaktır. JS etkin modda keşfedilen bağlantı sayısı, JS devre dışı modun belirgin biçimde üzerindeyse bu fark doğrudan JavaScript bağımlı linklere işaret eder. GSC URL denetleme aracında bağlantı kaynakları incelenerek bu linklerin Googlebot tarafından gerçekten görülüp görülmediği kontrol edilebilir.
Infinite scroll sayfalandırmayı Googlebot için görünmez kılar
Paginator'lı bir yapıda Googlebot her sayfayı ayrı bir URL olarak tarar: /blog/sayfa/2, /blog/sayfa/3 gibi URL'lerin hepsi ayrı hedeflerdir. Infinite scroll bu yapıyı ortadan kaldırır. Kullanıcı sayfayı aşağı kaydırdıkça yeni içerik otomatik yüklenir; ama URL değişmez, yeni içerik için ayrı bir adres yoktur. Googlebot sayfayı ilk yüklediğinde yalnızca o anki içeriği görür.
Bir blog arşivinde ilk yükleme 15 yazıyı getiriyorsa, scroll sonrasında gelen yüzlerce yazı hiç taranmaz. E-ticaret sitelerinde kategori sayfasının yalnızca ilk yükleme ürünleri görünür olur; geri kalan katalog Googlebot'un erişemeyeceği bir alanda kalır. Crawl budget açısından bu iki katmanlı bir sorundur: hem içerik görünmez kalır hem de var olduğu bilinmediği için bütçe hiç ayrılmaz.
Infinite scroll ile arama görünürlüğünü birlikte sağlamanın yolu, her içerik yüklemesine URL atamaktır. Kullanıcı scroll ettikçe ?sayfa=2, ?sayfa=3 gibi parametreler adres çubuğuna yansıtılır ya da her yükleme için ayrı pagination URL'leri tanımlanır. Bu URL'ler Googlebot tarafından taranabilir hâle gelir. Eğer bu yapı yoksa tüm içerik tek URL altında yığılır ve görünürlük ilk yüklemeyle sınırlı kalır.
Bu sorunları yüzeye çıkaran araçlar ve tespit adımları
JavaScript SEO sorunlarını saptamak için birden fazla aracın birlikte kullanımı gerekir. Tek bir araçtan alınan rapor, JavaScript kaynaklı sorunları çoğu zaman eksik gösterir ya da hiç göstermez.
Search Console URL Denetleme her URL için Googlebot'un gördüğü render edilmiş HTML'yi doğrudan sunar. "Sayfayı Google gibi görüntüle" seçeneği Googlebot'un son tarama anındaki DOM görüntüsünü açar. Bu görüntüde kaybolmuş içerik blokları, boş bölümler ya da beklenen iç linkler yoksa render sorunu kesinleşir. Araç aynı zamanda Googlebot'un sayfayı en son ne zaman taradığını da gösterir; bu bilgi, sorun tanımayı zaman boyutunda destekler.
Çift tarama karşılaştırması en bilgilendirici yöntemlerden biridir. Screaming Frog ya da benzer bir araç, aynı siteyi önce JavaScript devre dışı modda, sonra JavaScript etkin modda tarar. İki tarama arasındaki link sayısı, içerik uzunluğu ve sayfa sayısı anlamlı biçimde farklıysa, bu fark doğrudan JavaScript bağımlı alanlara işaret eder. Yalnızca JS etkin modda keşfedilen URL'lerin listesi, sorunun tam kapsamını gösterir. Taranabilirlik ve indeksleme sorunlarının büyük bölümü bu karşılaştırmayla başlar.
Chrome DevTools JavaScript devre dışı modu hızlı bir ön değerlendirme için kullanılır. DevTools içindeki komut paletinden JavaScript devre dışı bırakılarak sayfa yenilenir. Bu hâlde görünmeyen içerik alanları, navigation ya da bağlantı grupları doğrudan JavaScript bağımlıdır. Sayfa tamamen boş geliyorsa ya da yalnızca iskelet bir HTML görünüyorsa, sunucu taraflı render bulunmadığına dair güçlü bir sinyal alınır.
Log dosyası analizi, Googlebot'un gerçekte hangi URL'leri ziyaret ettiğini gösterir. SPA içindeki route URL'leri log dosyalarında hiç görünmüyorsa Googlebot bu URL'lere hiç istek atmamış demektir. Log analizi ile tespit edilen bu boşluklar, client-side routing sorununun bağımsız bir doğrulaması işlevi görür. Log verisine erişim her zaman mümkün olmayabilir ama erişilebildiğinde en kesin sonucu verir.
Network isteklerini izleme de içerik kaynaklarını anlamak için değerlidir. DevTools'da Network sekmesi açıkken sayfa yüklendiğinde JavaScript'in hangi endpoint'lere istek attığı görülür. İçerik bir API'den JSON olarak gelip tarayıcıda DOM'a yazılıyorsa, sunucudan gelen ham HTML bu içeriği barındırmıyordur. Pre-render ya da SSR yoksa Googlebot bu içeriğe erişemez. XHR ve Fetch filtresiyle bu istekler kolayca ayrıştırılır. Teknik SEO analizi sürecinde JavaScript sorunlarına ayrılacak süre, sitenin mimarisine (tam statik, hibrit ya da tam client-side) göre orantılı biçimde planlanır.
JavaScript'in SEO sorununu yaratan değil, sorunun görünmesini geciktiren unsur olduğunu akılda tutmak gerekir. Sorun; içeriğin var olmadığı değil, içeriğin doğru koşulda, doğru zamanda, doğru biçimde sunulup sunulmadığıyla ilgilidir. Googlebot'un bir sayfaya ulaşmasıyla o sayfanın tüm içeriğini işleyebilmesi arasındaki fark, JavaScript yoğun sitelerde en kritik denetim sorusudur.
Hangi sorunu ne kadar önceliklendireceğiniz ise kapsamla belirlenir. Client-side routing sorunu binlerce URL'yi etkileyebilir; lazy-load hatası yalnızca birkaç içerik bloğunu. Bu farkı görmeden müdahale planı yapmak, kaynakları yanlış yönlendirir. Doğru tespit, önceliklendirmeyi mümkün kılar; önceliklendirme, müdahaleyi anlamlı kılar.