Oğuzhan KARAGÜZEL

OĞUZHAN KARAGÜZEL

Yazılım geliştirici

Teknik SEO: robots.txt, Sitemap ve Canonical Rehberi

Yazar: Oğuzhan KARAGÜZEL ·

Bu yazı SEO serisinin ikinci bölümüdür. İlk bölümde sayfa içi SEO temellerini (title, meta description, başlıklar ve slug) ele almıştık. Şimdi sayfanın dışında kalan, arama motoru botlarıyla doğrudan konuşan teknik katmana geçiyoruz: robots.txt, sitemap.xml, canonical, hreflang ve güvenlik ayarları.

Aşağıdaki örnekler ASP.NET Core ağırlıklıdır, ancak mantık hangi altyapıyı kullanırsanız kullanın aynıdır. Bir sonraki bölümde Open Graph, yapılandırılmış veri ve ARIA konularına bakacağız.

Teknik SEO Nedir?

Teknik SEO, içeriğin kendisinden bağımsız olarak, sitenin arama motorları tarafından bulunabilir, taranabilir ve dizine eklenebilir olmasını sağlayan altyapı çalışmalarının tümüdür. İçerik ne kadar iyi olursa olsun, bot sayfaya ulaşamıyorsa ya da hangi URL'nin esas olduğunu anlayamıyorsa sıralama alamaz.

Bu katman büyük ölçüde geliştiricinin sorumluluğundadır. Bu yazıda şu başlıkları ele alıyoruz:

  • robots.txt: botlara hangi alanları tarayabileceklerini söyler.
  • sitemap.xml: sitedeki sayfaların haritasını sunar.
  • Canonical, alternate ve hreflang: yinelenen içerik ve çok dilli yapıyı yönetir.
  • Güvenlik: HTTPS yönlendirmesi ve form koruması.

robots.txt Nedir ve Ne İçin Kullanılır?

robots.txt, sitenin kök dizininde duran ve arama motoru botlarına (crawler) hangi bölümleri tarayıp tarayamayacaklarını bildiren düz metin bir dosyadır. Bir bot siteye geldiğinde ilk olarak alanadi.com/robots.txt adresine istek atar. Herhangi bir sitenin robots.txt dosyasını tarayıcıdan açıp inceleyebilirsiniz.

  • Tarama bütçesini yönetmek: Arama motorlarının gereksiz yere taramasını istemediğiniz alanları (yönetim paneli, arama sonuçları, filtre kombinasyonları) dışarıda bırakırsınız.
  • Sunucu yükünü azaltmak: Botların sunucuyu gereksiz yormasını engellersiniz.
  • Sitemap'i duyurmak: Sitemap dosyasının adresini botlara bildirirsiniz.

Önemli not: robots.txt bir güvenlik mekanizması değildir. Dosyayı herkes okuyabilir ve kurallara uymak botun inisiyatifindedir. Üstelik Disallow ile engellenen bir sayfa, başka sitelerden link alıyorsa yine de arama sonuçlarında görünebilir. Gerçekten gizli olması gereken içerik için kimlik doğrulama kullanın; sonuçlardan çıkarmak istediğiniz sayfalar için noindex meta etiketi ekleyin (bot bu etiketi görebilsin diye o sayfaları robots.txt ile engellemeyin).

robots.txt Nasıl Yazılır?

Dosya dört temel komuttan oluşur:

  1. User-agent: Kuralın hangi bota ait olduğunu belirtir. * tüm botlar anlamına gelir.
  2. Disallow: Belirtilen yolun taranmasını engeller.
  3. Allow: Engellenmiş bir dizinin içindeki belirli bir yola izin verir.
  4. Sitemap: Sitemap dosyasının tam adresini bildirir.

Tipik bir örnek:

robots.txt
User-agent: *
Disallow: /admin/
Disallow: /login/
Allow: /public/

Sitemap: https://www.orneksite.com/sitemap.xml

Bu dosya tüm botlara /admin/ ve /login/ dizinlerini taramamalarını söyler, /public/ dizinine izin verir ve sitemap adresini duyurur. Sitemap adresi her zaman tam (https dahil) yazılmalıdır.

ASP.NET'te robots.txt Yönetimi

ASP.NET Core'da wwwroot klasörüne bir robots.txt koymak çoğu proje için yeterlidir. Ancak iki noktaya dikkat etmek gerekir:

  • Ortama göre farklı içerik: Test ve geliştirme ortamları arama motorlarında görünmemelidir; bu ortamlarda Disallow: / döndürün. Canlı ortamda ise yönetim alanı gibi taranmaması gereken yolları kısıtlayıp geri kalanına izin verin.
  • Ne döndürdüğünüzü bilmek: /robots.txt isteğine 404 dönmesi sorun değildir; Google bunu "her şeye izin var" olarak yorumlar. Asıl tehlike 5xx hatalarıdır: robots.txt sunucu hatası verirse Google bir süre siteyi taramayı durdurabilir. Bu yüzden isteğe her ortamda bilinçli bir içerikle yanıt vermek en sağlıklısıdır.

Bu iki ihtiyacı birlikte karşılamanın pratik yolu, isteği bir middleware ile yönetmek ve ortama göre Robots.Development.txt, Robots.Production.txt gibi dosyaları okumaktır:

C#
app.Use(async (context, next) =>
{
    if (!context.Request.Path.Equals("/robots.txt", StringComparison.OrdinalIgnoreCase))
    {
        await next();
        return;
    }

    var robotsPath = Path.Combine(
        app.Environment.ContentRootPath,
        $"Robots.{app.Environment.EnvironmentName}.txt");

    // Dosya yoksa güvenli bir varsayılan döndür
    var output = "User-agent: *\nAllow: /";

    if (File.Exists(robotsPath))
    {
        output = await File.ReadAllTextAsync(robotsPath);
    }

    context.Response.ContentType = "text/plain; charset=utf-8";
    await context.Response.WriteAsync(output);
});

sitemap.xml Nedir ve Nasıl Yazılır?

sitemap.xml, sitedeki sayfaların listesini içeren bir XML dosyasıdır. Arama motorlarının tüm içeriği bulmasını, yeni ve güncellenen sayfaları hızlı fark etmesini kolaylaştırır. Özellikle büyük, derin yapılı ve çok dilli sitelerde önemlidir.

Temel yapı şöyledir:

XML
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://www.example.com/</loc>
    <lastmod>2026-10-23</lastmod>
  </url>
  <url>
    <loc>https://www.example.com/makaleler/ornek-yazi</loc>
    <lastmod>2026-10-20</lastmod>
  </url>
</urlset>
  • <url>: Her sayfa için bir kayıt.
  • <loc>: Sayfanın tam URL'si (zorunlu).
  • <lastmod>: Sayfanın son güncellenme tarihi. Doğru tutulduğunda yararlıdır.
  • <changefreq> ve <priority>: Eski rehberlerde sıkça geçer, ancak Google bu alanları dikkate almaz. Eklemek zorunlu değildir.

Çok Dilli Siteler İçin Sitemap Yapısı

Çok dilli ya da çok bölgeli sitelerde tek dosya yerine hiyerarşik bir yapı kurulabilir: ana dosya (/sitemap.xml) dillere ait sitemap dosyalarını gösterir (örneğin /tr/sitemap.xml ve /en/sitemap.xml). Tek dosya da olsa hiyerarşik yapı da olsa kural değişmez: arama motorlarının ulaşacağı ilk adres alanadi.com/sitemap.xml olmalı ve bu adres robots.txt içinde Sitemap: satırıyla duyurulmalıdır.

Başka sitemap dosyalarını gösteren ana dosya <urlset> değil, <sitemapindex> kök etiketini kullanır:

XML
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <sitemap>
    <loc>https://www.example.com/tr/sitemap.xml</loc>
    <lastmod>2026-10-23T11:30:18+03:00</lastmod>
  </sitemap>
  <sitemap>
    <loc>https://www.example.com/en/sitemap.xml</loc>
    <lastmod>2026-10-23T11:30:18+03:00</lastmod>
  </sitemap>
</sitemapindex>

Dil dosyalarını wwwroot altına tr/sitemap.xml, en/sitemap.xml gibi fiziksel klasörler olarak koymak mümkündür, ancak yeni dil eklendikçe yönetimi zorlaşır. Daha esnek bir yol, sitemap.tr.xml ve sitemap.en.xml gibi dosyaları bir middleware ile /{dil}/sitemap.xml adresinden sunmaktır:

C#
using System.Text.RegularExpressions;

app.Use(async (context, next) =>
{
    // /tr/sitemap.xml  veya  /en/sitemap.xml/
    var path = context.Request.Path.Value?.TrimEnd('/') ?? string.Empty;
    var match = Regex.Match(path, @"^/(?<culture>[a-z]{2})/sitemap\.xml$", RegexOptions.IgnoreCase);

    if (!match.Success)
    {
        await next();
        return;
    }

    var culture = match.Groups["culture"].Value.ToLowerInvariant();
    var file = Path.Combine(app.Environment.ContentRootPath, $"sitemap.{culture}.xml");

    if (!File.Exists(file))
    {
        context.Response.StatusCode = StatusCodes.Status404NotFound;
        return;
    }

    context.Response.ContentType = "application/xml; charset=utf-8";
    await context.Response.WriteAsync(await File.ReadAllTextAsync(file));
});

Sitemap hazır olduğunda Google Search Console üzerinden göndermeyi unutmayın.

Canonical URL

Canonical URL, aynı ya da çok benzer içeriğin birden fazla adreste bulunduğu durumlarda arama motorlarına hangi adresin asıl (kanonik) sürüm olduğunu söyleyen bir bağlantı etiketidir. Etiket sayfanın <head> bölümüne yazılır:

HTML
<head>
  <link rel="canonical" href="https://www.example.com/blog/yazi-basligi" />
</head>

Canonical etiketi dört önemli sorunu çözer:

  • Yinelenen içerik: Arama motoru hangi URL'yi sıralayacağını bilemez; canonical bu belirsizliği ortadan kaldırır.
  • Sıralama performansı: Güç tek bir adreste toplanır, sıralamalar bölünmez.
  • Tarama bütçesi: Botlar aynı içeriği tekrar tekrar taramak yerine önemli sayfalara zaman ayırır.
  • Backlink değeri: Aynı içeriğe gelen bağlantıların değeri (halk arasındaki adıyla link juice) tek bir URL'de toplanır.

En sık karşılaşılan kullanım durumları; renk ve beden gibi seçeneklerle çoğalan ürün sayfaları, ?utm_source=... ya da ?sirala=fiyat gibi URL parametreleri ve aynı içeriği sunan farklı URL yapılarıdır.

Canonical Kullanırken Dikkat Edilecekler

  • Her sayfa ya kendisini ya da asıl sayfayı gösteren bir canonical içermelidir (kendine işaret eden canonical de geçerlidir).
  • Canonical her zaman tam URL olmalı, protokol (https) ve www tercihi sitenin geri kalanıyla tutarlı olmalıdır.
  • Dahili bağlantılarda da canonical adresler kullanılmalıdır.

Geliştirici tarafında yapılacak iş, canonical adresini her sayfanın <head> bölümüne doğru yazmaktır. Editör bir canonical belirlediyse o adres, belirlemediyse sayfanın kendi temiz adresi (sorgu parametreleri olmadan) kullanılmalıdır.

Örnek Senaryo

Diyelim ki bir sağlık sitesinde /soguk-alginligina-ne-iyi-gelir adresinde bir makale yayında. Yönetici daha fazla arama trafiği çekmek için aynı makaleyi /soguk-alginligi ve /soguk-alginligi-nedir adreslerinde de yayınlamak istiyor. Üç sayfada da içerik birebir aynı olacağı için üçü de canonical olarak /soguk-alginligina-ne-iyi-gelir adresini göstermelidir.

Burada iki ayrıntı var. Birincisi, canonical'ın hangi sayfayı göstereceği ve işaretlenip işaretlenmeyeceği içerik yöneticisine bırakılmalıdır; çünkü yoğun anahtar kelimeyle kısa süreliğine yayınlanan bir sayfa bir süre sonra kaldırılacaksa canonical gerekmeyebilir. CMS'te bu yüzden canonical alanı düzenlenebilir olmalıdır. İkincisi, mümkünse aynı içeriği çoğaltmak yerine ek adresleri 301 ile asıl adrese yönlendirmek daha temiz bir çözümdür.

Alternate, hreflang ve x-default

Çok dilli sitelerde her sayfa, kendi dil sürümlerini rel="alternate" ve hreflang ile bildirmelidir. Böylece arama motoru Türkçe kullanıcıya Türkçe, İngilizce kullanıcıya İngilizce sürümü gösterir. Kurallar:

  • Her dil sürümü, kendisi dahil tüm sürümleri listelemelidir (karşılıklı bağlantı şarttır).
  • Adresler tam URL olmalıdır.
  • x-default, belirli bir dile ya da bölgeye uymayan kullanıcılar için varsayılan sayfayı belirtir.
HTML
<head>
  <link rel="alternate" hreflang="tr" href="https://www.example.com/tr/ornek-sayfa" />
  <link rel="alternate" hreflang="en" href="https://www.example.com/en/example-page" />
  <link rel="alternate" hreflang="x-default" href="https://www.example.com/en/example-page" />
</head>

Eskiyen etiketler: Eski rehberlerde mobil sürüm için rel="alternate" media="..." ve sayfalı içerik için rel="prev" / rel="next" etiketleri anlatılır. Responsive tasarım kullanıyorsak (ve mobil için ayrı alt alan adı açmıyorsak) mobil alternate etiketine ihtiyacımız yoktur. Google da prev/next etiketlerini artık sıralama için kullanmadığını açıkladı; sayfalı listelerde her sayfanın kendine işaret eden canonical'ı ve botların takip edebileceği normal bağlantılar yeterlidir.

Canonical ve alternate etiketlerini doğrulamak için Google Search Console, Screaming Frog ya da Ahrefs / Semrush gibi araçları kullanabilirsiniz.

Güvenlik: HTTPS Yönlendirmesi ve Captcha

Güvenlik başlığı SEO'nun da bir parçasıdır, ancak iki temel kuralı hatırlamak çoğu zaman yeterlidir:

  1. Herkese açık formları koruyun. İletişim, kayıt ve başvuru formları spam botlarının ilk hedefidir; captcha ya da benzeri bir koruma kullanın. Spam hem kullanıcı deneyimini hem de site itibarını bozar.
  2. http isteklerini https'e 301 ile yönlendirin. Kalıcı yönlendirme (301), sıralama değerinin https adrese aktarılmasını sağlar ve sitenin http ve https olarak iki ayrı kopya halinde dizine girmesini engeller.

ASP.NET Core'da yönlendirme durum kodunu 301 yapmak için:

C#
builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = StatusCodes.Status301MovedPermanently;
});

var app = builder.Build();

app.UseHttpsRedirection();

Alternatif olarak URL Rewrite ara yazılımıyla aynı sonuç elde edilebilir:

C#
var rewriteOptions = new RewriteOptions()
    .AddRedirectToHttpsPermanent();

app.UseRewriter(rewriteOptions);

Canlı ortamda ayrıca app.UseHsts() ile HSTS başlığını eklemek, tarayıcıların siteye bir daha http üzerinden bağlanmasını engeller.

Teknik SEO Kontrol Listesi

Yayına almadan önce hızlıca şu listeden geçin:

  1. /robots.txt açılıyor mu, canlı ortamda siteyi yanlışlıkla tamamen engellemiyor mu?
  2. Test ve geliştirme ortamı arama motorlarına kapalı mı?
  3. /sitemap.xml mevcut mu, robots.txt içinde duyurulmuş mu ve Search Console'a gönderildi mi?
  4. Çok dilli sitede dil bazlı sitemap dosyaları ve sitemap index doğru mu?
  5. Her sayfada doğru bir canonical etiketi var mı?
  6. Çok dilli sayfalarda karşılıklı hreflang ve x-default tanımlı mı?
  7. http istekleri https'e 301 ile yönlendiriliyor mu?
  8. Herkese açık formlar spam'e karşı korunuyor mu?

Serinin devamında Open Graph, yapılandırılmış veri (Schema.org) ve ARIA konularına geçiyoruz.