ItemList JSON-LD on Jobs/Shifts list & landing pages
Mark up the result list as a schema.org ItemList (ordered listing URLs) so Google reads the landing/list pages as a curated collection. Emitted alongside the breadcrumb JSON-LD when there are results. Improvement 6 of the backlog (SEO). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -145,4 +145,8 @@
|
||||
@section Head {
|
||||
@{ var bcUrl = $"{ViewContext.HttpContext.Request.Scheme}://{ViewContext.HttpContext.Request.Host}"; }
|
||||
@Html.Raw("<script type=\"application/ld+json\">" + JobsMedical.Web.Services.SeoJsonLd.Breadcrumb(Model.Breadcrumbs, bcUrl) + "</script>")
|
||||
@if (Model.Results.Count > 0)
|
||||
{
|
||||
@Html.Raw("<script type=\"application/ld+json\">" + JobsMedical.Web.Services.SeoJsonLd.ItemList(Model.Results.Select(j => "/Jobs/Details/" + j.Id), bcUrl) + "</script>")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,4 +178,8 @@
|
||||
@section Head {
|
||||
@{ var bcUrl = $"{ViewContext.HttpContext.Request.Scheme}://{ViewContext.HttpContext.Request.Host}"; }
|
||||
@Html.Raw("<script type=\"application/ld+json\">" + JobsMedical.Web.Services.SeoJsonLd.Breadcrumb(Model.Breadcrumbs, bcUrl) + "</script>")
|
||||
@if (Model.Results.Count > 0)
|
||||
{
|
||||
@Html.Raw("<script type=\"application/ld+json\">" + JobsMedical.Web.Services.SeoJsonLd.ItemList(Model.Results.Select(s => "/Shifts/Details/" + s.Id), bcUrl) + "</script>")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +145,22 @@ public static class SeoJsonLd
|
||||
}, Opts));
|
||||
}
|
||||
|
||||
/// <summary>ItemList JSON-LD for a results/landing page — an ordered list of the listing URLs,
|
||||
/// so Google understands it as a curated collection. Relative URLs are made absolute.</summary>
|
||||
public static string ItemList(IEnumerable<string> urls, string baseUrl)
|
||||
{
|
||||
var els = urls.Select((u, i) => (object)new Dictionary<string, object?>
|
||||
{
|
||||
["type"] = "ListItem", ["position"] = i + 1, ["url"] = u.StartsWith("http") ? u : baseUrl + u,
|
||||
}).ToList();
|
||||
return Fix(JsonSerializer.Serialize(new Dictionary<string, object?>
|
||||
{
|
||||
["@context"] = "https://schema.org",
|
||||
["@type"] = "ItemList",
|
||||
["itemListElement"] = els,
|
||||
}, Opts));
|
||||
}
|
||||
|
||||
// Nested anonymous objects use "type"/"queryyy" placeholders for @type / query-input;
|
||||
// restore the @-prefixed schema.org keys here.
|
||||
private static string Fix(string json) => json
|
||||
|
||||
Reference in New Issue
Block a user