This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Varför du inte hittade det här på Google?
Wednesday, 26 November 2025
Jag har drivit den här bloggen i ett tag nu., skriver detaljerade tekniska artiklar på ASP, ., NET Core och ,, Beståndsdel av enhet, ,, HTMX och ,, och alla möjliga sorters.
Problemet: Varje sida såg lika ut som Google
När Google går igenom din sida, tittar den på flera nyckelsignaler för att förstå vad varje sida handlar om.
The Smoking Gun: Statiska Metabeschreibunger
Här är vad min _Layout.cshtml såg ut som
<meta name="description" content="Scott Galloway is a lead developer and software engineer with a passion for building web applications.">
<meta property="og:description" content="Scott Galloway is a lead developer and software engineer with a passion for building web applications.">
Varje. Enlig. sida . Samma beskrivningM SK3 Min artikel om Hintergrundtjänster i ASP.NET Core? Samma beskrivning som min hemsida. Min djupdykning in RAG arkitektur? Samma beskrywing.
Google ser 200+ sidor med identiska beskrywings och tror att "den här sidan har duplicerade innehållsmängder M SK2 eller
Missande kanoniska URLs
Jag har en flerspråkig blogg med översättningar. Samma innehåll existerar på
/blog/my-article( engelska)/blog/my-article/fr( franskaM SK1/blog/my-article/de(DeutskM SK1
Utan kanoniska URLs, Google skulle kunna se dessa som duplicerade innehåll, som dämpar SEO-värdet över flera URLs istället för att konsolidera det på den primära sidan
Ingen strukturerad data
Googles sökresultat kan visa rika fragment. JSON-LD strukturerade data. Jag var
Statiska sociala bilder
Varje sida delade samma og:image. Medan detta inte affecterar direkt Googles rankinger , påverkar det click- -through rates when articles are shared on social media.
The Fixes
1. Dynamiska Metabeschreibunger
Den första lösningen var att göra layout stöd för dynamiska beschreibunger med en vetlig fallback
@{
var currentUrl = $"https://{Context.Request.Host}{Context.Request.Path}";
var defaultDescription = "Scott Galloway is a lead developer and software engineer with a passion for building web applications.";
var pageDescription = ViewBag.Description as string ?? defaultDescription;
}
<!-- Canonical URL -->
<link rel="canonical" href="@currentUrl" />
<!-- Facebook Meta Tags -->
<meta property="og:url" content="@currentUrl">
<meta property="og:type" content="@(ViewBag.OgType ?? "website")">
<meta property="og:title" content="@ViewBag.Title">
<meta property="og:description" content="@pageDescription">
<meta property="og:site_name" content="mostlylucid" />
<!-- Twitter Meta Tags -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="@ViewBag.Title">
<meta name="twitter:description" content="@pageDescription">
<!-- Meta Description -->
<meta name="description" content="@pageDescription" />
<!-- Article metadata for blog posts -->
@if (ViewBag.PublishedDate != null)
{
<meta property="article:published_time" content="@(((DateTime)ViewBag.PublishedDate).ToString("yyyy-MM-ddTHH:mm:ssZ"))" />
<meta property="article:author" content="Scott Galloway" />
}
@if (ViewBag.Categories != null)
{
foreach (var category in ViewBag.Categories)
{
<meta property="article:tag" content="@category" />
}
}
Nu låter layouten ViewBag.Description om ställts, faller tillbaka till en standardversion. Den kanoniska URL: n ställs automatiskt till den nuvarande sidan
2. Automatiskt-Generat descriptions for blog posts
Varje bloggpost genererar nu dess Beschreibung från de första 155-tecknen i innehållet Post.cshtml:
@using Mostlylucid.Shared.Helpers
@model Mostlylucid.Models.Blog.BlogPostViewModel
@{
Layout = "_Layout";
ViewBag.Title = $"{Model.Title} ({Model.Language.ConvertCodeToLanguage()})";
// Generate description from plain text content (first 155 chars, truncate at word boundary)
var plainText = Model.PlainTextContent ?? "";
var description = plainText.Length > 155
? plainText.Substring(0, plainText.LastIndexOf(' ', 155)) + "..."
: plainText;
description = description.Replace("\n", " ").Replace("\r", "").Trim();
ViewBag.Description = description;
// Set article metadata
ViewBag.OgType = "article";
ViewBag.PublishedDate = Model.PublishedDate;
ViewBag.Categories = Model.Categories;
// Build canonical URL (without language suffix for English)
var canonicalUrl = Model.Language == "en"
? $"https://{Context.Request.Host}/blog/{Model.Slug}"
: $"https://{Context.Request.Host}/blog/{Model.Slug}/{Model.Language}";
}
Nyckelpunkten här:
- Spräng vid ordgränsen - Vi hittar det sista utrymmet innan 155-tecknen för att undvika att skära ihop ord
- Strippa nya linjer - Metabeschreibunger borde vara ensamma
- Bestämda
og:typetill "articleM SK1 - säger till sociala plattformar att det här är en artikel , inte en generisk webbsida - Passa artikel-metadata - Published date and categories flow through to the layout
3. JSON-LD Strukturerade data
Det här är den stora för rika snippets.
<!-- JSON-LD Structured Data for Blog Post -->
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "BlogPosting",
"headline": "@Model.Title",
"description": "@description",
"datePublished": "@Model.PublishedDate.ToString("yyyy-MM-ddTHH:mm:ssZ")",
@if (Model.UpdatedDate.HasValue)
{
@:"dateModified": "@Model.UpdatedDate.Value.ToString("yyyy-MM-ddTHH:mm:ssZ")",
}
"author": {
"@@type": "Person",
"name": "Scott Galloway",
"url": "https://mostlylucid.net/blog/aboutme"
},
"publisher": {
"@@type": "Organization",
"name": "mostlylucid",
"logo": {
"@@type": "ImageObject",
"url": "https://mostlylucid.net/img/logo.svg"
}
},
"mainEntityOfPage": {
"@@type": "WebPage",
"@@id": "@canonicalUrl"
},
"wordCount": @Model.WordCount,
"inLanguage": "@Model.Language",
"keywords": "@string.Join(", ", Model.Categories)",
"image": "https://mostlylucid.net/img/social2.jpg"
}
</script>
Kom ihåg @@ att fly ut för @ symbol i Razor-uppfattningar - JSON -LD använder @context och @type som annars skulle tolkas som Razor syntax.
Denna strukturerade data säger till Google:
- Vilken typ av innehåll är detta? (Blogposting)
- Vem skrev det? (Person med en URL för att lära sig mer
- När den publicerades och ändrades
- Vilka ämnen omfattas av den (talord från kategorier)
- Hur länge är det? (tal ord)
- Vilket språk det är, ', i
Google kan använda detta för att visa innehållsrika fragment i sökresultaten, inklusive författareinformationen , publiceringsdatum, och merM SK3
4. Enkela Beschreibunger för nyckelsidor
Glöm inte dina statiska sidor.
<!-- Home page -->
@{
ViewBag.Title = "mostlylucid- Scott Galloway's Developer Blog";
ViewBag.Description = "Technical blog covering ASP.NET Core, C#, Entity Framework, HTMX, Docker, and modern web development. Practical tutorials, NuGet packages, and open source projects.";
}
<!-- Blog index -->
@{
ViewBag.Title = "Blog Posts";
ViewBag.Description = "Technical articles on ASP.NET Core, C#, Entity Framework, Docker, and modern web development. Practical tutorials and real-world examples from a lead developer.";
}
<!-- Contact page -->
@{
ViewBag.Title = "Contact Scott Galloway";
ViewBag.Description = "Get in touch with Scott Galloway. Questions about ASP.NET Core, C#, web development, or collaboration opportunities? Send me a message.";
}
<!-- Search page -->
@{
ViewBag.Title = "Search Results";
ViewBag.Description = "Search through technical articles on ASP.NET Core, C#, Entity Framework, and web development. Find tutorials, guides, and solutions.";
}
Andra SEO nödvändigheter
Sitemap
Du behöver en platskarta. Här' är en enkel kontroller som genererar en dynamiskt
public class SiteMapController(
IBlogViewService blogViewService,
IHttpContextAccessor httpContextAccessor) : Controller
{
[HttpGet]
[ResponseCache(Duration = 43200)] // Cache for 12 hours
public async Task<IActionResult> Index()
{
var pages = await blogViewService.GetPosts();
var siteUrl = $"https://{httpContextAccessor.HttpContext?.Request.Host}";
XNamespace sitemap = "http://www.sitemaps.org/schemas/sitemap/0.9";
var feed = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement(sitemap + "urlset",
from page in pages
select new XElement(sitemap + "url",
new XElement(sitemap + "loc", $"{siteUrl}/blog/{page.Slug}"),
new XElement(sitemap + "lastmod", page.PublishedDate.ToString("yyyy-MM-dd")),
new XElement(sitemap + "changefreq", "weekly"),
new XElement(sitemap + "priority", "0.8")
)
)
);
return Content(feed.ToString(), "text/xml");
}
}
Registrera vägen:
app.MapControllerRoute(
name: "sitemap",
pattern: "sitemap.xml",
defaults: new { controller = "SiteMap", action = "Index" });
robotar.txt
Berätta för sökmotorer var din webbkarta är och vad man ska gå igenom
app.MapGet("/robots.txt", async context =>
{
var siteUrl = $"https://{context.Request.Host}";
var robotsTxt = $"""
User-agent: *
Allow: /
Sitemap: {siteUrl}/sitemap.xml
""";
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync(robotsTxt);
});
RSS-flöde
Många utvecklare använder RSS-reader.
<link rel="alternate" type="application/atom+xml"
title="RSS Feed for mostlylucid.net"
href="https://mostlylucid.net/rss" />
Vad sägs om bilder?
Du kanske undrar om att generera unika OG-bilder för varje Beitrag.
- Sök på Google - beskriver är viktigare än bilder
- RSS-flöden - inga bilder
- Hacker-nyheter / Reddit - tummenailer knappt synliga
- Direkta länkar - utvecklare som delar URLs
Ett konsekvent varumärke är bra för att känna igen
Om du ville generera dem, så kunde du använda Bildform ( som jag redan använder för bildbearbeitning
public async Task<string> GenerateOgImage(string title, string slug)
{
using var image = await Image.LoadAsync("wwwroot/img/og-template.png");
var font = SystemFonts.CreateFont("Arial", 48, FontStyle.Bold);
image.Mutate(x => x.DrawText(
new RichTextOptions(font)
{
Origin = new PointF(50, 200),
WrappingLength = 1100
},
title,
Color.White));
var outputPath = $"wwwroot/og/{slug}.png";
await image.SaveAsPngAsync(outputPath);
return $"/og/{slug}.png";
}
Men för en teknisk blogg
Testa din SEO
Google Rich Results Test
Använda Googles rika resultattest att validera dina strukturerade data.
Se sidan källa
Den enklaste testen - tittar på sidans källa och kontrollerar
- Är
<meta name="description">unikt för denna sida? - Finns det en
<link rel="canonical">? - Finns det en
<script type="application/ld+json">block?
Googles sökkonsole
Efter att sätta igång, skicka din webbkarta till Googles sökkonsole. Du kan också använda URL Inspection-Toolet för att se exakt hur Google ser dina sidor och fråga om redigering
sammanfattning
Bestämningarna var enkla.
| Problemet | Fixera |
|---|---|
| Statiska metabeschreibunger | Dynamiska ViewBag.Description med automatiserad generation av innehåll |
| Inga kanoniska URLs | Hinnades <link rel="canonical"> till layout |
Inga strukturerade data BlogPosting schema på varje gång |
|
Missande artikel-metadata article:published_time, article:author, article:tag meta-tag |
|
| Statiska webbsidorsbeschreibunger | Enkela webbsidor för hemsidan, BlogM SK3 Kontakt |
Den viktigaste insikten Google kan inte läsa din tankar. Om varje sida har samma beskrivning , Google har inget sätt att veta vad som gör varje sida unik och värdefulla M SK2 Säg till Google vad varje sida handlar om , så kommer du att rankera bättre
Give it a few weeks for Google to re