Bir SEO Değişikliğinin Etkisini Ölçmek: Önce/Sonra Analizi, Mevsimsellik, Annotation ve Dürüst Raporlama
Bir SEO değişikliğinin etkisini, değişiklik yapılmayan benzer sayfalardan oluşan bir kontrol grubuyla, tam haftalık pencerelerle ve normal haftalık dalgalanmanın aralığına göre ölçersin; kontrol grubu olmadan mevsim ve tatiller etkiyle karışır. Hipotez yazmayı, annotation'ı, dış etkenleri, sentetik veriyle C# analizini, küçük sitede split testin sınırlarını ve dürüst bir etki raporunu anlatıyoruz.
Sürüm notu: Bu yazıdaki kodlar .NET 10 ile derlenip denenmiştir; örneklerdeki bütün veri sentetiktir. Bu yazıda resmî belgelerden yararlanılmıştır: Google'ın trafik düşüşü rehberi, website testing rehberi, Search Console annotation ve data anomalies sayfaları, 15 Kasım 2026'daki hâliyle.
Önce Tahmin Et
Sitedeki serilerin ortak örnek uygulaması Bookstore'un (bir online kitapçı) blog'unda iki değişiklik yapıldı. 2 Eylül'de iki yazıya dateModified içeren Article structured data eklendi; dört hafta sonra bu iki yazının click'leri yüzde 43 artmış. 14 Ekim'de üç yazının başlığı yenilendi; dört hafta sonra bu üç yazının click'leri yüzde 12 artmış. Ekip ikisini de başarı olarak raporlamak istiyor. Sence hangisi gerçekten işe yaradı? İkisi de mi, hiçbiri mi? Bu kararı vermek için başka hangi sayıya bakardın?
Önce Hipotez, Sonra Değişiklik
Etki ölçümü değişiklikten önce başlıyor. Bir değişiklik yapmadan önce dört şeyi yaz: hangi sayfalar değişiyor, hangi metric'in değişmesini bekliyorsun, hangi yönde ve kabaca ne kadar, ne kadar bekleyeceksin. Başlık yenilemesi için hipotez şöyle olabilir: "Bu üç yazıda impression aynı kalırken CTR (click-through rate; tıklamanın impression'a oranı) artacak; dört hafta sonra değişiklik yapılmayan sayfalarla karşılaştıracağız." Hipotez sonradan yazılırsa, veride ne çıkarsa onu açıklayan bir hikâye kurmak çok kolay.
Sonra değişikliği işaretle. Search Console'un Performance grafiğine 17 Kasım 2025'ten beri annotation ekleyebiliyorsun: en fazla 120 karakter, property başına 200 not, 500 günden eskiler siliniyor; owner ve full user'lar ekleyip siliyor, restricted user'lar yalnız görüyor. Not bütün kullanıcılarla paylaşıldığı için kişisel bilgi yazma. Annotation'ı tek kayıt olarak bırakma: repository'de bir değişiklik dosyası tut ve deploy log'unla eşleştir. Bookstore'da bu dosya basit bir CSV (virgülle ayrılmış metin dosyası):
date,description,pages
2026-09-02,Article structured data with dateModified on two posts,/blog/cs8618-nullable-uyarisi|/blog/linq-groupby
2026-10-14,title rewrite on three posts,/blog/ef-core-migration-rehberi|/blog/dependency-injection-nedir|/blog/async-await-nasil-calisir
Son olarak bekle. Google'ın trafik düşüşü rehberi bazı değişikliklerin günler içinde, bazılarının aylar içinde etkisini gösterdiğini ve tekrar değerlendirmeden önce birkaç hafta beklemeyi öneriyor; iyi bir değişikliğin bile iyileşme garantisi olmadığını da ekliyor. Core Web Vitals değişikliklerinde CrUX'in 28 günlük penceresi zaten bir bekleme süresi demek.
Mevsimsellik ve Dış Etkenler
Önce/sonra karşılaştırmasını en çok bozan şey, değişiklikle aynı dönemde senin elinde olmayan şeylerin de değişmesi. Teknik bir blog için tipik olanlar:
- Haftanın günü: hafta sonu trafik düşüyor. Pencereleri tam hafta seç, Help sayfasının önerdiği gibi pazartesiyi cumartesiyle karşılaştırma.
- Tatiller ve dönemler: resmî tatiller, bayramlar, yaz tatili ve okulların açılması. Eylül'de trafiğin artması çoğu zaman yaptığın bir şeyden değil, takvimden.
- Core update'ler ve diğer ranking değişiklikleri: Google'ın ranking update geçmişine bak; SEO (arama motoru optimizasyonu) Temelleri serisinin "Google Nasıl Sıralar?" yazısında anlattık.
- Veri düzeltmeleri: Search Console'un Data anomalies sayfası. Örneğin 13 Mayıs 2025 ile 27 Nisan 2026 arasındaki impression logging hatası impression, CTR ve position'ı etkiledi.
- Ölçüm değişiklikleri: consent banner'ı, tag ya da log formatı değişince grafik trafik değişmeden kırılıyor; serinin beşinci yazısında gördük.
- İlginin kendisi: Google'ın rehberi, düşüşün sana mı özel yoksa genel bir eğilim mi olduğunu anlamak için Google Trends'e bakmayı öneriyor.
Kontrol Grubu ile Önce/Sonra
Bu etkenlerin çoğunu ortadan kaldırmanın basit bir yolu var: değişiklik yapılmayan benzer sayfaları kontrol grubu olarak aynı dönemde izlemek. Mevsim, tatil ya da bir update iki grubu birlikte etkiliyorsa, test grubunun kontrol grubuna oranı değişmez. Aşağıdaki analiz bunu yapıyor: değişiklik gününü dışarıda bırakıyor, önce ve sonra için dörder tam hafta alıyor, test grubunun değişimini kontrol grubunun değişimine bölüyor:
// Değişiklik günü dışarıda kalır. Pencereler tam haftadır; her haftanın günü eşit sayılır.
public static ImpactResult Analyze(
IReadOnlyList<DailyPage> days, IReadOnlySet<string> testPages, DateOnly changeDay,
int windowWeeks = 4, int baselineWeeks = 12)
{
DateOnly afterFrom = changeDay.AddDays(1);
DateOnly afterTo = afterFrom.AddDays(windowWeeks * 7 - 1);
DateOnly beforeTo = changeDay.AddDays(-1);
DateOnly beforeFrom = beforeTo.AddDays(-(windowWeeks * 7) + 1);
GroupWindow Sum(bool test, DateOnly from, DateOnly to)
{
List<DailyPage> rows = days
.Where(d => d.Date >= from && d.Date <= to && testPages.Contains(d.Page) == test)
.ToList();
return new GroupWindow(rows.Sum(d => d.Clicks), rows.Sum(d => d.Impressions));
}
double WeekRatio(DateOnly weekStart)
{
GroupWindow test = Sum(true, weekStart, weekStart.AddDays(6));
GroupWindow control = Sum(false, weekStart, weekStart.AddDays(6));
return (double)test.Clicks / control.Clicks;
}
GroupWindow testBefore = Sum(true, beforeFrom, beforeTo);
GroupWindow testAfter = Sum(true, afterFrom, afterTo);
GroupWindow controlBefore = Sum(false, beforeFrom, beforeTo);
GroupWindow controlAfter = Sum(false, afterFrom, afterTo);
// Test click'leri kontrol click'lerine göre: ortak etkiler (mevsim, tatil, update) birbirini götürür.
double effect = (double)testAfter.Clicks / testBefore.Clicks
/ ((double)controlAfter.Clicks / controlBefore.Clicks) - 1;
List<double> baseline = Enumerable.Range(1, baselineWeeks)
.Select(w => WeekRatio(changeDay.AddDays(-7 * w)))
.ToList();
List<double> after = Enumerable.Range(0, windowWeeks)
.Select(w => WeekRatio(afterFrom.AddDays(7 * w)))
.ToList();
return new ImpactResult(testBefore, testAfter, controlBefore, controlAfter, effect, baseline, after);
}
}
Tek bir oran yetmiyor, çünkü küçük bir sitede haftadan haftaya oran zaten oynuyor. Bu yüzden kod, değişiklikten önceki 12 haftanın her biri için test/kontrol oranını hesaplıyor ve sonraki dört haftanın oranlarını bu aralıkla karşılaştırıyor. Hepsi aralığın dışındaysa etkinin normal dalgalanmadan ayrıldığını söylüyor, değilse söylemiyor.
Girdi data/daily-pages.csv: on sayfanın Haziran-Kasım 2026 arası günlük click ve impression'ı. Veri seti tools/synthetic/daily_pages.py ile üretildi ve gerçek bir sitenin verisi değil; ama içine bilinen bir gerçek koyduk: başlığı yenilenen üç yazıda 14 Ekim'den sonra CTR bir hafta içinde yüzde 15 artıyor. Geri kalan her şey mevsim, haftanın günü, 29 Ekim tatili ve rastgele dalgalanma. Önce structured data değişikliği:
$ dotnet run --project src/Bookstore.Analytics.Cli -- impact data/daily-pages.csv data/changes.csv 2026-09-02
change 2026-09-02: Article structured data with dateModified on two posts (2 pages)
windows: 28 days before vs 28 days after, change day excluded
clicks before after change ctr before after
test 501 716 +42.9% 7.09% 7.15%
control 1130 1618 +43.2% 4.30% 4.42%
test vs control, clicks: -0.2% ctr: -2.0%
weekly test/control ratio, 12 weeks before: 0.412 .. 0.518
weekly test/control ratio, 4 weeks after: 0.438 0.450 0.450 0.431
the weeks after the change stay within normal variation: no evidence of an effect
Test grubu yüzde 43 artmış, ama kontrol grubu da yüzde 43 artmış: veri setine koyduğumuz mevsim etkisi (yazın düşük, Eylül'de yüksek) iki grubu birlikte büyütmüş; gerçek bir sitede bu, yaz tatilinin bitmesine karşılık gelir. Test/kontrol oranı değişmemiş, sonraki dört hafta da önceki 12 haftanın aralığında. Veri setine burada bir etki koymamıştık; analiz de bulmuyor. Bu değişikliği başarı olarak raporlamak, takvimi başarı olarak raporlamak olurdu. Structured data'nın neyi etkileyip neyi etkilemediğini Structured Data ve Schema.org serisinde ayrıntılı anlattık.
Sonra başlık değişikliği:
$ dotnet run --project src/Bookstore.Analytics.Cli -- impact data/daily-pages.csv data/changes.csv 2026-10-14
change 2026-10-14: title rewrite on three posts (3 pages)
windows: 28 days before vs 28 days after, change day excluded
clicks before after change ctr before after
test 994 1110 +11.7% 4.25% 4.77%
control 1372 1415 +3.1% 5.68% 5.78%
test vs control, clicks: +8.3% ctr: +10.3%
weekly test/control ratio, 12 weeks before: 0.665 .. 0.781
weekly test/control ratio, 4 weeks after: 0.744 0.788 0.726 0.883
the weeks after the change stay within normal variation: no evidence of an effect
Burada sonuç daha ince. Kontrol grubuna göre test grubu click'te yüzde 8,3, CTR'da yüzde 10,3 önde; dört haftadan biri önceki aralığın dışında, üçü içinde. Analizin vardığı sonuç "kanıt yetersiz". Oysa veride gerçek bir yüzde 15'lik CTR artışı var. Bu, yöntemin hatası değil, küçük bir sitenin gerçeği: üç yazının haftada birkaç yüz click'i, yüzde 10-15'lik bir etkiyi rastgele dalgalanmadan dört haftada ayırmaya yetmiyor. Dürüst seçenekler şunlar: pencereyi uzatmak, değişikliği daha fazla sayfaya uygulamak ya da "olumlu yönde bir işaret var ama doğrulanmadı" diye raporlamak.
Testler kodun iki temel davranışını sabitliyor: iki gruba birlikte gelen yüzde 50'lik mevsimsel artış etki olarak görünmüyor, gerçek bir iki kat artış ise normal dalgalanmanın dışında çıkıyor:
$ dotnet test --filter "FullyQualifiedName~ChangeImpactAnalyzerTests"
Passed! - Failed: 0, Passed: 3, Skipped: 0, Total: 3, Duration: 8 ms - Bookstore.Analytics.Tests.dll (net10.0)
SEO Split Test ve Küçük Sitenin Sınırları
Kontrol grubu fikrinin daha düzenli hâli SEO split testi: benzer sayfaları rastgele iki gruba ayırıp yalnız birinde değişiklik yapmak. Burada Googlebot ve kullanıcı aynı sayfayı görüyor, yani cloaking söz konusu değil. Kullanıcı bazlı A/B testinde ise Google'ın website testing rehberi geçerli: Googlebot'a farklı içerik gösterme, varyant URL'lerinde orijinale rel="canonical" ver, varyanta yönlendiriyorsan 301 değil 302 kullan ve testi gerektiğinden uzun tutma; Googlebot çoğunlukla çerez kabul etmediği için çerez tabanlı testlerde çerezsiz tarayıcının gördüğü varyantı görür.
Split test büyük sitelerde iyi çalışıyor, çünkü yüzlerce benzer sayfa ve günde binlerce click var. Bookstore blog'u gibi birkaç düzine yazılık bir sitede gruplar küçük kalıyor ve az önce gördüğümüz sorun büyüyor. Küçük bir sitede gerçekçi hedef, büyük etkileri yakalamak ve küçük etkiler için "bilmiyoruz" demeyi kabul etmek.
Haftalık Raporu Arşivden Üretmek
Analizin girdisi, serinin üçüncü yazısında Search Console API'den doldurduğumuz SQL Server arşivinden aynı biçimde çıkıyor:
SELECT DataDate AS [date], Page AS page, SUM(Clicks) AS clicks, SUM(Impressions) AS impressions
FROM dbo.SearchAnalyticsDaily
WHERE SearchType = 'web'
GROUP BY DataDate, Page
ORDER BY DataDate, Page;
Haftalık job önce yeni günleri arşive yazıyor, sonra bu sorgunun çıktısını CSV olarak kaydedip changes.csv'deki her değişiklik için, değişiklikten 28 gün geçmişse, impact komutunu çalıştırıyor. Sorgu ayrıntı tablosundan geldiği için anonim sorguları içermiyor; test ve kontrol grubu aynı şekilde etkilendiği için oran karşılaştırması bundan büyük ölçüde etkilenmiyor, ama mutlak sayıları raporlarken bunu not etmek gerekiyor.
Dürüst Raporlama
Raporun okuru kimse, ona göre metric seç. Yönetim için Search Console'un non-branded click trendi ve birkaç cümlelik bir sonuç; ekip için sayfa ve sorgu düzeyinde ayrıntı. Her etki raporunda olması gerekenler:
- Hipotez ve değişiklik tarihi, değişiklik dosyasındaki kaydıyla.
- Pencereler: kaç gün, hangi günler, değişiklik günü dışarıda mı.
- Test ve kontrol grubu, ikisinin ham sayıları ve oran.
- Normal dalgalanmanın aralığı ve sonucun bu aralığa göre yeri.
- Aynı dönemdeki dış etkenler: update, tatil, data anomaly, ölçüm değişikliği.
- Sonucun dili: "işe yaradı", "işaret var ama doğrulanmadı" ya da "etki görülmedi".
Kanıt düzeyi özellikle iddialarda önemli. "AI Overviews yüzünden CTR'ımız düştü" cümlesini ele al: Search Console AI Overviews ve AI Mode verisini "Web" arama tipinin içinde gösteriyor ve bu tıklamaları ayırmanın bir yolu yok; generative AI raporu da yalnız impression veriyor. Üstelik 2025-2026 arasındaki impression düzeltmesi CTR'ı ayrıca değiştirdi. Bu durumda elindeki en fazla bir zaman çakışması, nedensellik değil. Raporda "CTR, AI Overviews'un yaygınlaştığı dönemde düştü; Search Console verisi bu ikisini ayırmamıza izin vermiyor" demek dürüst olanı. Ölçümün AI tarafı GEO (AI tabanlı arama motorları için içerik optimizasyonu) serisinin "GEO'yu Ölçmek" yazısında.
Üretimde Dikkat
Değişiklikleri sırayla yap. Aynı sayfalarda iki değişiklik arasında en az bir ölçüm penceresi bırak; değişiklik dosyası bu sırayı görünür kılar.
Kontrol grubunu önceden seç. Sonuçları gördükten sonra "bu sayfalar kontrol olsun" demek, istediğin sonucu seçmek demek.
Ham veriyi sakla. Raporun dayandığı CSV'yi ve kullandığın komutu rapora ekle; aylar sonra biri sorduğunda aynı sayıyı tekrar üretebilmelisin.
Sonucu güncelle. Dört haftada "kanıt yetersiz" çıkan bir değişikliğe sekizinci haftada tekrar bak; yeni bir değişiklik araya girmediyse pencere uzadıkça belirsizlik azalır.
Sık Düşülen Tuzaklar
Tek günlük sıçramayı başarı saymak. Bir günün click'i haber, sosyal medya paylaşımı ya da bir bot yüzünden zıplayabilir; tam haftalarla çalış.
Aynı anda beş değişiklik yapmak. Başlık, structured data, iç link ve görseller aynı hafta değişirse hangisinin işe yaradığını hiçbir analiz ayıramaz.
Kontrol grubu olmadan önce/sonra karşılaştırması. Eylül örneğinde gördüğün gibi takvim, en güçlü "değişiklik".
"Etki yok"u "kanıt yok"la karıştırmak. Küçük bir sitede ölçülemeyen etki, var olmayan etki demek değil; raporda ikisini ayrı yaz.
Küçük Bir Deneme
★☆☆ tools/synthetic/daily_pages.py'deki etkiyi yüzde 15'ten yüzde 40'a çıkar, CSV'yi yeniden üret ve impact komutunu çalıştır. Sonuç değişiyor mu?
★★☆ ChangeImpactAnalyzer'a pencere uzunluğunu parametre olarak al ve başlık değişikliğini 2, 4 ve 6 haftalık pencerelerle karşılaştır. Hangi pencerede ilk kez normal dalgalanmanın dışına çıkıyor?
★★★ Haftalık oran yerine bir permutation test ekle: değişiklik tarihini önceki haftalara rastgele kaydırıp aynı etki büyüklüğünün ne sıklıkla çıktığını say. Sentetik veriyle test et ve sonucu "kaç denemenin kaçında" diye raporla.
Analytics ve Ölçüm serisi burada bitiyor. Hangi sorunun hangi veriyle cevaplandığını, Search Console'un sayılarını doğru okumayı ve otomatikleştirmeyi, GA4'ü (Google Analytics 4; Google'ın web analitik ürünü) bir SPA'da (Single Page Application; tek sayfalık uygulama) doğru kurmayı, consent'in sayılara etkisini, Core Web Vitals'ın field data'sını ve bir değişikliğin etkisini dürüstçe ölçmeyi gördük. Ortak sonuç basit: önce soruyu yaz, her sayının nereden geldiğini bil ve emin olmadığın yerde bunu rapora yaz.