İç bağlantı denetimi

Yetim Sayfa Tespiti: Site Haritasını İç Bağlantı Taramasıyla Karşılaştıran Çalışan Denetim

Yetim sayfa, sitenizde başka hiçbir sayfadan bağlantı almayan sayfadır; bulmak için site haritasındaki ve yayınlanmış sayfa listesindeki adresleri, sitenizi tarayıp topladığınız iç bağlantı listesiyle karşılaştırır ve hiç bağlantı almayanları ayırırsınız. Aşağıdaki betik bunu yapar; yademreklam.com'un 17-18 Ekim 2026 taramaları ve ailevegitim.com sonucu verildi.

Güncellendi: 18 Ekim 20268 dk okumaHazırlayan: Yadem Reklam ekibi
Yetim Sayfa Tespiti: Site Haritasını İç Bağlantı Taramasıyla Karşılaştıran Çalışan Denetim – Yadem Reklam
Yetim sayfa nedir?

Sitenizdeki başka hiçbir sayfadan bağlantı almayan sayfadır.

Nasıl bulunur?

Site haritası ve yayınlanmış sayfa listesinden envanter çıkarılır, site taranıp iç bağlantılar toplanır ve hiç bağlantı almayan adresler ayrılır.

Gerçek taramada ne çıktı?

yademreklam.com'da ilk taramada 61 adresten 1'i, 18 Ekim 2026 taramasında 117 adresten 5'i yetimdi; ailevegitim.com'un site haritasındaki 259 adresin hiçbiri yetim çıkmadı.

Yetim sayfa nedir ve neden sorundur?

Yetim sayfa (orphan page), sitenizdeki başka hiçbir sayfadan bağlantı almayan, yalnız doğrudan adresiyle ya da site haritasıyla erişilebilen sayfadır. Google, tarayıcı bağlantıları belgesinde ilgilendiğiniz her sayfanın sitenizdeki en az bir başka sayfadan bağlantı alması gerektiğini söyler.

Yetim sayfa dizinden çıkmış anlamına gelmez: Google’ın site haritası belgesi haritanın URL’lerin keşfine yardım ettiğini ama haritadaki her adresin taranıp dizine gireceğini garanti etmediğini; yeni ve dışarıdan az bağlantı alan bir sitede, başka siteler bağlantı vermedikçe Googlebot’un sayfaları keşfedemeyebileceğini yazar. Bağlantı ayrıca çapa metniyle sayfanın konusunu anlatır ve kullanıcıyı sayfaya götürür; bu yüzden yetim sayfa üç şey kaybeder: keşif yolu, bağlam ve okur.

Yetim sayfa nasıl bulunur? Üç liste ve bir fark

Yetim sayfa, envanter listesinden iç bağlantı listesini çıkararak bulunur: sitede olması gereken tüm adreslerle, sitenin kendi sayfalarının verdiği bağlantıları karşılaştırırsınız. Adımlar:

  1. Envanteri çıkarın. Site haritasındaki adresleri okuyun; WordPress’te yayınlanmış sayfa ve yazı listesi herkese açık REST arayüzünden de alınır (/wp-json/wp/v2/pages ve posts). İki listenin farkı da bir bulgudur.
  2. Siteyi tarayın. Ana sayfadan başlayıp aynı siteye giden bağlantıları izleyin ve her sayfada hangi sayfaların kendisine bağlandığını kaydedin.
  3. Farkı alın. Envanterde olup hiçbir sayfadan bağlantı almayan adresler yetim adaydır.
  4. Bağlamı ayırın. Menü, üst bilgi ve alt bilgi bağlantıları her sayfada tekrarlanır; içerik içinden gelen bağlantıyla ayrı sayın. Yalnız menüden bağlanan sayfa teknik olarak yetim değildir ama içerikten bağlanmamıştır.
  5. Her adayı kontrol edin. robots meta değerine, yönlendirmeye ve canonical’a bakın; bilinçli olarak dizin dışı bırakılmış sayfa bir sorun olmayabilir. İlgili kontroller için XML site haritası hataları ve robots.txt ile noindex farkı sayfalarına bakın.

Çalışan denetim: tek dosyalık betik nasıl kullanılır?

Betik yalnız Python standart kütüphanesini kullanır ve tek komutla çalışır: site adresi, site haritası adresi ve isteğe bağlı çıktı dosyası verilir; WordPress sitelerinde bir bayrak REST listesini de karşılaştırır. Aşağıdaki kod, bu sayfadaki sonuçları üreten betiğin tamamıdır ve indirme bölümünde dosya olarak da vardır.

# Kullanım:  python -X utf8 yetim-sayfa-tespiti.py https://siteniz.com https://siteniz.com/sitemap_index.xml sonuc.json --rest
import json
import re
import sys
import time
import urllib.error
import urllib.parse
import urllib.request
from collections import defaultdict
from html.parser import HTMLParser

UA = {'User-Agent': 'Mozilla/5.0 (compatible; YademYetimDenetim/1.0)'}
VOID = {'br', 'img', 'input', 'meta', 'link', 'hr', 'source', 'area', 'base', 'col', 'embed', 'param', 'track', 'wbr'}
NAV_TAGS = {'nav', 'header', 'footer', 'aside'}
NAV_CLASS = re.compile(r'(menu|nav|footer|header|breadcrumb|crumbs|widget|sidebar|toc)', re.I)
ATLA = re.compile(r'\.(jpe?g|png|gif|webp|svg|pdf|zip|xml|css|js|json|txt|mp4|ico)$|/(wp-content|wp-json|wp-admin|feed|xmlrpc|wp-login)', re.I)


def indir(url):
    r = urllib.request.Request(url, headers=UA)
    try:
        with urllib.request.urlopen(r, timeout=40) as x:
            return x.status, x.geturl(), x.read().decode('utf-8', 'replace')
    except urllib.error.HTTPError as e:
        return e.code, url, ''
    except Exception:
        return 0, url, ''


def normalle(url, host):
    p = urllib.parse.urlparse(url)
    if p.scheme not in ('http', 'https') or p.netloc.replace('www.', '') != host.replace('www.', ''):
        return None
    yol = p.path or '/'
    if ATLA.search(yol) or p.query:
        return None
    if not yol.endswith('/') and '.' not in yol.rsplit('/', 1)[-1]:
        yol += '/'
    return 'https://%s%s' % (host, yol)


class Baglanti(HTMLParser):
    def __init__(self, taban, host):
        super().__init__(convert_charrefs=True)
        self.taban, self.host, self.yigin, self.bagli = taban, host, [], []

    def handle_starttag(self, tag, attrs):
        a = dict(attrs)
        if tag not in VOID:
            self.yigin.append((tag, a.get('class', '') + ' ' + a.get('id', '')))
        if tag == 'a' and a.get('href'):
            hedef = normalle(urllib.parse.urljoin(self.taban, a['href'].split('#')[0]), self.host)
            if hedef:
                gezinme = any(t in NAV_TAGS or NAV_CLASS.search(c) for t, c in self.yigin)
                icerik = any(t in ('main', 'article') for t, c in self.yigin)
                self.bagli.append((hedef, 'icerik' if icerik and not gezinme else 'gezinme'))

    def handle_endtag(self, tag):
        for i in range(len(self.yigin) - 1, -1, -1):
            if self.yigin[i][0] == tag:
                del self.yigin[i:]
                break


def site_haritasi(url, derinlik=0):
    durum, _, govde = indir(url)
    adresler = re.findall(r'<loc>\s*([^<\s]+)\s*</loc>', govde)
    if '<sitemapindex' in govde and derinlik < 3:
        return [u for alt in adresler for u in site_haritasi(alt, derinlik + 1)]
    return adresler


def rest_adresleri(taban, host):
    """WordPress REST: yayınlanmış sayfa ve yazı adresleri (herkese açık)."""
    out = set()
    for tur in ('pages', 'posts'):
        sayfa = 1
        while True:
            durum, _, g = indir('%s/wp-json/wp/v2/%s?per_page=100&page=%d&_fields=link' % (taban, tur, sayfa))
            if durum != 200:
                break
            veri = json.loads(g)
            out |= {normalle(x['link'], host) for x in veri}
            if len(veri) < 100:
                break
            sayfa += 1
    return out - {None}


def denetle(taban, harita, rest=False, bekle=0.25):
    host = urllib.parse.urlparse(taban).netloc
    envanter = sorted({normalle(u, host) for u in site_haritasi(harita)} - {None})
    rest_farki = sorted(rest_adresleri(taban, host) - set(envanter)) if rest else []
    sirada, gorulen, gelen, durumlar = [normalle(taban + '/', host)] + envanter + rest_farki, set(), defaultdict(lambda: defaultdict(set)), {}
    while sirada:
        u = sirada.pop(0)
        if u in gorulen:
            continue
        gorulen.add(u)
        durum, son, govde = indir(u)
        robots = re.search(r'<meta[^>]{0,200}name="robots"[^>]{0,200}content="([^"]*)"', govde, re.I)
        durumlar[u] = {'durum': durum, 'son_adres': son, 'robots': robots.group(1) if robots else None}
        if durum != 200 or not govde:
            continue
        p = Baglanti(u, host)
        p.feed(govde)
        for hedef, tur in p.bagli:
            if hedef != u:
                gelen[hedef][tur].add(u)
                if hedef not in gorulen:
                    sirada.append(hedef)
        time.sleep(bekle)
    sayilar = lambda u: {'icerik_gelen': len(gelen[u]['icerik']), 'gezinme_gelen': len(gelen[u]['gezinme']),
                         'toplam_gelen': len(gelen[u]['icerik'] | gelen[u]['gezinme']), 'durum': durumlar.get(u, {}).get('durum'), 'robots': durumlar.get(u, {}).get('robots')}
    kume = set(envanter)
    return {'taban': taban, 'envanter': len(envanter), 'gezilen': len(gorulen),
            'satirlar': [{'url': u, **sayilar(u)} for u in envanter],
            'haritada_yok': [{'url': u, **sayilar(u)} for u in sorted((set(gelen) | set(rest_farki)) - kume)]}


if __name__ == '__main__':
    arg = [x for x in sys.argv[1:] if not x.startswith('--')]
    s = denetle(arg[0].rstrip('/'), arg[1], rest='--rest' in sys.argv)
    L = s['satirlar']
    print('envanter %d, gezilen %d' % (s['envanter'], s['gezilen']))
    print('yetim (gelen bağlantı 0):', [(x['url'], x['robots']) for x in L if x['toplam_gelen'] == 0])
    print('yalnız gezinme bağlantılı:', [x['url'] for x in L if x['toplam_gelen'] > 0 and x['icerik_gelen'] == 0])
    print('tek içerik bağlantılı:', [x['url'] for x in L if x['icerik_gelen'] == 1])
    print('haritada yok:', [(x['url'], x['toplam_gelen'], x['robots']) for x in s['haritada_yok']])
    print('durumu 200 olmayan:', [(x['url'], x['durum']) for x in L if x['durum'] != 200])
    if len(arg) > 2:
        json.dump(s, open(arg[2], 'w', encoding='utf-8'), ensure_ascii=False, indent=1)

Betik her sayfa isteği arasında 0,25 saniye bekler; büyük sitelerde süreyi artırın. Bağlantıyı gezinme sayması için üst bilgi, menü, alt bilgi, kenar çubuğu ve sınıf adında menü, widget, içindekiler geçen alanlar kullanılır; bu sezgisel bir kuraldır, temanıza göre ayarlayın.

yademreklam.com'da 17 ve 18 Ekim 2026 taramaları ne gösterdi?

yademreklam.com’da aynı betik 17 ve 18 Ekim 2026’da 3 kez çalıştı ve yetim sayfa listesi her taramada değişti; yayın dalgası sürerken yeni sayfalar yayınlanır yayınlanmaz yetim kaldı, ilk taramadaki yetim sayfa ise sonradan düzeldi.

TaramaSite haritasındaki adresYetim sayfa (gelen bağlantı 0)Yalnız menü/altbilgi bağlantılıTek içerik bağlantılı
17 Ekim 2026 22:44611: /hizmetler/blender-3d-animasyon-teknikleri/33
17 Ekim 2026 23:471062: /efsane-cuma-seo/, /ugc-video-senaryo-ornekleri/37
18 Ekim 2026 03:311175: /efsane-cuma-seo/, /karakter-tutarliligi-yapay-zeka/, /seo-ajansi-devir-teslim/, /ugc-video-senaryo-ornekleri/, /video-ses-duzenleme/37

İlk taramada tek yetim sayfa Blender ile 3B animasyon teknikleri sayfasıydı: site haritasındaydı ve 200 döndürüyordu ama hiçbir sayfa ona bağlanmıyordu. Bağlantı eklendikten sonra sayfanın içerikten aldığı bağlantı sayısı şöyle değişti: 17 Ekim 2026 22:44 taramasında 0, 17 Ekim 2026 23:47 taramasında 6, 18 Ekim 2026 03:31 taramasında 7. Son taramadaki 5 yetim sayfa ise yayınlanmış ama henüz hiçbir sayfadan bağlantı almamış sayfalardır: /efsane-cuma-seo/, /karakter-tutarliligi-yapay-zeka/, /seo-ajansi-devir-teslim/, /ugc-video-senaryo-ornekleri/, /video-ses-duzenleme/. Bu yüzden yetim sayfa denetimi tek seferlik değil, her yayın dalgasından sonra yapılan bir kontroldür.

Yalnız menü ya da alt bilgiden bağlanan sayfalar ana sayfa, blog ve benzeri gezinme sayfalarıdır; bunlar için içerikten bağlantı gerekmez. Tek içerik bağlantısı alan sayfalar ise kırılgandır: o sayfa değişirse bağlantı da gider. Hizmet ve rehber sayfaları arasında bağlantı kurgusu için iç bağlantı stratejisi sayfasına bakın.

ailevegitim.com sonucu: site haritası ile yayınlanmış sayfa listesi arasındaki fark

ailevegitim.com’da 17 Ekim 2026 23:48 taramasında site haritasındaki 259 adresin hiçbiri yetim çıkmadı, ancak yayınlanmış sayfa listesinde (REST) olup site haritasında bulunmayan iki sayfa vardı ve biri hiçbir sayfadan bağlanmıyordu. Betik 261 sayfa gezdi (Rank Math site haritası ve REST listesi); sayfaların içerik bağlantısı ortancası 5, en az bağlantı alan 7 sayfa tek içerik bağlantısı aldı.

AdresSite haritasındaREST listesindeGelen bağlantırobots metaYorum
/mizac-testi/HayırEvet0noindex, followHiçbir sayfadan bağlanmıyor; dizin dışı bırakılmış, yani bilinçli yetim
/panom/HayırEvet260noindex, followHer sayfadan bağlanıyor (menü); dizin dışı bırakılmış

Bu iki adres, yetim sayfa ile sorunlu sayfa aynı şey değildir demek için iyi bir örnektir: biri hiç bağlantı almıyor ama noindex olduğu için bir sorun değil; diğeri her sayfadan bağlanıyor ama site haritasında yok. Dizin raporundaki durumlarla bağlantılı kontrol için Google dizine eklenmiyor sayfasına bakın. Sitenin ana hikâyesi vaka çalışmasında anlatılıyor.

Yetim sayfa bulununca ne yapılır?

Yetim sayfa bulununca sayfanın değerine göre üç karardan biri verilir: bağlantı eklenir, bilinçli olarak yetim bırakılıp belgelenir ya da sayfa birleştirilir veya kaldırılır.

DurumKararKanıt
Sayfa değerli ve dizine girmeliEn az bir ilgili sayfadan bağlamlı çapa metniyle bağlantı ekleyin; hizmet ve hub sayfalarından ya da ilgili rehberlerdenBlender sayfası: ilk taramada 0, son taramada 7 içerik bağlantısı
Sayfa bilinçli olarak dizin dışıYetim bırakılabilir; nedeni (test, panel, araç) belgelenir/mizac-testi/: noindex, follow ve 0 gelen bağlantı
Sayfa ince, eski ya da başka sayfayla çakışıyorBirleştirin, yönlendirin ya da site haritasından çıkarınAnahtar kelime yamyamlığı kontrolü
Yalnız menüden bağlanıyorİçerikten de bağlantı ekleyinYalnız gezinme bağlantılı sayfalar tablosu

Betiğin sınırları nelerdir?

Betik yalnız sunucunun gönderdiği HTML’deki bağlantıları görür; bu yüzden sonucu kesin değil, ilk tarama olarak okuyun.

  • JavaScript bağlantıları görünmez. Menüsü tarayıcıda kurulan sitelerde bağlantı eksik sayılır; Google’ın nasıl gördüğünü URL Denetimi’nin işlenmiş HTML’iyle karşılaştırın.
  • Envanter site haritasından gelir. Haritada olmayan bir yetim sayfa, REST listesi ya da CMS dışa aktarımı olmadan bulunmaz; betikteki REST bayrağı bunun içindir.
  • Parametreli adresler ve dosyalar atlanır. Filtre ve sıralama adresleri ile resim, PDF gibi dosyalar sayıma girmez.
  • robots.txt dikkate alınmaz. Taramaya kapalı bölümler de gezilir; Google’ın gördüğüyle aynı olmayabilir.
  • Gelen bağlantı sayısı değer ölçüsü değildir. Çok bağlantı alan sayfa önemli olmayabilir; amaç sıfır olanı bulmaktır.

Yadem Reklam yetim sayfa denetimini SEO hizmetinde nasıl kullanır?

Yadem Reklam, SEO hizmetinin başlangıç denetiminde ve her büyük yayından sonra bu denetimi çalıştırır; bulguları öncelik sırasıyla verir ve hangi bağlantıyı kimin ekleyeceğini teklifte yazar. Sıralama garantisi verilmez. Bu bulgunun teknik çerçevesi için teknik SEO rehberine bakın.

İndirilebilir dosyalar

Sık sorulan sorular

Yetim sayfa nedir?

Sitenizdeki başka hiçbir sayfadan bağlantı almayan sayfadır. Google, ilgilendiğiniz her sayfanın sitenizdeki en az bir başka sayfadan bağlantı alması gerektiğini söyler.

Yetim sayfa nasıl tespit edilir?

Site haritası ve yayınlanmış sayfa listesinden envanter çıkarılır, site taranıp iç bağlantılar toplanır ve envanterde olup hiç bağlantı almayan adresler ayrılır. Betik bu sayfada.

Yetim sayfa SEO için zararlı mı?

Tek başına dizinden çıkarma nedeni değildir; ancak keşif yolunu, çapa metni bağlamını ve kullanıcı erişimini kaybettirir. Google, site haritasının keşfe yardım ettiğini ama taranmayı garanti etmediğini söyler.

Site haritasındaki sayfa yetim olabilir mi?

Evet. yademreklam.com'un 18 Ekim 2026 03:31 taramasında site haritasındaki 117 sayfanın 5'i hiçbir sayfadan bağlantı almıyordu. Site haritası sayfayı Google'a bildirir, ama sitenin kendi sayfalarından gelen bağlantının yerini tutmaz.

Yetim sayfa bulununca ne yapmalıyım?

Sayfa değerliyse ilgili sayfalardan bağlamlı bağlantı ekleyin; bilinçli dizin dışıysa nedenini belgeleyin; ince ya da çakışıyorsa birleştirin veya yönlendirin.

noindex sayfalar yetim sayılır mı?

Hiçbir sayfadan bağlantı almıyorlarsa teknik olarak yetimdir; ama noindex bilinçli bir karar olabilir. ailevegitim.com'da /mizac-testi/ böyle bir örnekti.

Sıradaki adım

Sitenizin iç bağlantı denetimini birlikte yapalım

Site adresinizi WhatsApp'tan yazın; site haritası ve iç bağlantı taramasını karşılaştırıp yetim sayfaları öncelik sırasıyla yazılı verelim. SEO için fiyat, kapsama göre aylık tekliftir.

WhatsApp'tan yazın