Giriş: Her Şeyin Mükemmel Göründüğü O Cuma Akşamı
Bu senaryo, hayali ancak sektörde sıkça karşılaştığımız klasik bir Kurumsal (Enterprise) SEO Krizini ele almaktadır. Olayın baş kahramanı olan Emre, İstanbul merkezli, aylık 300.000$ MRR (Aylık Tekrarlayan Gelir) üreten bir B2B İK yazılımı şirketinde (HR-Tech) "VP of Marketing" olarak çalışmaktadır.
Şirket, eski ve yavaş çalışan WordPress altyapısından kurtulmak, daha modern, hızlı ve "cool" görünmek için tüm web sitesini (Blog, Yardım Merkezi, Fiyatlandırma, Çözümler sayfaları dâhil) tamamen React.js ile baştan yazma kararı alır.
Frontend ekibi aylarca uğraşır, harika animasyonlar (Framer Motion), kusursuz bileşenler (TailwindCSS) ve mükemmel bir UI (Kullanıcı Arayüzü) inşa eder. CEO ve yönetim kurulu, yeni sitenin tasarımına bayılır. Emre de SEO ekibiyle birlikte URL yönlendirmelerini (301) yapar ve yeni siteyi Cuma gecesi yayına (Production) alırlar.
Krizin Patlak Vermesi (Pazartesi Sabahı)
Pazartesi sabahı ofise gelen Emre, Google Analytics (GA4) paneline girdiğinde kan dondurucu bir tabloyla karşılaşır. Hafta sonu boyunca organik trafik %85 oranında düşmüştür. Emre panikle Google Search Console'u (GSC) açar. Sıralamada her zaman 1. sayfada oldukları "B2B Personel Takip Programı" aramasında ilk 100'de bile yoktur.
Sorunun kaynağını bulmak için GSC üzerinden "Canlı URL'yi Test Et (Test Live URL)" butonuna basar ve "Ekran Görüntüsü (Screenshot)" sekmesine tıklar. Karşısına çıkan manzara şudur: Bomboş beyaz bir sayfa.
Googlebot, JavaScript'i çalıştıramamış ve sitenin muhteşem tasarımını değil, sadece div id="root" yazan boş bir HTML iskeletini indekslemiştir!
1. Gün: Kök Neden Analizi (Root Cause Analysis)
Emre derhal Frontend Lideri (Lead Developer) Cihan ile acil bir toplantı ayarlar.
Emre: "Cihan, Google sitemizi göremiyor! Search Console'da sayfalarımız bembeyaz görünüyor. SEO trafiğimiz buharlaştı." Cihan: "Nasıl yani? Bende kusursuz açılıyor. Lighthouse skorumuz 95, site çok hızlı. Bütün API istekleri milisaniyede dönüyor. Cache'i temizleyip bir daha baksana?" Emre: "Kullanıcılar görüyor evet ama Googlebot göremiyor!"
Kavramsal Açıklama: Client-Side Rendering (CSR) Tuzağı
Geleneksel web siteleri (WordPress, PHP, HTML) sunucudan tamamen oluşturulmuş (Render edilmiş) bir HTML dosyası gönderir (Buna Server-Side Rendering denir). Googlebot siteye girdiğinde tüm metinleri ve linkleri anında görür.
Ancak standart bir React.js (Create React App - CRA) veya Vue.js projesi (Eğer Next.js SSR veya Nuxt kullanılmamışsa), Client-Side Rendering (CSR) kullanır. Sunucudan sadece şu şekilde bomboş bir dosya gelir:
<!DOCTYPE html>
<html lang="tr">
<head>
<title>B2B SaaS Çözümü</title>
</head>
<body>
<div id="root"></div>
<script src="/static/js/bundle.js"></script>
</body>
</html>
İçerik, kullanıcı tarayıcıya (Browser) girdiğinde o devasa bundle.js dosyasının indirilip çalıştırılmasıyla (Execute) ekrana basılır.
Google'ın Tarama Bütçesi (Crawl Budget) çok değerlidir. Googlebot (Evergreen Chromium tabanlıdır), bu JavaScript'i çalıştırmayı (Render etmeyi) dener, ancak sunucu geç cevap verirse, API'ler yavaşlarsa veya JS dosyasında ufak bir hata (Syntax error) olursa render işlemini iptal eder ve o boş HTML'i dizine ekler.
Karar Noktası 1: Ne Yapılmalı?
Cihan ve Emre'nin önünde 3 seçenek vardır:
- Seçenek A: Bütün siteyi çöpe atıp eski WordPress'e dönmek. (Yönetim kurulu bunu duyarsa herkesi kovar).
- Seçenek B: Projeyi Next.js App Router (Server Components) mimarisine taşımak. (Bu işlem en az 3-4 ay sürer, şirket o zamana kadar batar).
- Seçenek C: Dinamik İşleme (Dynamic Rendering) ile Googlebot'a özel HTML sunmak. (Hızlı ve etkili acil durum çözümü).
Ekip haklı olarak Seçenek C'de (Dynamic Rendering) karar kılar.
2. Gün: Prerender.io ve Dinamik İşleme Entegrasyonu
Dinamik Rendering (Dynamic Rendering) şu anlama gelir: Sunucunuza gelen isteğin (Request) bir gerçek insan mı yoksa Arama Motoru Botu mu olduğunu (User-Agent üzerinden) anlarsınız. Eğer gelen bir insansa, normal React uygulamasını (CSR) gönderirsiniz. Eğer gelen Googlebot, Bingbot veya ChatGPT ise, siteyi arka planda (Headless Chrome ile) çalıştırıp oluşturduğunuz Saf Statik HTML'i bota gönderirsiniz.
Adım 1: Prerender Kurulumu
Emre, sektör standartı olan Prerender.io servisini satın alır. Cihan (Frontend Lideri), sunucu tarafında (Nginx) gelen trafikleri filtrelemek için şu yapılandırmayı (Configuration) yazar:
# Nginx Prerender Kurulumu
location / {
try_files $uri @prerender;
}
location @prerender {
set $prerender 0;
# Gelen ziyaretçi bir SEO Botu mu?
if ($http_user_agent ~* "googlebot|bingbot|yandexbot|slurp|duckduckbot|baiduspider|twitterbot|facebookexternalhit|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest\/0\.|pinterestbot|slackbot|vkShare|W3C_Validator|whatsapp") {
set $prerender 1;
}
# Statik dosyaları (JS, CSS, Resimler) bota gönderme
if ($uri ~* "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff|woff2|svg|eot)") {
set $prerender 0;
}
if ($prerender = 1) {
# Botu Prerender.io servisine yönlendir
rewrite .* /$scheme://$host$request_uri? break;
proxy_pass http://service.prerender.io;
}
if ($prerender = 0) {
rewrite .* /index.html break;
}
}
Adım 2: Hydration (Hidrasyon) Hataları ve Test
Prerender bağlandıktan sonra, site Googlebot'a dolu HTML sunmaya başlar. Ancak Cihan bir detayı atlamıştır: Hydration Mismatch. Sunucudan gelen statik HTML ile tarayıcının React'i yükledikten sonra (Mount/Hydrate aşamasında) ekrana basmaya çalıştığı HTML arasında milisaniyelik bir uyuşmazlık (Örn: Sunucudan gelen saat ile tarayıcıdaki saatin farklı olması) varsa, sayfa FOUC (Flash of Unstyled Content) hatası verir. Ekran bir anlığına bozulup düzelir. Bu Core Web Vitals metriklerinden CLS'yi (Cumulative Layout Shift) mahveder.
Bunu çözmek için useEffect kancalarını (Hook) doğru yapılandırırlar ve sadece Client tarafında render edilmesi gereken animasyon bileşenlerini if (typeof window !== 'undefined') şartı içine alırlar.
4. Gün: Edge SEO ve Cloudflare Workers İle Müdahale
Prerender maliyetli bir çözümdür. Ayda 2 milyon sayfa görüntülemesi alan site için Prerender'a ciddi bir fatura ödemeye başlarlar. Ayrıca Prerender'ın cache (önbellek) süresi yüzünden, siteye girilen yeni bir blog yazısı Google'a bazen 24 saat sonra gitmektedir.
Emre (SEO Yöneticisi), "Prerender harika bir acil durum çözümüdür ama kalıcı mimarimiz bu olamaz. Bize daha native bir çözüm lazım" der.
Cloudflare kullanan şirket, Edge SEO konseptiyle tanışır. Cihan, Cloudflare Workers üzerine küçük bir V8 JavaScript motoru kodu yazar. Sayfayı asıl sunucuya gitmeden (Edge lokasyonunda - Türkiye'deki kullanıcıya İstanbul'dan) HTMLRewriter ile parse eder.
// Cloudflare Worker - HTMLRewriter Example
export default {
async fetch(request, env) {
const url = new URL(request.url);
// Yalnızca blog detay sayfalarını yakala
if (url.pathname.startsWith("/blog/")) {
const response = await fetch(request);
const apiData = await fetch(`https://api.sirket.com/v1/posts?slug=${url.pathname.split('/').pop()}`).then(res => res.json());
// Gelen boş React HTML'ine SEO taglarını göm (Inject)
return new HTMLRewriter()
.on("title", {
element(element) {
element.setInnerContent(`${apiData.title} | Şirket Adı`);
}
})
.on("meta[name='description']", {
element(element) {
element.setAttribute("content", apiData.summary);
}
})
.transform(response);
}
return fetch(request);
}
}
Bu yöntem sayesinde, Googlebot sitenin <head> kısmındaki Meta Description, Title ve Canonical etiketlerini (JavaScript'i hiç çalıştırmasına gerek kalmadan) milisaniyeler içinde görebilir. Bu yöntem, Prerender'a kıyasla %95 daha ucuzdur.
7. Gün: Gerçek Çözüm - Next.js (App Router & SSR) Refactoring
Bir aylık kaosun ve kriz yönetiminin ardından, trafikler %70 oranında toparlanır. Ancak Core Web Vitals (INP ve LCP) skorları hâlâ kırmızıdır. Emre ve Cihan yönetime kalıcı çözümü sunar: Gelecek 6 ay içinde site aşama aşama Next.js'e (Server-Side Rendering) taşınmalıdır.
Çünkü Google'ın algoritmaları (Özellikle Information Gain ve E-E-A-T) çok hızlı çalışır. SEO içeriği bir useEffect içinde sonradan yüklenirse, Google o sayfayı değersiz (Low Quality) kabul etme eğilimindedir.
Büyük kurumsal B2B siteleri, e-ticaret portalları ve haber siteleri (Yani içeriğin çok hızlı dizine eklenmesi gereken yerler) asla saf CSR (Client Side Rendering - Salt React/Vue) ile yapılamaz.
Mutlak Kural: İçeriğiniz API'den geliyorsa (Dinamikse) ve o içeriğin Google'da çıkmasını istiyorsanız, onu kullanıcının bilgisayarında (Browser) değil, sunucuda (Server - Node.js/Next.js) render etmek zorundasınız.
Uzman Önerileri ve Sık Yapılan Hatalar (Best Practices)
- Hasbang (#!) Yönlendirmeleri Asla Kullanmayın:
Eski Angular.js veya React projelerinde URL'ler
site.com/#!/hakkimizdaşeklinde kurgulanırdı. Googlebot, Hash (#) işaretinden sonrasını "Aynı sayfa içindeki bir çıpa (Anchor)" olarak görür ve asla farklı bir sayfa olarak indekslemez. URL'leriniz her zaman temiz (Clean URL) olmalıdır. - Kritik CSS'i (Critical CSS) İçeri Gömün:
Ekranın üst kısmı (Above the Fold) yüklenirken harici bir
style.cssdosyasının indirilmesini beklemeyin. Kritik stilleri<style>etiketleri ile doğrudan HTML içine (Inline) yazın. - Lazy Load'u Akıllıca Kullanın:
Resimlere
loading="lazy"vermek harikadır ama Ekranın en üstündeki kapak görseline (LCP Image) asla lazy load vermeyin! Verirseniz Largest Contentful Paint (LCP) süreniz felaket seviyelere çıkar.
🕸️ Knowledge Graph & Semantik Bağlantılar
Bu içerik, Intent.com.tr'nin Teknik SEO ve Performans Optimizasyonu topikal kümelerinin (Topic Cluster) bir parçasıdır. Konuyu daha derinlemesine anlamak için aşağıdaki varlıkları (Entities) ve ilişkili içerikleri inceleyebilirsiniz:
📖 İlgili Rehberler ve İçerikler
- Core Web Vitals Nedir? LCP ve CLS Nasıl Optimize Edilir?
- Büyük E-Ticaret Sitelerinde Altyapı Taşıma (Migration) Süreci
🧠 Semantic Entities (Terimler)
- Kavram: Tarama Bütçesi (Crawl Budget)
- Kavram: Edge SEO
Semantic Yönerge: Bu sayfa JavaScript Rendering (CSR/SSR) krizlerindeki teknik hata ayıklama niyetini (Debugging Search Intent) karşılamak üzere yapılandırılmıştır.
SSS (Sıkça Sorulan Sorular)
1. Sitemi React ile yazarsam Google beni hiç mi görmez? Görür. Googlebot (WRS - Web Rendering Service) modern bir tarayıcıdır ve JavaScript'i çalıştırır. Ancak bu "ikinci dalga (Second Wave of Indexing)" taramasında olur ve sunucu/render gecikmeleri yüzünden risklidir. SEO odaklı projelerde saf React yerine Next.js (SSR) önerilir.
2. Prerender kullanmak Cloaking (Karartma/Hile) sayılır mı? Hayır. Google (John Mueller dâhil) resmi dokümanlarında "Dynamic Rendering" (Prerender) kullanımının, içerik aynı olduğu sürece Cloaking (Spam) sayılmayacağını belirtmiştir.
3. Next.js App Router mı yoksa Pages Router mı SEO için daha iyi? App Router (React Server Components), sayfayı sunucuda çok daha hafif bir JSON/HTML olarak hazırladığı için Client'a gönderilen JavaScript (Bundle) boyutunu devasa oranda küçültür. Bu da TTI (Time to Interactive) ve TBT (Total Blocking Time) değerlerini inanılmaz düşürür. App Router şu an SEO için endüstri standartıdır.
4. Googlebot'un JavaScript'i nasıl çalıştırdığını nasıl görebilirim? Google Search Console'da "URL Denetimi (URL Inspection)" aracı ile sayfanızı test edin. "Taranan Sayfayı Göster (View Crawled Page)" seçeneğinden "Ekran Görüntüsü (Screenshot)" veya "HTML" sekmesine bakarak botun ne gördüğünü (DOM ağacını) teyit edebilirsiniz.
5. Sayfa yüklendikten sonra SEO etiketlerini (Helmet/next-seo) değiştirmek yeterli mi? React Helmet ile CSR tarafında meta etiketleri değiştirirseniz, Googlebot bunları "okuyabilir" ancak LinkedIn, Twitter, WhatsApp gibi botlar (Open Graph scraper'lar) JavaScript çalıştırmadığı için sayfanızı her zaman "varsayılan (Boş)" title ile paylaşır.
6. Edge SEO nedir? Sadece hız için mi kullanılır? Hayır, Cloudflare Workers gibi Edge SEO teknolojileri, sunucuya dokunmadan (Backend ekibini beklemeden) HTML içine SEO kodları (Örn: Hreflang, Canonical, Schema) enjekte etmek için kullanılır.
7. Yönlendirmeleri (301) React (Client) tarafında yapabilir miyim?
Kesinlikle hayır! Client-Side yönlendirmeler (useHistory.push veya <Navigate>) HTTP başlığında (Header) 301 statü kodu döndürmez (Zaten 200 dönmüştür). Google bu tarz yönlendirmeleri SEO otoritesini (PageRank) geçirmek için geçerli saymaz. Yönlendirme (301) daima Sunucu (Nginx/Node) seviyesinde olmalıdır.