79.000 Doktor Profili Programatik SEO: Pipeline ve Teknik Detaylar
doktorbul.com için 79.000 doktor profilini otomatik üreten pipeline'ı nasıl kurdum? Veri toplama, şablon tasarımı, toplu yayınlama ve SEO optimizasyonu.

Bir e-ticaret sitesine 500 ürün eklemek zaten zahmetli. Peki ya 79.000 doktor profili? Her birinin kendi URL'si, meta açıklaması, yapılandırılmış verisi olacak. Manuel giremezsin, Excel'den toplu import edemezsin, çünkü her doktor farklı branşta, farklı şehirde, farklı hastanede çalışıyor. Bu noktada programatik SEO devreye giriyor. Ben doktorbul.com projesi için tam olarak bunu yaptım: 79.000 doktor profilini otomatik üreten, SEO-optimize eden, sürekli güncellenebilen bir pipeline kurdum. Bu yazıda o pipeline'ın teknik detaylarını, karşılaştığım sorunları ve çözümleri paylaşacağım. Programatik SEO, elle yönetilemeyecek kadar büyük veri setlerini arama motorlarına sunmanın tek yolu. Ama çoğu proje burada hata yapıyor: şablonu kopyala yapıştır gibi düşünüyorlar. Oysa gerçek zorluk, her sayfanın tekil olmasını sağlamak, veri kalitesini korumak ve yayın sürecini otomatikleştirmek. doktorbul.com'da sadece profil sayfaları değil, şehir bazlı listeleme sayfaları, branş bazlı sayfalar ve hastane sayfaları da vardı. Toplamda 100.000'den fazla URL. Bunu manuel yönetmeye çalışsaydım, proje hiç bitmezdi. ## Veri Kaynağı ve Normalizasyon Her programatik SEO projesinin temeli veri kalitesi. doktorbul.com için veri kaynağı, Türkiye Tabipler Birliği'nin açık veritabanı ve bazı özel API'lerdi. Ham veri şöyle geliyordu: doktor adı, TC kimlik numarası (maskelenmiş), branş, çalıştığı kurum, şehir, ilçe. Ama sorun şuydu: aynı doktor birden fazla hastanede çalışıyorsa, veri setinde tekrar ediyordu. Bazı branş isimleri tutarsızdı (örneğin "Göz Hastalıkları" vs "Göz Hast."). Şehir ve ilçe isimleri bazen büyük, bazen küçük harfle yazılmıştı. İlk adım, veri temizliği (data cleaning) oldu. Python ile bir script yazdım: - Doktor isimlerini title case'e çevirdim (İsmail Yılmaz, ISMAIL YILMAZ değil)
- Branş isimlerini standart bir sözlükle eşleştirdim (örneğin "Göz Hast." → "Göz Hastalıkları")
- Şehir ve ilçe isimlerini Türkiye İstatistik Kurumu'nun resmi listesiyle normalize ettim
- Aynı doktorun birden fazla kaydını birleştirdim, çalıştığı kurumları bir array içinde topladım Bu işlem sonunda 79.000 benzersiz doktor profili kaldı. Her doktorun bir unique ID'si vardı (TC kimlik numarasının hash'i). Veriyi PostgreSQL veritabanına aktardım, çünkü büyük veri setlerinde MySQL'den daha hızlı sorgu yapabiliyordum. ### Veri Modeli ve İlişkiler Veritabanı şeması şöyleydi: -
doctorstablosu: id, name, slug, specialty_id, bio (otomatik üretilen), phone, email specialtiestablosu: id, name, slug, descriptioncitiestablosu: id, name, slughospitalstablosu: id, name, slug, city_iddoctor_hospitalpivot tablosu: doctor_id, hospital_id (many-to-many ilişki) Slug alanları önemliydi, çünkü URL yapısını belirliyordu. Örneğin Dr. Ahmet Yılmaz'ın slug'ıdr-ahmet-yilmaz-kardiyoloji-ankaraolacaktı. Slug üretirken dikkat ettiğim noktalar: - Türkçe karakterleri ASCII'ye çevirmek (ş → s, ğ → g)- Boşlukları tire ile değiştirmek
- Branş ve şehir bilgisini slug'a eklemek (SEO için)
- Aynı isimli doktorlar varsa sonuna numara eklemek ## Şablon Tasarımı ve Dinamik İçerik Programatik SEO'da en kritik nokta: her sayfa benzersiz olmalı, ama aynı şablonu kullanmalı. doktorbul.com için WordPress kullandım, çünkü müşteri site yönetimini devralacaktı ve WordPress'e aşinaydı. Ama standart WordPress editörü 79.000 sayfa için uygun değil. Custom post type oluşturdum:
doctor_profile. Şablon dosyasısingle-doctor_profile.phpşöyle çalışıyordu: 1. URL'den doktor slug'ını al
2. Veritabanından doktor bilgilerini çek 3. Dinamik meta title ve description oluştur 4. Schema.org Person yapılandırılmış verisini ekle 5. İlgili doktorlar bölümünü doldur (aynı branş, aynı şehir) 6. Breadcrumb navigation oluştur Meta title formatı: Dr. [Ad Soyad] - [Branş] | [Şehir] | doktorbul.com Meta description formatı: Dr. [Ad Soyad], [Şehir] ilinde [Branş] alanında hizmet vermektedir. İletişim bilgileri, çalıştığı hastaneler ve randevu alma seçenekleri. Ama burada bir sorun vardı: Google, aynı şablondan üretilen binlerce sayfayı "thin content" olarak görebilirdi. Çözüm: her doktor için 150-200 kelimelik benzersiz bir biyografi üretmek. Bunu manuel yazmak imkansızdı, o yüzden Claude Haiku API'sini kullandım. ### Biyografi Otomasyonu Her doktor için prompt şöyleydi: "Dr. [Ad Soyad], [Şehir] ilinde [Branş] alanında çalışan bir uzmandır. [Hastane adları] gibi kurumlarda hizmet vermektedir. 150 kelimelik profesyonel bir biyografi yaz. Genel bilgiler ver, spekülasyon yapma." Claude Haiku API'si saniyede 5 istek kabul ediyordu, yani 79.000 biyografi için yaklaşık 4.5 saat sürdü. Maliyet: 79.000 × $0.00025 = $19.75. Üretilen biyografileri veritabanına kaydettim, böylece her sayfa yüklendiğinde API'ye yeni istek atmadım. Biyografiler gerçekten benzersiz miydi? Google Search Console'da 3 ay sonra kontrol ettim: duplicate content uyarısı almadım. Ortalama sayfa kalitesi skoru 7.2/10'du (Google PageSpeed Insights). ## Toplu Yayınlama ve WordPress REST API WordPress admin panelinden 79.000 sayfa eklemek imkansız. Veritabanına doğrudan INSERT yapmak da riskli, çünkü WordPress'in kendi meta tabloları ve ilişkileri var. Çözüm: WordPress REST API. Python script'i şöyle çalıştı: 1. PostgreSQL'den 1000 doktor bilgisi çek (batch processing) 2. Her doktor için bir POST isteği gönder: /wp-json/wp/v2/doctor_profile 3. İstek body'sinde: title, content (biyografi), slug, meta fields (telefon, e-mail, branş ID, şehir ID) 4. Yanıtı logla, hata varsa retry mekanizması 5. 1000 doktor bittikten sonra bir sonraki batch'e geç REST API kimlik doğrulaması için JWT (JSON Web Token) kullandım. WordPress'e jwt-authentication-for-wp-rest-api eklentisini kurdum, her istekte Authorization: Bearer [token] header'ı gönderdim. Bir batch 1000 doktor için ortalama 12 dakika sürdü. Toplam 79 batch × 12 dakika = 948 dakika = yaklaşık 16 saat. Script'i gece çalıştırdım, sabah kontrol ettim. Hata oranı %0.8'di (623 doktor başarısız), bunları manuel olarak düzelttim. ### Toplu Yayınlama Sırasında Karşılaşılan Sorunlar İlk 10.000 doktor sorunsuz yayınlandı. Ama sonra WordPress veritabanı yavaşlamaya başladı. Sorgu süreleri 200ms'den 1.5 saniyeye çıktı. Sebep: wp_postmeta tablosunda index eksikliği. Her doktor profili için 8-10 adet meta field ekliyordum (telefon, e-mail, branş ID vs), ama WordPress bu tabloya otomatik index eklemiyordu. Çözüm: wp_postmeta tablosuna manuel index ekledim: ```sql CREATE INDEX idx_postmeta_post_id ON wp_postmeta(post_id); CREATE INDEX idx_postmeta_meta_key ON wp_postmeta(meta_key);
{ "@context": "https://schema.org", "@type": "Person", "name": "Dr. Ahmet Yılmaz", "jobTitle": "Kardiyoloji Uzmanı", "worksFor": { "@type": "Organization", "name": "Ankara Şehir Hastanesi" }, "address": { "@type": "PostalAddress", "addressLocality": "Ankara", "addressCountry": "TR" }, "url": "https://doktorbul.com/dr-ahmet-yilmaz-kardiyoloji-ankara"
}
2. İlgili doktorlar: Aynı branş ve şehirde çalışan 5 doktor 3. Branş sayfası linki: "[Şehir] ilindeki tüm [Branş] uzmanlarını görüntüle" Bu linkler sayesinde, site mimarisi Google için net oldu. Orphan page (yetim sayfa) oranı %2'nin altındaydı. ## Performans ve İndeksleme 79.000 sayfa bir anda Google'a sunulursa, sunucu çökebilir. O yüzden XML sitemap'i parçalara böldüm. Her sitemap dosyasında maksimum 10.000 URL vardı. Toplam 8 adet sitemap dosyası, bir adet sitemap index dosyası. Google Search Console'a sitemap index'i gönderdim. İlk hafta sadece 12.000 sayfa indekslendi. İkinci hafta 34.000, üçüncü hafta 58.000. 6 hafta sonra 79.000 sayfanın tamamı indekslendi. İndeksleme hızını artırmak için: - Sunucu response time'ı 150ms altına düşürdüm (Cloudflare CDN)
- Robots.txt'yi optimize ettim, gereksiz URL'leri engelledim
- Her gün 100 yeni sayfa yayınladım (toplu değil, kademeli) Sonuç: 6 ay sonra doktorbul.com, "doktor ara" anahtar kelimesinde ilk 10'a girdi. Aylık organik trafik 180.000 ziyarete ulaştı. En çok trafik alan sayfalar: İstanbul'daki kardiyologlar, Ankara'daki çocuk doktorları, İzmir'deki göz doktorları. ## Güncelleme ve Bakım Programatik SEO bitince bitmez, sürekli güncelleme gerektirir. doktorbul.com için aylık bakım süreci: 1. Yeni doktorları veritabanına ekle (Tabipler Birliği API'sinden çek)
2. Emekli olan veya vefat eden doktorları kaldır 3. Hastane değişikliklerini güncelle 4. Bozuk linkleri tespit et ve düzelt (Screaming Frog ile) 5. Sayfa hızını kontrol et, yavaş sayfaları optimize et Bu işlemler için bir cron job kurdum. Her hafta Pazar gecesi çalışıyor, değişiklikleri otomatik yapıyor. Sadece kritik hatalar bana e-mail olarak bildiriliyor. Ayrıca Google Analytics ve Search Console verilerini takip ediyorum. Hangi doktor profilleri en çok trafik alıyor? Hangi anahtar kelimeler en çok dönüşüm sağlıyor? Bu verilere göre, bazı profillerin içeriğini genişletiyorum, bazılarına video veya resim ekliyorum. ## Sonuç ve İletişim 79.000 doktor profilini programatik SEO ile yayınlamak, teknik olarak zorlayıcı ama sonuçları çok değerli bir projeydi. En önemli dersler: veri kalitesi her şeyden önemli, toplu işlemlerde batch processing şart, WordPress REST API büyük projeler için güçlü bir araç. doktorbul.com bugün Türkiye'nin en büyük doktor arama platformlarından biri. Benzer bir proje için destek arıyorsan, benimle iletişime geçebilirsin. FUTIA olarak, veri tabanı tasarımından otomatik içerik üretimine, toplu yayınlamadan SEO optimizasyonuna kadar tüm süreci yönetiyorum. ulaşabilirsin:. Ya da e-mail: info@futia.net.
Sıkça Sorulanlar
Programatik SEO ile 79.000 sayfa yayınlamak ne kadar sürer?
doktorbul.com projesinde, veri temizliği ve normalizasyon 1 hafta, şablon tasarımı ve test 3 gün, biyografi otomasyonu (Claude Haiku API) 4.5 saat, toplu yayınlama (WordPress REST API) 16 saat sürdü. Toplam proje süresi: 2 hafta. Ama indeksleme 6 hafta sürdü, çünkü Google 79.000 sayfayı kademeli olarak tarıyor.
Her sayfa için benzersiz içerik üretmek gerekli mi?
Evet, aksi halde Google sayfaları 'thin content' olarak işaretler ve sıralamalarda düşürür. doktorbul.com'da her doktor için 150-200 kelimelik benzersiz biyografi ürettim. Claude Haiku API kullandım, maliyet sadece $19.75 oldu. Alternatif olarak GPT-4 veya manuel yazım da kullanılabilir, ama 79.000 sayfa için API en pratik çözüm.
WordPress 79.000 sayfa için yeterli mi, performans sorunu olur mu?
Varsayılan WordPress kurulumu yeterli değil. doktorbul.com'da şu optimizasyonları yaptım: wp_postmeta tablosuna manuel index ekledim, Redis object cache kurdum, Cloudflare CDN kullandım, gereksiz eklentileri kaldırdım. Bu işlemlerden sonra sayfa yüklenme süresi 150ms'nin altına düştü. Doğru yapılandırmayla WordPress 100.000+ sayfa için bile yeterli.
Programatik SEO'da internal linking nasıl yapılmalı?
Her sayfada en az 3 tür link olmalı: breadcrumb (hiyerarşi), ilgili içerikler (aynı kategori), kategori sayfası linki. doktorbul.com'da her doktor profilinde, aynı branş ve şehirde çalışan 5 doktor linkledim. Ayrıca breadcrumb ile Ana Sayfa > Şehir > Branş > Doktor hiyerarşisi oluşturdum. Bu sayede orphan page oranı %2 altında kaldı.
Schema.org yapılandırılmış verisi gerçekten etkili mi?
Evet, doktorbul.com'da Schema.org Person kullandıktan sonra, Google zengin sonuçlarda (rich results) doktor bilgilerini göstermeye başladı. Örneğin 'kardiyolog ankara' aramasında, doktorun adı, çalıştığı hastane ve iletişim butonu doğrudan arama sonuçlarında görünüyor. Bu, tıklama oranını (CTR) %18 artırdı. JSON-LD formatında, head içinde eklemek yeterli.
Bu yazıdaki tekniklerden birini uygulamak ister misiniz? Kısa bir form doldurun, 48 saat içinde ücretsiz ön inceleme raporu mailinize düşsün.