# Varför du inte hittade det här på Google?

<!--category-- ASP.NET Core, SEO -->
<datetime class="hidden">2025-11-26T14:00</datetime>

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.

[TOC]

# 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

```html
<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](/blog/background-services-in-aspnetcore-part1)? Samma beskrivning som min hemsida. Min djupdykning in [RAG arkitektur](/blog/rag-architecture)? 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](https://developers.google.com/search/docs/appearance/structured-data/article). 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

```html
@{
    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`:

```html
@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:

1. **Spräng vid ordgränsen** - Vi hittar det sista utrymmet innan 155-tecknen för att undvika att skära ihop ord
2. **Strippa nya linjer** - Metabeschreibunger borde vara ensamma
3. **Bestämda `og:type` till "articleM SK1** - säger till sociala plattformar att det här är en artikel , inte en generisk webbsida
4. **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.

```html
<!-- 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.

```html
<!-- 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

```csharp
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:

```csharp
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

```csharp
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.

```html
<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](https://docs.sixlabors.com/articles/imagesharp/) ( som jag redan använder för bildbearbeitning

```csharp
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](https://search.google.com/test/rich-results) 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](https://search.google.com/search-console). 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

# Fortsättning avläsning

- [Google's SEO Starter Guide](https://developers.google.com/search/docs/fundamentals/seo-starter-guide)
- [Schema.org bloggar](https://schema.org/BlogPosting)
- [Open Graph Protokoll](https://ogp.me/)
- [Google Rich Results Test](https://search.google.com/test/rich-results)
- [Googles sökkonsole](https://search.google.com/search-console)