Diğer Gallery Tipleri İçin Tarifler: Event, Course List, Discussion Forum, Q&A, Dataset, Software App ve Image Metadata
Bir tip, galerideki görünüme göre değil sayfanın gerçekte ne olduğuna göre seçilir: yalnızca online bir etkinlik Event'e, ürün sayfasındaki soru-cevap QAPage'e, kitap yorumları DiscussionForumPosting'e aday değildir. Event, Discussion forum, Q&A ve Image metadata için Bookstore örnekli kartlar veriyor, Bookstore'a uymayan tipleri ve Türkiye'deki carousel sınırını açıklıyor, kartları xUnit'te çalışan bir kural tablosuyla test ediyoruz.
Sürüm notu: Bu yazı Google Search Central'ın structured data galerisinin (son güncelleme 16 Ekim 2026) ve Event, Discussion forum, Q&A, Image metadata, Dataset, Course list ve Carousel dokümanlarının 15 Kasım 2026'daki hâlini ve schema.org 30.1'i esas alır; kodlar .NET 10 (SDK 10.0.404) ve xUnit v3 4.0 ile derlenip denenmiştir.
Önce Tahmin Et
Bookstore (sitedeki serilerin ortak örnek uygulaması, bir online kitapçı) aralık ayında Dune için bir okuma akşamı düzenliyor: bir salonda yapılacak ve aynı anda canlı yayınlanacak. Ekip etkinlik sayfasına Event markup'ı ekliyor ve location olarak yalnızca yayın linkini veren bir VirtualLocation yazıyor. Aynı hafta kitap sayfasının altındaki "Bu kitap hakkında sorular" bölümüne QAPage, yorumlara da DiscussionForumPosting markup'ı ekleniyor; "galeride 25 özellik var, ne kadar çok tip o kadar çok görünüm" deniyor. Soru: Bu üç markup'tan hangisi galerideki özelliğe aday?
Hiçbiri, ve üçünün de sebebi aynı: tip sayfanın gerçekte ne olduğuna göre değil, galerideki bir görünüme göre seçilmiş. Bu yazı galerinin geri kalanını Bookstore gözüyle gezen kısa tarif kartlarından oluşuyor: ne zaman uygun, ne zorunlu, en küçük JSON-LD ve sık yapılan hata.
Galerinin Bugünkü Hâli
Google'ın "Structured data markup that Google Search supports" sayfası 16 Ekim 2026 güncellemesiyle 25 özellik listeliyor. Bu seri dokuzunu işledi: Article, Breadcrumb, Organization ve Profile page üçüncü yazıda; Video, Software app ve Speakable dördüncüde; Product altıncıda; Review snippet yedincide. Bu yazı Event, Discussion forum, Q&A ve Image metadata için kart veriyor, Dataset, Course list ve Carousel'e kısaca bakıyor ve kalanların Bookstore'a neden uymadığını bir tabloda topluyor.
Listede olmayanlar da bir şey söylüyor. Book actions'ın dokümanı duruyor ama galeride yok; altıncı yazıda gördüğümüz gibi feed ve ortaklık gerektiriyor. FAQ (sıkça sorulan sorular) ve HowTo'nun hikâyesi ise dördüncü yazıda: galeri sabit bir liste değil ve her tip için soru "bugün destekleniyor mu?" ile başlıyor.
Bu bölümde resmî belgelerden yararlanılmıştır.
Kart: Event
Ne zaman uygun: fiziksel bir yerde, belirli bir tarihte, herkesin katılabileceği bir etkinlik. Google Haziran 2025'te dokümanı değiştirdi: online etkinlik property'leri kaldırıldı ve bir etkinliğin Google'ın etkinlik deneyimine aday olması için genel halka açık olması ve fiziksel bir yerde yapılması gerekiyor. Üyelik ya da davetiye gerektiren etkinlikler ve gerçek dünyada karşılığı olmayan sanal deneyimler aday değil. Her etkinliğin tek bir etkinliğe odaklanan kendi URL'i olmalı; takvim sayfaları değil.
Zorunlu: name, startDate, location (Place) ve location.address. Önerilen: description, endDate, eventStatus, image, location.name, offers, organizer, performer, previousStartDate. Bookstore'un okuma akşamı için kart:
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Dune Reading Night: Q&A with Ada Kaplan",
"description": "A one-evening reading of the first chapter of Dune, followed by questions from readers.",
"startDate": "2026-12-12T19:00:00+03:00",
"endDate": "2026-12-12T21:00:00+03:00",
"eventStatus": "https://schema.org/EventScheduled",
"location": {
"@type": "Place",
"name": "Sample Culture Center",
"address": {
"@type": "PostalAddress",
"streetAddress": "Sample Street 1",
"addressLocality": "Istanbul",
"addressCountry": "TR"
}
},
"image": ["https://bookstore.example/images/events/dune-reading-night-16x9.jpg"],
"organizer": { "@id": "https://bookstore.example/#organization" },
"performer": { "@type": "Person", "name": "Ada Kaplan" },
"offers": {
"@type": "Offer",
"url": "https://bookstore.example/events/dune-reading-night",
"price": 0,
"priceCurrency": "TRY",
"availability": "https://schema.org/InStock",
"validFrom": "2026-11-20T10:00:00+03:00"
}
}
Sık hata: etkinliğin adına mekân adını, fiyatı ya da "hemen bilet al" gibi bir çağrıyı yazmak. Google name'in yalnızca etkinliğin adı olmasını, mekânın location.name'e gitmesini istiyor. Tarihlerde de dikkat: saat yazıyorsan UTC (eşgüdümlü evrensel zaman) offset'ini ekle ya da hiç saat yazma; 2026-12-12T00:00:00+00:00 gibi bir değer, İstanbul'daki bir etkinlik için gece yarısı değil, sabah 03:00 demek. Ücretsiz etkinlikte price sıfır olabilir; kayıt sayfası offers.url'e gider. Yayın linki bu markup'ta yer almıyor; fiziksel etkinliğin bir yayını olması onu online etkinliğe çevirmiyor, ama yalnızca yayın olan bir etkinlik aday değil.
Kart: Discussion Forum
Ne zaman uygun: kullanıcıların kendi deneyimlerini paylaştığı forum sayfaları. Google'ın dokümanı geçerli ve geçersiz örnekleri açıkça veriyor: bir oyun hakkında konuşulan topluluk forumu geçerli; site sahibinin ya da onun adına çalışanların yazdığı bir makale ya da blog yazısı, altında yorumlar olsa bile geçersiz; bir ürün hakkındaki kullanıcı yorumları da geçersiz. Baştaki ikinci hata burada: kitap yorumları DiscussionForumPosting değil, yedinci yazıdaki Review.
Zorunlu: author ve author.name, datePublished, ayrıca text, image ya da video'dan biri; yorumlar (Comment) için de aynı üçlü. Bookstore'da bir okur forumu olsaydı bir konu sayfası şöyle görünürdü:
{
"@context": "https://schema.org",
"@type": "DiscussionForumPosting",
"headline": "Should I read the Dune appendices first?",
"text": "I am about to start Dune. A friend says reading the appendices first spoils nothing and helps with the names. Did anyone try that?",
"url": "https://bookstore.example/forum/dune/read-appendices-first",
"datePublished": "2026-11-10T21:04:00+03:00",
"author": {
"@type": "Person",
"name": "Alan T.",
"url": "https://bookstore.example/forum/users/alan-t"
},
"commentCount": 1,
"comment": [
{
"@type": "Comment",
"text": "I did. The glossary helped, the history section was better after the book.",
"datePublished": "2026-11-10T22:30:00+03:00",
"author": {
"@type": "Person",
"name": "Grace H.",
"url": "https://bookstore.example/forum/users/grace-h"
}
}
]
}
Google bu tipte, genel tercihinin aksine, uzun metni markup'ta tekrar etmemek için Microdata ya da RDFa'yı öneriyor; JSON-LD de tam olarak destekleniyor. Mart 2026'da yorum zincirinin yapısını netleştirmek için yeni property'ler eklendi; içerik bir yapay zekâ modeli tarafından üretildiyse digitalSourceType ile bunu belirtmek mümkün. Forum asıl olarak soru ve cevaplardan oluşuyorsa Google Q&A markup'ını öneriyor.
Kart: Q&A
Ne zaman uygun: tek bir sorunun ve kullanıcıların o soruya yazdığı cevapların olduğu sayfa. Google'ın geçerli örnekleri arasında kullanıcıların tek bir soruya cevap yazabildiği bir ürün destek sayfası var; geçersiz örnekleri arasında ise sitenin kendi yazdığı sıkça sorulan sorular sayfası, kullanıcıların tek sayfada birden çok soru sorup cevapladığı ürün sayfası, bir soruyu cevaplayan blog yazısı ya da rehber. Baştaki "Bu kitap hakkında sorular" bölümü bu yüzden aday değil: tek sayfada birden çok soru var.
Zorunlu: mainEntity altında tek bir Question, onun name'i ve answerCount'u, acceptedAnswer ya da suggestedAnswer'dan en az biri ve her Answer'ın text'i. Her soruya kendi sayfasını veren bir yapıda kart:
{
"@context": "https://schema.org",
"@type": "QAPage",
"mainEntity": {
"@type": "Question",
"name": "Does the Dune paperback include the maps?",
"text": "I want the edition with the map of Arrakis. Does the paperback (ISBN 9780000000019) have it?",
"answerCount": 2,
"datePublished": "2026-11-05T10:12:00+03:00",
"author": { "@type": "Person", "name": "Linus T." },
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes, the map is on the two pages before chapter one, in black and white.",
"datePublished": "2026-11-05T11:40:00+03:00",
"upvoteCount": 4,
"url": "https://bookstore.example/questions/dune-paperback-maps#answer-2",
"author": { "@type": "Person", "name": "Ada L." }
},
"suggestedAnswer": [
{
"@type": "Answer",
"text": "Mine has it too, but the hardcover prints it larger.",
"datePublished": "2026-11-06T09:02:00+03:00",
"upvoteCount": 1,
"url": "https://bookstore.example/questions/dune-paperback-maps#answer-3",
"author": { "@type": "Person", "name": "Barbara L." }
}
]
}
}
acceptedAnswer sitede bir şekilde kabul görmüş cevap olmalı: soruyu soran, bir moderatör ya da oylama tarafından. Google, "en yeni" gibi başka bir sıralamanın kabul edilen cevap olarak işaretlenmemesini istiyor. Cevaplara yazılan yorumlar Answer değil Comment. Google'ın galerisinde ayrı bir özellik olan Education Q&A ise öğrenci ödev soruları için ve tek bir uzman cevabına izin veriyor; Bookstore'un konusu değil.
Kart: Image Metadata
Ne zaman uygun: bir görselin yaratıcısını, telif bilgisini ve nasıl lisanslanabileceğini Google Görseller'de göstermek istediğinde. Bookstore için anlamlı olan, kendi çektiği ürün fotoğrafları. Kitabın kapak tasarımı Bookstore'un değil; Bookstore yalnızca kendi fotoğrafının lisansını söyleyebilir.
Zorunlu: contentUrl ve creator, creditText, copyrightNotice ya da license'tan en az biri. Google, birini eklediğinde diğer üçünün Rich Results Test'te önerilen alan olarak görüneceğini yazıyor. Görselin "Licensable" rozetiyle gösterilmesi için license şart; acquireLicensePage da öneriliyor:
{
"@context": "https://schema.org",
"@type": "ImageObject",
"contentUrl": "https://bookstore.example/images/books/dune-paperback-1x1.jpg",
"creator": { "@type": "Organization", "name": "Bookstore" },
"creditText": "Photo: Bookstore",
"copyrightNotice": "© 2026 Bookstore",
"license": "https://bookstore.example/image-license",
"acquireLicensePage": "https://bookstore.example/image-license#request"
}
Sık hata: markup'ı yalnızca bir sayfaya koymak. Google, structured data'yı görselin kullanıldığı her yer için, aynı görsel olsa bile, ayrı ayrı eklemeyi istiyor. Alternatif, bilgiyi IPTC (International Press Telecommunications Council; basın fotoğrafçılığının metadata standardını belirleyen kuruluş) alanları olarak görselin kendisine gömmek; ikisi çelişirse Google structured data'yı kullanıyor.
Bookstore'a Uymayanlar
Galerinin kalanında bir tipin neden uymadığını bilmek, neden uyduğunu bilmek kadar işe yarıyor. Google'ın genel yönergeleri structured data'nın sayfa içeriğinin doğru bir temsili olmasını istiyor ve ilgisiz işaretlemeye örnek olarak tarifleri "recipe" diye işaretleyen bir marangozluk sitesini veriyor.
| Özellik | Neden Bookstore'a uymuyor? |
|---|---|
| Course list | Yalnızca İngilizce sonuçlarda; en az üç kurs, carousel markup'ı ve eğitmenli, öğrencili bir müfredat gerekiyor. Bookstore kurs satmıyor. |
| Dataset | Bookstore bir veri kümesi yayımlamıyor; yayımlasaydı bile görünüm Dataset Search ile sınırlı. |
| Local business | Fiziksel mağaza için. Bookstore yalnızca online; doğru tip sekizinci yazıdaki OnlineStore. |
| Recipe, Movie | Yemek tarifi ve film listeleri için; bir kitapçının sayfası değil. |
| Job posting, Employer aggregate rating | İş ilanı ve işveren puanı için; Bookstore'un örnek uygulamasında kariyer sayfası yok. |
| Vacation rental | Hotel Center erişimi ve Google'la teknik bir ortaklık gerektiriyor. |
| Math solver, Education Q&A | Matematik problemleri ve öğrenci ödev soruları için. |
| Subscription and paywalled content | Ödeme duvarlı içerik için; Bookstore'un sayfaları açık. |
İki tip ayrıca anılmalı. Software app'in kartı dördüncü yazıda: zorunlu alanlar name, offers.price ve bir puan ya da yorum; puan yoksa aday değil. Dataset'in zorunlu alanları ise name ve 50 ile 5.000 karakter arasında bir description.
Carousel ayrı bir özellik değil, bir birleşim. Klasik host carousel yalnızca Course list, Movie, Recipe ve Restaurant ile birlikte çalışıyor. Beta olan "structured data carousels" ItemList'i LocalBusiness, Product ya da Event ile birleştiriyor, ama yalnızca Avrupa Ekonomik Alanı, Türkiye ve Güney Afrika'da ve Türkiye'de yalnızca otel, tatil kiralaması ve yerel işletme sorgularında. Bookstore'un kategori sayfası bu yüzden Türkiye'de bir ürün carousel'ine aday değil.
Bu bölümde resmî belgelerden yararlanılmıştır.
Kartları Test Etmek
Kartlar dokümandan kopyalanıp unutulacak örnekler değil; Bookstore'un test projesinde JSON dosyaları olarak duruyorlar ve her build'de küçük bir kural tablosundan geçiyorlar. Kurallar, Google'ın her özellik için zorunlu tuttuğu alanların bir kısmı:
// Özellik başına Google'ın zorunlu property'lerinden birkaçı; Search Central dokümanlarından 2026-11-15'te okundu
public static class GalleryRules
{
public static IReadOnlyList<string> Check(JsonElement node) => node.GetProperty("@type").GetString() switch
{
"Event" => Event(node),
"DiscussionForumPosting" => Forum(node),
"QAPage" => QaPage(node),
"ImageObject" => Image(node),
var other => [$"no rule for {other}"],
};
private static List<string> Event(JsonElement e)
{
List<string> problems = Missing(e, "name", "startDate");
// etkinlik fiziksel bir yerde olmalı: adresi olan bir Place
if (!e.TryGetProperty("location", out JsonElement place) || Type(place) != "Place")
{
problems.Add("location must be a Place (virtual-only events are not supported)");
}
else
{
problems.AddRange(Missing(place, "address").Select(p => $"location.{p}"));
}
return problems;
}
private static List<string> Forum(JsonElement post)
{
List<string> problems = Missing(post, "datePublished");
if (!post.TryGetProperty("author", out JsonElement author) || !author.TryGetProperty("name", out _))
{
problems.Add("author.name is missing");
}
if (!HasAny(post, "text", "image", "video"))
{
problems.Add("one of text, image or video is required");
}
return problems;
}
private static List<string> QaPage(JsonElement page)
{
// sayfa başına tam bir Question, mainEntity altında
if (!page.TryGetProperty("mainEntity", out JsonElement q) || q.ValueKind != JsonValueKind.Object
|| Type(q) != "Question")
{
return ["mainEntity must be a single Question"];
}
List<string> problems = Missing(q, "name", "answerCount");
if (!HasAny(q, "acceptedAnswer", "suggestedAnswer"))
{
problems.Add("a Question needs acceptedAnswer or suggestedAnswer");
}
foreach (JsonElement answer in Answers(q))
{
problems.AddRange(Missing(answer, "text").Select(p => $"Answer.{p}"));
}
return problems;
}
Testler iki yönlü: iyi kartlarda hiç sorun çıkmamalı, bilinen hataları içeren kartlarda beklenen sorun bulunmalı.
using System.Text.Json;
namespace Bookstore.Web.Tests;
public sealed class GalleryCardTests
{
private static JsonElement Load(string file) =>
JsonDocument.Parse(File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "GalleryCards", file))).RootElement;
[Theory]
[InlineData("event.json")]
[InlineData("discussion-forum.json")]
[InlineData("qa-page.json")]
[InlineData("image-metadata.json")]
public void Card_meets_the_required_properties(string file)
{
JsonElement card = Load(file);
Assert.Equal("https://schema.org", card.GetProperty("@context").GetString());
Assert.Empty(GalleryRules.Check(card));
}
[Theory]
[InlineData("event-online-only.json", "location must be a Place (virtual-only events are not supported)")]
[InlineData("event-online-only.json", "name is missing")]
[InlineData("qa-product-page.json", "mainEntity must be a single Question")]
public void Rule_catches_a_known_mistake(string file, string expected)
{
Assert.Contains(expected, GalleryRules.Check(Load(file)));
}
}
Baştaki yalnızca yayın linkiyle yazılmış etkinlik kartını iyi kartlar arasına koyunca:
failed Bookstore.Web.Tests.GalleryCardTests.Card_meets_the_required_properties(file: "event-online-only.json") (0ms)
Assert.Empty() Failure: Collection was not empty
Collection: ["name is missing", "location must be a Place (virtual-only events are "···]
$ dotnet test --project Bookstore.Web.Tests
Test run summary: Passed!
total: 35
failed: 0
succeeded: 31
skipped: 4
Bu kurallar Google'ın kararının yerine geçmiyor; beşinci yazıda söylediğimiz gibi uygunluğu yalnızca Google'ın kendi araçları söyler. Amacı, dokümanda açıkça yazan bir şartı unutmayı build sırasında yakalamak.
Üretimde Dikkat
Galeriyi düzenli takip et. Google'ın değişiklik günlüğü (developers.google.com/search/updates) bir RSS (sitedeki güncellemeleri abonelere ileten biçim) feed'i de sunuyor; bu serideki tarihlerin hepsi oradan. 2025 ve 2026'daki değişiklikler, bir tipin desteğinin birkaç ay içinde değişebildiğini gösterdi: Event'in online property'leri kaldırıldı, mağaza düzeyinde kargo politikası eklendi, review snippet yönergelerine yeni bir madde girdi.
Kartları sayfaya taşırken görünen içerikle bağla. Buradaki JSON dosyaları test verisi; gerçek bir etkinlik ya da forum sayfası yazıldığında markup, altıncı yazıdaki fiyat gibi, sayfanın kendi verisinden üretilmeli ve sayfayla aynı olduğunu bir test göstermeli.
Kural tablosunu dokümanla birlikte güncelle. Bir kural Google'ın artık istemediği bir şeyi istiyorsa test yanlış bir güven verir; tarihli yorum satırı bunu hatırlatmak için.
Sık Düşülen Tuzaklar
İçerikle ilgisi olmayan tipi "rich result alırım" diye eklemek. Google'ın genel yönergeleri ilgisiz işaretlemeyi spam sayabilir. Structured data için verilen bir manual action sayfayı aramadan çıkarmaz, ama sayfadaki structured data yok sayılır.
Yalnızca online olan bir etkinliği Event olarak işaretlemek. Haziran 2025'ten beri aday değil.
Ürün sayfasındaki soru-cevap bölümünü QAPage yapmak. Tek sayfada birden çok soru var; Google bunu açıkça geçersiz örnek olarak veriyor.
Kitap yorumlarını DiscussionForumPosting olarak işaretlemek. Ürün hakkındaki kullanıcı yorumları forum değil, Review.
Kapak görseline lisans yazmak. Kapak tasarımının hakları yayınevine ve tasarımcısına ait; Bookstore yalnızca kendi fotoğrafının lisansını verebilir.
Küçük Bir Deneme
★☆☆ event.json'a bir previousStartDate ve eventStatus: EventRescheduled ekleyerek etkinliği bir hafta ertele. Google, durum değişse bile startDate'in silinmemesini istiyor; neden?
★★☆ GalleryRules'a Dataset için bir kural ekle: name ve description zorunlu, description 50 ile 5.000 karakter arasında olmalı. Kuralı bir iyi ve bir kötü kartla test et.
★★★ Okuma akşamını Bookstore'da gerçek bir Razor sayfasına (/events/dune-reading-night) taşı; markup'ı sayfanın kendi verisinden üret ve name, startDate ve mekân adının sayfada görünen metinle aynı olduğunu JsonLdPage ile test et.
Seri burada bitiyor. Structured data'nın ne olduğundan ve JSON-LD'yi güvenle üretmekten başladık; bir teknik blog için entity graph kurduk, Google'ın neyi desteklediğini ve neyi kaldırdığını gördük, hepsini testlere bağladık. Son dört yazıda Bookstore'un mağaza tarafına geçtik: kitap sayfasının fiyatı ve stoğu, okur yorumları ve puan, mağazanın iade ve kargo politikası ve galerinin geri kalanı. Bütün yazıların ortak dersi aynı: markup sayfanın kendi verisinden üretilmeli ve sayfayla aynı olduğunu bir test göstermeli. Buradan sonraki doğal adım işaretlediğin içeriğin kendisi: içerik tarafındaki SEO'yu (arama motoru optimizasyonu) bu turda yazılan Content SEO serisi ele alıyor.