Mert Özen Her Satırda Daha İleri
SEO ve GEO Teknik SEO — #13

Image SEO: alt Metni, Dosya Adı, srcset/picture, Image Sitemap, CDN Domain'i, og:image ve max-image-preview

Mert Özen 15 Kas 2026 12 dk 4 görüntülenme
Image SEO: alt Metni, Dosya Adı, srcset/picture, Image Sitemap, CDN Domain'i, og:image ve max-image-preview

Google görseli yalnız img element'inin src'sinden bulur; CSS background index'lenmez, srcset ve picture her zaman bir src yedeğiyle kullanılır. Kapak alt metnini katalog verisinden üretiyor, dosya adını sabit tutuyor, sitemap'e image:loc ekliyor, CDN domain'ini ve tercih edilen görseli (og:image, primaryImageOfPage, max-image-preview:large) ASP.NET Core ve Angular NgOptimizedImage ile kuruyoruz.

Sürüm notu: Bu yazıdaki kodlar .NET 10 (ASP.NET Core 10.0.15) ve Angular 22.2 (@angular/core 22.2.6) ile derlenip denenmiştir; kurallar Google'ın görsel SEO rehberinin (son güncelleme 2 Mart 2026), image sitemap sayfasının (10 Aralık 2025) ve robots meta tag dokümanının (24 Mart 2026) Kasım 2026'da okunan hâli esas alınarak anlatılmıştır.

Önce Tahmin Et

Sitedeki serilerin ortak örnek uygulaması Bookstore'un (bir online kitapçı) kitap sayfası yenileniyor. Tasarımcı ana kapağı bir div'in background-image'ı olarak koymuş, çünkü kapağın üstüne bir indirim etiketi binecek. "Benzer kitaplar" listesindeki kapaklar bir JavaScript kütüphanesiyle yükleniyor: HTML'de <img data-src="..." class="lazy"> var, src yok. Pazarlama ekibi de alt metni hazırlamış: "dune kitap dune roman dune satın al ucuz dune".

Üç soru. Google Görseller'de "Dune kitap kapağı" arayan biri bu kapakları bulur mu? Alt metni kim için yazıyoruz? Ve aynı kapak hem Türkçe hem İngilizce sayfada duruyorsa, dosya adını dile göre çevirmek gerekir mi?

Teknik SEO serisinin buraya kadarki on iki yazısı sayfanın kendisiyle uğraştı: URL, robots.txt, sitemap, canonical, rendering, hreflang, taşıma. Bu yazıyla başlayan son blok sayfadaki medyaya, katalog filtrelerine ve denetime bakıyor. İlk konu görseller.

Google Görseli Nereden Bulur?

Google'ın görsel SEO rehberinin ilk kuralı basit: Google görseli <img> element'inin src attribute'unda bulur; <picture> içindeki <img> de buna dahil. CSS ile verilen görseller, yani background-image, index'lenmiyor. Açılıştaki ana kapak bu yüzden Google Görseller için yok. İndirim etiketi gibi süsleri CSS'te bırakıp kapağın kendisini <img> ile vermek gerekiyor.

İkinci kural srcset ve <picture> ile ilgili. Rehber bazı tarayıcıların ve crawler'ların bu attribute'ları anlamadığını hatırlatıp her zaman src ile bir yedek URL vermeyi öneriyor. <picture> kullanıyorsan içindeki <img>'in de bir src'si olmalı.

Desteklenen formatlar BMP, GIF, JPEG, PNG, WebP, SVG ve AVIF (WebP ve AVIF, aynı kalitede daha küçük dosya üreten modern formatlar). Dosya uzantısının gerçek formatla uyuşması da öneriliyor. Görseli data URI (dosyanın base64 olarak doğrudan HTML'e yazılması) ile sayfaya gömmek mümkün ama sayfayı büyüttüğü için dikkatli kullanılmalı.

Lazy loading konusu ayrı bir dokümanda. Google sayfayla etkileşime girmediği için, yani scroll etmediği ve tıklamadığı için, içerik görünür alana girdiğinde yüklenmeli; tarayıcının kendi loading="lazy" desteği bunu sağlıyor. Açılıştaki data-src deseninde ise asıl URL bir JavaScript kütüphanesinin onu src'ye taşımasını bekliyor. Kütüphane render sırasında çalışmazsa Google'ın elinde URL'siz bir <img> kalıyor. Doğrulamanın yolu Search Console'daki URL Inspection aracının render edilmiş HTML'inde görsel URL'lerinin src içinde görünmesi.

alt Metni: Erişilebilirlik ve Arama İçin Aynı Cümle

Google'ın rehberi alt metni görsel metadata'sının en önemli attribute'u olarak tanımlıyor. Google alt metni sayfanın içeriği ve kendi görüntü işleme algoritmalarıyla birlikte görselin konusunu anlamak için kullanıyor; görsel bir link'se alt metin anchor text işlevi de görüyor. Aynı metin, ekran okuyucu kullanan biri için görselin kendisi. Rehberdeki örnekler bir uçtan diğerine gidiyor: alt'sız görsel kötü, keyword dizisi de kötü, tek kelime biraz daha iyi, görselde ne olduğunu anlatan kısa ve somut bir cümle en iyisi. Açılıştaki "dune kitap dune roman..." metni ikinci gruba giriyor.

Bookstore'da kapak alt metnini elle yazmak yerine katalog verisinden üretiyoruz: başlık, yazar ve baskı türü, sayfanın dilinde. Bir kapakta görünen şey tam olarak bu:

// alt metni katalog verisinden: başlık, yazar, baskı türü
public static string Alt(Book book, string lang) => lang == "tr"
    ? $"{book.Title}, {book.Author}, {FormatTr(book.Format)} kapağı"
    : $"Cover of {book.Title} by {book.Author}, {FormatEn(book.Format)}";

private static string FormatTr(BookFormat format) => format switch
{
    BookFormat.Hardcover => "ciltli baskı",
    BookFormat.Paperback => "karton kapaklı baskı",
    _ => "e-kitap",
};

Bu kodda Türkçe string'ler bilinçli olarak duruyor: konu, sayfa diline göre değişen metnin kendisi. Sonuç Türkçe sayfada "Dune, Frank Herbert, ciltli baskı kapağı", İngilizce sayfada "Cover of Dune by Frank Herbert, hardcover edition". Kapağın üstündeki yazıyı (başlık ve yazar adı) tekrar ediyor, çünkü görmeyen biri için kapağın taşıdığı bilgi bu.

Dekoratif görseller ise tam tersini istiyor: alt="". Bölüm ayırıcı bir çizgi ya da ikon için alt metin yazmak hem ekran okuyucuya gereksiz bir cümle okutur hem de sayfaya bilgi taşımayan bir metin ekler. alt attribute'unu tamamen silmek ise farklı bir şey: ekran okuyucu bu durumda çoğu zaman dosya adını okur. Kural "alt her zaman var, dekoratifse boş". HTML tarafının ayrıntıları HTML5 ve Semantic HTML serisinin "Image ve Media" yazısında.

Dosya Adı ve URL: Kısa, Açıklayıcı, Sabit

Rehber dosya adının Google'a görselin konusu hakkında hafif bir ipucu verdiğini söylüyor; IMG00023.JPG yerine kısa ve açıklayıcı bir ad, image1.jpg gibi genel adlardan kaçınmak ve büyük sitelerde adlandırmayı otomatikleştirmek öneriliyor. Bookstore'da dosya adı kitap ve yazardan, serinin ilk yazısındaki Slugifier ile üretiliyor:

// dosya adı dilden bağımsız: kitap + yazar, ör. dune-frank-herbert-640.jpg
public static string FileStem(Book book) => $"{book.Slug}-{Slugifier.ToSlug(book.Author)}";

public static string Url(Book book, int width, string ext, string baseUrl) =>
    $"{baseUrl}/images/covers/{FileStem(book)}-{width}.{ext}";

"Şeker Portakalı" kapağı böylece seker-portakali-jose-mauro-de-vasconcelos-640.jpg oluyor. Rehber, lokalize sitelerde dosya adlarını da çevirmeyi ve Latin dışı karakterlerde URL encoding kurallarına uymayı öneriyor. Bookstore'da bunu yapmıyoruz ve sebebi aynı rehberin başka bir kuralı: bir görsel birden fazla sayfada kullanılıyorsa hep aynı URL ile referans verilmeli. Kitap kapağı dile göre değişmiyor; başlık ve yazar adı zaten iki dilde aynı. Türkçe ve İngilizce sayfa aynı dosyayı gösterince Google görseli bir kez crawl edip iki sayfa için kullanabiliyor. Dosya adını çevirmek, içeriği dile göre değişen görseller için anlamlı: Türkçe metin içeren bir kampanya afişi gibi.

"Aynı URL" kuralı deploy'larda da geçerli. Görsel URL'ine her build'de değişen bir sürüm numarası eklemek (?v=1843), Google'ın gözünde her deploy'da yeni bir görsel demek. Cache'i doğru kırmanın yolu dosya içeriğinin hash'ini kullanmak: dosya değişmedikçe URL de değişmez.

srcset ve picture, src ile Birlikte

Kitap sayfasındaki ana kapak üç format ve üç genişlikle geliyor. Tarayıcı <source>'lardan desteklediği ilk formatı seçiyor; hiçbirini tanımayan bir istemci için <img>'in src'si yedek:

<picture>
    <source type="image/avif" srcset="@CoverImages.SrcSet(book, "avif", img)" sizes="@Sizes">
    <source type="image/webp" srcset="@CoverImages.SrcSet(book, "webp", img)" sizes="@Sizes">
    <img src="@CoverImages.Url(book, 640, "jpg", img)" srcset="@CoverImages.SrcSet(book, "jpg", img)" sizes="@Sizes"
         alt="@CoverImages.Alt(book, Model.Lang)" width="320" height="480" fetchpriority="high">
</picture>
<img src="/images/divider.svg" alt="" width="240" height="12">

Ana kapak ilk ekranda olduğu için loading="lazy" almıyor; "Benzer kitaplar"daki küçük kapaklar alıyor, ama src'leri her zaman dolu. Uygulamayı production ayarlarıyla açıp sayfaya baktım:

$ curl -s http://127.0.0.1:52213/books/dune | grep -E 'og:image|robots|<img' | head -5
    <meta name="robots" content="max-image-preview:large">
        <meta property="og:image" content="https://cdn.bookstore.example/images/covers/dune-frank-herbert-1200.jpg">
        <img src="https://cdn.bookstore.example/images/covers/dune-frank-herbert-640.jpg" srcset="https://cdn.bookstore.example/images/covers/dune-frank-herbert-320.jpg 320w, https://cdn.bookstore.example/images/covers/dune-frank-herbert-640.jpg 640w, https://cdn.bookstore.example/images/covers/dune-frank-herbert-1200.jpg 1200w" sizes="(max-width: 600px) 50vw, 320px"
    <img src="/images/divider.svg" alt="" width="240" height="12">
                    <img src="https://cdn.bookstore.example/images/covers/dune-messiah-frank-herbert-320.jpg" alt="Dune Messiah, Frank Herbert, karton kapaklı baskı kapağı"

İlk denemede alt metinler bask&#x131; kapa&#x11F;&#x131; gibi çıkıyordu. ASP.NET Core'un varsayılan HTML encoder'ı Latin dışı karakterleri entity'ye çeviriyor. Tarayıcı ve Google bunu doğru okur, ama kaynağı okuyan biri için zor. WebEncoderOptions'a UnicodeRanges.All vermek metni olduğu gibi bırakıyor. Format seçimi, boyutlandırma ve sizes'ın performans tarafı Web Performansı serisinin "Görsel ve Font Optimizasyonu" yazısında.

Test: Her img'in Gerçek Bir src'si Var mı?

Bu kuralların hepsi bir sayfa değişikliğiyle sessizce bozulabilir. Bookstore'da kitap sayfası WebApplicationFactory ile isteniyor ve AngleSharp ile parse ediliyor:

[Fact]
public async Task Every_img_has_a_real_src_and_an_alt_attribute()
{
    IDocument doc = await GetAsync("/books/dune");
    foreach (IElement img in doc.QuerySelectorAll("img"))
    {
        Assert.False(string.IsNullOrWhiteSpace(img.GetAttribute("src")), img.OuterHtml);
        Assert.True(img.HasAttribute("alt"), img.OuterHtml); // dekoratif görselde alt="" olur ama attribute vardır
        Assert.NotNull(img.GetAttribute("width"));
        Assert.NotNull(img.GetAttribute("height"));
    }
}

Açılıştaki data-src desenini benzer kitaplar listesine geri koyup testi çalıştırdım:

$ dotnet test --filter "FullyQualifiedName~Every_img"
...
  Failed Bookstore.Web.Tests.BookPageImageTests.Every_img_has_a_real_src_and_an_alt_attribute [226 ms]
  Error Message:
   <img data-src="/images/covers/dune-messiah-frank-herbert-320.jpg" class="lazy" alt="Dune Messiah, Frank Herbert, karton kapaklı baskı kapağı" width="160" height="240">
...
Failed!  - Failed:     1, Passed:     0, Skipped:     0, Total:     1, Duration: 232 ms - Bookstore.Web.Tests.dll (net10.0)

Hata mesajı doğrudan sorunlu element'i gösteriyor. Aynı test dosyasında ana kapağın lazy olmadığını, iki dildeki alt metnini ve kodun ürettiği her kapak dosyasının wwwroot'ta gerçekten bulunduğunu kontrol eden testler de var; sonuncusu, dosya adı kuralı değiştiğinde kırık görsel URL'lerini deploy'dan önce yakalıyor.

Image Sitemap: Sitemap'e image:loc Eklemek

Image sitemap, Google'ın kendi başına bulamayabileceği görselleri, örneğin JavaScript ile yüklenenleri, bildirmenin yolu. Ayrı bir dosya olabilir ya da mevcut sitemap'e eklenebilir. Biçim sade: http://www.google.com/schemas/sitemap-image/1.1 namespace'i, her görsel için bir <image:image> ve içinde <image:loc>. Bir <url> en fazla 1.000 görsel taşıyabiliyor. Mayıs 2022'de <image:caption>, <image:title>, <image:geo_location> ve <image:license> dokümandan kaldırıldı; bugün geçerli iki tag'den ibaret.

Serinin dördüncü yazısındaki streaming sitemap yazıcısına iki satır ekleniyor: kök element'e namespace ve her <url>'nin içine kapak:

await xml.WriteAttributeStringAsync("xmlns", "image", null, ImageNs);

// image sitemap: yalnız image:image ve image:loc; caption, title, license 2022'de kaldırıldı
private static async Task WriteImageAsync(XmlWriter xml, string imageUrl)
{
    await xml.WriteStartElementAsync("image", "image", ImageNs);
    await xml.WriteElementStringAsync("image", "loc", ImageNs, imageUrl);
    await xml.WriteEndElementAsync();
}
$ curl -s http://127.0.0.1:52213/sitemaps/books.xml | xmllint --format - | head -14
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://bookstore.example/books/dune</loc>
    <lastmod>2026-11-01</lastmod>
    <xhtml:link rel="alternate" hreflang="tr" href="https://bookstore.example/books/dune"/>
    <xhtml:link rel="alternate" hreflang="en" href="https://bookstore.example/en/books/dune"/>
    <xhtml:link rel="alternate" hreflang="x-default" href="https://bookstore.example/books/dune"/>
    <image:image>
      <image:loc>https://cdn.bookstore.example/images/covers/dune-frank-herbert-640.jpg</image:loc>
    </image:image>
  </url>
  <url>
    <loc>https://bookstore.example/en/books/dune</loc>

Her kitabın Türkçe ve İngilizce sayfası sitemap'te ayrı <url>; ikisi de aynı kapak URL'ini gösteriyor (38 kitap, 76 <image:loc>). Sitemap'e srcset'teki bütün genişlikleri yazmak gerekmiyor: amaç görseli keşfettirmek, her varyantı listelemek değil. Testler de bunu sabitliyor: her URL'de tek görsel, CDN (statik dosyaları kullanıcıya yakın sunuculardan dağıtan ağ) adresinde, ve dosyada image ile loc dışında bir image tag'i yok.

CDN Domain'i ve Search Console

Kapaklar cdn.bookstore.example'da, sayfalar bookstore.example'da. Normal sitemap'lerden farklı olarak image sitemap başka domain'deki görselleri listeleyebiliyor. Google'ın rehberleri burada iki şey istiyor: CDN domain'inin de Search Console'da doğrulanması, böylece o host'taki crawl hataları sana bildirilebiliyor; ve index'lenmesini istediğin görsellerin robots.txt ile engellenmemesi.

İkinci madde gözden kaçması kolay bir ayrıntı taşıyor. robots.txt host başına geçerli (serinin ikinci yazısı). cdn.bookstore.example/images/... adresindeki bir görsel için bakılan dosya bookstore.example/robots.txt değil, cdn.bookstore.example/robots.txt. CDN'in bu adreste ne döndüğü kuruluma bağlı: dosyaları origin'den çeken (pull) bir CDN, robots.txt isteğini de origin'e iletip onun dosyasını aynen sunabilir. O durumda origin'de /images/'i engelleyen eski bir satır, CDN'deki görselleri de Google'a kapatır. Bunu Search Console'da CDN mülkü üzerinden ya da doğrudan curl https://cdn.bookstore.example/robots.txt ile kontrol etmek gerekiyor.

Bu bölümde resmî belgelerden yararlanılmıştır.

Tercih Edilen Görsel: primaryImageOfPage, og:image ve max-image-preview

Bir sayfada birden fazla görsel varsa sonuçta hangisinin önizleme olarak gösterileceğine Google kendisi karar veriyor; ama tercihini bildirebilirsin. Mart 2026'da rehbere eklenen bölüme göre Google hem schema.org markup'ını hem de og:image meta tag'ini kaynak olarak kullanıyor: WebPage üzerinde primaryImageOfPage, sayfanın ana entity'sine (mainEntity) bağlı image ya da og:image. Rehber logo gibi genel görsellerden, yazı yoğun görsellerden, aşırı en-boy oranlarından ve düşük çözünürlükten kaçınmayı öneriyor.

Bookstore'da üç sinyal aynı dosyayı gösteriyor, kapağın 1200 piksel genişliğindeki sürümünü:

// tercih edilen görsel: og:image ve primaryImageOfPage aynı, büyük kapak
string preferredImage = CoverImages.Url(book, 1200, "jpg", _site.AbsoluteImageBase);

Dictionary<string, object> jsonLd = new()
{
    ["@context"] = "https://schema.org",
    ["@type"] = "ItemPage",
    ["@id"] = canonical,
    ["url"] = canonical,
    ["primaryImageOfPage"] = preferredImage,
    ["mainEntity"] = new Dictionary<string, object>
    {
        ["@type"] = "Book",
        ["name"] = book.Title,
        ["author"] = new Dictionary<string, object> { ["@type"] = "Person", ["name"] = book.Author },
        ["isbn"] = book.Isbn,
        ["image"] = preferredImage,
    },
};

1200 sayısının kaynağı Discover dokümanı: büyük görsellerin Discover'dan daha çok ziyaret getirdiğini söyleyip en az 1200 piksel genişlik, 300.000 pikselden fazla çözünürlük ve 16:9 oran öneriyor; büyük önizlemenin şartı da max-image-preview:large ayarı. Robots meta tag dokümanına göre bu ayar, görsel önizlemenin ekran genişliğine kadar büyük gösterilebileceğini söylüyor; standard varsayılan boyut, none hiç önizleme yok. Ayar verilmezse Google varsayılan boyutu kullanabiliyor.

Kitap kapağı burada bir uzlaşma: 2:3 oranında ve üstünde yazı var, yani Discover'ın tarif ettiği ideal görsel değil. Ama sayfayı en iyi temsil eden görsel o; Google'ın kendisi de görseli otomatik kırpmayı deniyor. Bookstore'un blog yazıları gibi metin ağırlıklı sayfalarda ise 16:9 bir kapak görseli üretmek daha doğru. Testlerden biri og:image ile primaryImageOfPage'in aynı dosya olduğunu ve robots meta'sında max-image-preview:large bulunduğunu doğruluyor; iki sinyal ayrışırsa build kırılıyor.

Angular: NgOptimizedImage ile Aynı Kurallar

Bookstore'un Angular istemcisinde (bookstore-web) kapaklar NgOptimizedImage ile basılıyor. Alt metni kuralı TypeScript'te aynı; dosyaların adı ve genişlikleri bir image loader'da:

@Component({
  selector: 'app-book-cover',
  imports: [NgOptimizedImage],
  template: `<img [ngSrc]="book().coverStem" [alt]="alt()" [width]="width()" [height]="width() * 1.5" [priority]="priority()" />`,
})
export class BookCover {
  readonly book = input.required<Book>();
  readonly width = input(320);
  // ilk ekrandaki ana kapak: lazy değil, fetchpriority=high, SSR'da preload
  readonly priority = input(false);
  private readonly locale = inject(LOCALE_ID);
  protected readonly alt = computed(() => coverAlt(this.book(), this.locale));
}
{
  provide: IMAGE_LOADER,
  useValue: (config: ImageLoaderConfig) => {
    // istenen genişliğe en yakın, ondan büyük ya da eşit dosya
    const width = COVER_WIDTHS.find((w) => w >= (config.width ?? 640)) ?? 1200;
    return `https://cdn.bookstore.example/images/covers/${config.src}-${width}.jpg`;
  },
},

ng build kitap sayfalarını prerender etti; Dune sayfasının ürettiği HTML'deki iki görsel ve preload link'i:

$ grep -o '<link as="image"[^>]*>' dist/bookstore-web/browser/books/dune/index.html
<link as="image" href="https://cdn.bookstore.example/images/covers/dune-frank-herbert-640.jpg" rel="preload" fetchpriority="high" imagesrcset="https://cdn.bookstore.example/images/covers/dune-frank-herbert-320.jpg 1x, https://cdn.bookstore.example/images/covers/dune-frank-herbert-640.jpg 2x">
$ grep -o '<img[^>]*>' dist/bookstore-web/browser/books/dune/index.html | head -2
<img alt="Cover of Dune by Frank Herbert, hardcover edition" width="320" height="480" loading="eager" fetchpriority="high" decoding="sync" ng-img="true" src="https://cdn.bookstore.example/images/covers/dune-frank-herbert-640.jpg" srcset="https://cdn.bookstore.example/images/covers/dune-frank-herbert-320.jpg 1x, https://cdn.bookstore.example/images/covers/dune-frank-herbert-640.jpg 2x">
<img alt="Cover of Foundation by Isaac Asimov, ebook edition" width="160" height="240" loading="lazy" fetchpriority="auto" decoding="auto" ng-img="true" src="https://cdn.bookstore.example/images/covers/foundation-isaac-asimov-640.jpg" srcset="https://cdn.bookstore.example/images/covers/foundation-isaac-asimov-320.jpg 1x, https://cdn.bookstore.example/images/covers/foundation-isaac-asimov-320.jpg 2x">

SEO açısından önemli olan şu: directive src'yi ilk HTML'de dolduruyor ve lazy loading için tarayıcının kendi loading="lazy"'sini kullanıyor; data-src benzeri bir ara adım yok. Uygulamanın dili en-US olduğu için alt metin İngilizce. Çıktıda bir ayrıntı da görünüyor: 160 piksellik küçük kapağın 1x ve 2x adayı aynı dosyaya çıkıyor, çünkü loader isteneni elindeki en yakın büyük dosyaya yuvarlıyor ve 320'den küçük dosya yok. Zararsız, ama elindeki dosya genişlikleriyle ngSrcset'i uyumlu tutmak gerektiğini gösteriyor.

Üretimde Dikkat

Görsel URL'lerini bir veri kuralı olarak yönet. Dosya adı, genişlik listesi ve CDN kökü tek bir yerde (Bookstore'da CoverImages) duruyorsa sayfa, sitemap, JSON-LD ve Angular istemcisi aynı URL'i üretir. Aynı görselin dört farklı URL'i, Google için dört ayrı görsel demek.

Görseli değiştirdiğinde URL'i de değiştir, değiştirmediğinde dokunma. Kapak yenilendiyse yeni dosya yeni bir içerik hash'i alır ve URL değişir; kapak aynı kaldıkça URL de aynı kalır. Her deploy'da değişen URL'ler ise Google'ın aynı görseli sürekli yeni bir görsel gibi keşfetmesine yol açar.

Görsellerinin Google Görseller'de tam boyut gösterilmesini istemiyorsan rehber bir yol tarif ediyor: isteğin referrer'ı Google domain'iyse 200 ya da içeriksiz 204 dönmek. Google sayfayı yine crawl eder ve crawl anındaki küçük önizlemeyi gösterebilir; rehber bunun cloaking sayılmadığını belirtiyor. Görseli tamamen index dışında tutmak ayrı bir konu: noimageindex ya da görsel dosyası için X-Robots-Tag: noindex (serinin üçüncü yazısı).

Sık Düşülen Tuzaklar

İçerik görselini CSS background-image ile vermek. Google CSS görsellerini index'lemiyor.

Lazy loading'i data-src ile yapıp src'yi boş bırakmak. Tarayıcının kendi loading="lazy"'si hem daha basit hem de Google için güvenli.

Dekoratif görsele uzun alt metin yazmak ya da içerik görselinde alt'ı keyword listesine çevirmek.

Görsel URL'ine her deploy'da değişen bir sürüm parametresi eklemek.

og:image olarak sitenin logosunu vermek. Rehber genel görselleri tercih edilen görsel olarak kullanmamayı öneriyor.

CDN domain'ini Search Console'da doğrulamamak ve CDN'in kendi robots.txt'sini hiç kontrol etmemek.

Küçük Bir Deneme

★☆☆ Kendi sitende bir sayfanın ilk HTML'ini curl ile al ve <img satırlarını say. src'si boş olan, alt attribute'u olmayan ya da içerik görseli olduğu hâlde CSS ile verilen görsel var mı?

★★☆ BookPageImageTests'e bir test ekle: sayfadaki her <picture> için <source>'ların srcset'indeki her URL'in wwwroot'ta bir dosyaya karşılık geldiğini kontrol etsin. Sonra CoverImages.Widths'e 1600 ekleyip testin neyi yakaladığına bak.

★★★ Bookstore'un blog yazıları için 16:9, 1200 piksel genişliğinde bir paylaşım görseli üreten bir endpoint yaz (başlık ve kapak birlikte). Görselin URL'i yazının içeriği değişmedikçe aynı kalsın; og:image ve primaryImageOfPage bu görseli göstersin ve testler ikisinin aynı olduğunu doğrulasın.

Görseller için kurduğumuz düzen (tek ve sabit URL, sayfa, sitemap ve structured data'nın aynı şeyi söylemesi) videoda daha da önemli, çünkü bir videonun aynı anda üç URL'i var: sayfası, player'ı ve dosyası. Bir sonraki yazıda watch page kavramını, video sitemap'ini, Clip ve SeekToAction ile key moments'ı ve thumbnail kurallarını Bookstore'un video sayfaları üzerinden kuracağız.