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
Warum Sie das nicht auf Google gefunden haben (und wie ich es behoben habe)
Wednesday, 26 November 2025
Ich habe diesen Blog für eine Weile laufen, schreiben detaillierte technische Artikel auf ASP.NET Core, Entity Framework, HTMX, und alle Arten von .NET Güte. Doch meine Such-Rankings waren... Underwhelming. Nachdem ich schließlich untersucht, warum, Ich entdeckte, dass ich sabotiert meine eigenen SEO mit einigen Rookie-Fehler. Hier ist, was falsch war und wie ich es behoben.
Das Problem: Jede Seite sah Identisch zu Google
Wenn Google krabbelt Ihre Website , es schaut auf mehrere Schlüsselsignale zu verstehen, was jede Seite ist . Ich war das Senden von Google die gleichen Signale für jede einzelne Seite .
Die Rauchpistole: Statische Meta-Beschreibungen
Hier ist, was meine _Layout.cshtml sah aus wie:
<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.">
Jeder. Single. Seite. Die gleiche Beschreibung. Mein Artikel über Hintergrunddienste im ASP.NET Core? Gleiche Beschreibung wie meine Homepage. RAG-Architektur? Dieselbe Beschreibung.
Google sieht 200+ Seiten mit identischen Beschreibungen und denkt, "diese Website hat doppelte Inhalte Probleme" oder "diese Website kümmert sich nicht um die Bereitstellung nützlicher Informationen." So oder so, Rankings leiden.
Fehlende kanonischen URLs
Ich habe einen mehrsprachigen Blog mit Übersetzungen. Der gleiche Inhalt existiert bei:
/blog/my-article(Englisch)/blog/my-article/fr(Französisch)/blog/my-article/de(Deutsch)
Ohne kanonische URLs , Google könnte diese als doppelte Inhalte sehen , Verdünnen der SEO-Wert über mehrere URLs, anstatt sie auf der primären Seite zu konsolidieren .
Keine strukturierten Daten
Googles Suchergebnisse können Rich Snippets zeigen - Autor Informationen, veröffentlichen Daten, Artikel Vorschauen. Aber nur, wenn Sie Google über diese Daten mit JSON-LD strukturierte DatenDas war ich nicht.
Statische soziale Bilder
Jede Seite hat das gleiche geteilt og:image. Während dies nicht direkt Google-Rankings beeinflussen, es Auswirkungen Klick-durch-Raten, wenn Artikel auf Social Media geteilt werden - die indirekt SEO durch Engagement-Signale beeinflusst.
Die Korrekturen
1. Dynamische Meta-Beschreibungen
Der erste Fix war die Erstellung der Layout-Unterstützung dynamische Beschreibungen mit einem sinnvollen 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" />
}
}
Jetzt liest sich das Layout ViewBag.Description wenn gesetzt, fällt auf eine Standardeinstellung zurück. Die kanonische URL wird automatisch auf die aktuelle Seiten-URL gesetzt.
2. Auto-generierte Beschreibungen für Blog-Posts
Jeder Blog-Post erzeugt nun seine Beschreibung aus den ersten 155 Zeichen des Inhalts. 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}";
}
Die wichtigsten Punkte hier:
- An der Wortgrenze abschneiden - Wir finden den letzten Platz vor 155 Zeichen, um das Schneiden von Wörtern in der Hälfte zu vermeiden
- Neue Linien abstreifen - Meta-Beschreibungen sollten einzeilig sein
- Satz
og:typezu "Artikel" - Sagt sozialen Plattformen Dies ist ein Artikel, nicht eine generische Webseite - Artikel-Metadaten übergeben - Veröffentlichtes Datum und Kategorien fließen durch das Layout
3. JSON-LD Strukturierte Daten
Dies ist die große für reiche Schnipsel. Fügen Sie einen JSON-LD-Skriptblock zu Ihrer Blog-Post-Ansicht hinzu:
<!-- 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>
Bemerken Sie die @@ die Flucht nach der @ Symbol in Razor-Ansichten - JSON-LD verwendet @context und @type die sonst als Razor-Syntax interpretiert würde.
Diese strukturierten Daten sagt Google:
- Welche Art von Inhalten das ist (Blogposting)
- Wer hat es geschrieben? (Person mit einer URL, um mehr zu erfahren)
- Als es veröffentlicht und geändert wurde
- Welche Themen es behandelt (Stichworte aus Kategorien)
- Wie lange ist es? (Wortzählen)
- Was für eine Sprache ist das?
Google kann dies verwenden, um reiche Schnipsel in Suchergebnissen zu zeigen, einschließlich Autoreninformationen, Veröffentlichung von Daten, und vieles mehr.
4. Einzigartige Beschreibungen für Schlüsselseiten
Vergessen Sie nicht Ihre statischen Seiten. Jeder sollte eine einzigartige, relevante Beschreibung haben:
<!-- 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.";
}
Sonstige SEO-Grundlagen
Seiten
Sie benötigen eine Sitemap. Hier ist eine einfache Steuerung, die dynamisch erzeugt:
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");
}
}
Registrieren Sie die Route:
app.MapControllerRoute(
name: "sitemap",
pattern: "sitemap.xml",
defaults: new { controller = "SiteMap", action = "Index" });
robots.txt
Sagen Sie Suchmaschinen, wo Ihre Sitemap ist und was zu kriechen:
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-Feed
Viele Entwickler verwenden RSS-Reader. Mit einem RSS-Feed hilft auch bei der Auffindbarkeit:
<link rel="alternate" type="application/atom+xml"
title="RSS Feed for mostlylucid.net"
href="https://mostlylucid.net/rss" />
Was ist mit Bildern?
Vielleicht fragen Sie sich, wie Sie einzigartige OG-Bilder für jeden Beitrag. Für einen technischen Blog, es ist wahrscheinlich nicht die Mühe wert. Ihr Verkehr kommt aus:
- Google-Suche - Beschreibungen sind wichtiger als Bilder
- RSS-Feeds - keine Bilder
- Hacker Nachrichten / Reddit - Vorschaubilder kaum sichtbar
- Direkte Verbindungen - Entwickler teilen URLs
Ein konsequentes Markenbild ist gut für die Wiedererkennung. Kundenspezifische Bildgenerierung zählt mehr für visuelle Inhalte, News-Websites oder Marketing-Seiten, die um Klicks auf Facebook und Twitter konkurrieren.
Wenn du sie erzeugen wolltest, könntest du sie benutzen. ImageSharp (die ich bereits für die Bildverarbeitung verwende) um Text auf einer Vorlage zu überlagern:
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";
}
Aber für einen technischen Blog? Schiff, was du hast.
Testen Sie Ihre SEO
Google Rich Ergebnisse Test
Verwendung Googles Rich Results Test um Ihre strukturierten Daten zu validieren. Fügen Sie eine URL ein und es wird Ihnen sagen, ob Ihre JSON-LD gültig ist und für welche reichen Ergebnisse Sie in Frage kommen.
Seitenquelle anzeigen
Der einfachste Test - Ansicht der Seitenquelle und überprüfen:
- Ist die
<meta name="description">einzigartig für diese Seite? - Gibt es eine
<link rel="canonical">? - Gibt es eine
<script type="application/ld+json">Blockieren?
Google-Konsole durchsuchen
Geben Sie nach der Bereitstellung Ihre Sitemap an Google-Konsole durchsuchen. Sie können auch das URL Inspection Tool verwenden, um genau zu sehen, wie Google Ihre Seiten sieht und Re-Indexierung anfordert.
Zusammenfassung
Die Korrekturen waren einfach:
Problembehebung
|---------|-----|
Statische Meta-Beschreibungen, dynamisch ViewBag.Description mit automatischer Generierung von Inhalten
Keine kanonischen URLs hinzugefügt <link rel="canonical"> zum Layout
Keine strukturierten Daten. JSON-LD BlogPosting Schema auf jedem Beitrag
Fehlende Artikel-Metadaten article:published_time, article:author, article:tag Meta-Tags
• Statische Seitenbeschreibungen • Einzigartige Beschreibungen für Zuhause, Blog, Kontakt, Suchseiten •
Die wichtigsten Erkenntnisse: Google kann Ihre Gedanken nicht lesen. Wenn jede Seite hat die gleiche Beschreibung , Google hat keine Möglichkeit zu wissen, was macht jede Seite einzigartig und wertvoll . Sagen Sie Google, was jede Seite ist , und Sie werden besser rangieren .
Geben Sie es ein paar Wochen für Google zu re-crawl Ihre Website, und Sie sollten Verbesserungen sehen. SEO ist ein langes Spiel, aber diese Grundlagen sind die Grundlage alles andere baut auf.