Γιατί δεν το βρήκες αυτό στο Google (Και πώς το έφτιαξα) (ελληνικά (Greek))

Γιατί δεν το βρήκες αυτό στο Google (Και πώς το έφτιαξα)

Wednesday, 26 November 2025

//

10 minute read

Έχω τρέξει αυτό το blog για λίγο καιρό τώρα, γράφοντας λεπτομερή τεχνικά άρθρα για το ASP.NET Core, Πλαίσιο οντότητας, HTMX, και όλα τα είδη της καλοσύνης .NET. Ωστόσο, η κατάταξη αναζήτησής μου ήταν... underwhelming. Μετά από επιτέλους έρευνα γιατί, ανακάλυψα ότι είχα σαμποτάρει το δικό μου SEO με κάποια λάθη νεοσύλλεκτων.

Το πρόβλημα: Κάθε σελίδα έψαχνε identical στο Google

Όταν η Google σέρνεται στο site σας, κοιτάζει αρκετά βασικά σήματα για να καταλάβει τι είναι κάθε σελίδα.

Το Κάπνισμα Όπλο: Static Meta Περιγραφή

Άκου τι θα κάνω _Layout.cshtml Έμοιαζε με:

<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.">

Κάθε μία, σελίδα, η ίδια περιγραφή. Background Services in ASP.NET CoreΤην ίδια περιγραφή με την αρχική μου σελίδα. RAG Αρχιτεκτονική♪ Ίδια περιγραφή. ♪

Η Google βλέπει 200+ σελίδες με πανομοιότυπες περιγραφές και σκέφτεται "αυτή η ιστοσελίδα έχει αντίγραφα θεμάτων περιεχομένου" ή "αυτή η ιστοσελίδα δεν ενδιαφέρεται για την παροχή χρήσιμων πληροφοριών."

Λείπει η Κανονική URL

Έχω ένα πολύγλωσσο blog με μεταφράσεις. Το ίδιο περιεχόμενο υπάρχει σε:

  • /blog/my-article (Αγγλικά)
  • /blog/my-article/fr (Γαλλικά)
  • /blog/my-article/de (Γερμανικά)

Χωρίς κανονικά URL, η Google μπορεί να τα δει ως διπλό περιεχόμενο, διαλύοντας την τιμή SEO σε πολλαπλά URL αντί να την εδραιώσει στην αρχική σελίδα.

Κανένα δομημένο στοιχείο

Τα αποτελέσματα αναζήτησης της Google μπορούν να δείξουν πλούσια snippets - πληροφορίες συγγραφέα, να δημοσιεύσουν ημερομηνίες, προεπισκοπήσεις άρθρου. Δομημένα δεδομένα JSON-LD- Δεν ήμουν.

Στατικές κοινωνικές εικόνες

Κάθε σελίδα μοιράζεται το ίδιο og:image. Ενώ αυτό δεν επηρεάζει άμεσα τις κατατάξεις της Google, επηρεάζει τα ποσοστά κλικ-μέσω όταν τα άρθρα μοιράζονται στα μέσα κοινωνικής δικτύωσης - τα οποία επηρεάζουν έμμεσα SEO μέσω σημάτων εμπλοκής.

Η Διόρθωσις

1. Δυναμικές περιγραφές Meta

Η πρώτη διόρθωση ήταν κάνοντας τη διάταξη υποστήριξη δυναμική περιγραφές με μια λογική οπισθοδρόμηση:

@{
    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" />
    }
}

Τώρα η διάταξη διαβάζει ViewBag.Description Το κανονικό URL ορίζεται αυτόματα στην τρέχουσα URL σελίδα.

2. Auto-Generated Περιγραφές για τα Blog Posts

Κάθε δημοσίευση blog παράγει τώρα την περιγραφή του από τους πρώτους 155 χαρακτήρες του περιεχομένου. 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}";
}

Τα βασικά σημεία εδώ:

  1. Πηγαίνετε στο όριο λέξεων - Βρίσκουμε τον τελευταίο χώρο πριν 155 χαρακτήρες για να αποφύγουμε να κόψουμε λέξεις στη μέση
  2. Στριπτιτζάδικα newlines - Μετα περιγραφές θα πρέπει να είναι ενιαία γραμμή
  3. Σετ og:type Στο "εμβόλιο" - Λέει κοινωνικές πλατφόρμες αυτό είναι ένα άρθρο, όχι μια γενική ιστοσελίδα
  4. Περάστε τα μεταδεδομένα άρθρου - Δημοσιευμένη ημερομηνία και κατηγορίες ροή μέσω της διάταξης

3. JSON-LD Δομημένα δεδομένα

Αυτό είναι το μεγάλο για πλούσια snippets. Προσθέστε ένα μπλοκ σεναρίου JSON-LD στο blog σας post view:

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

Σημειώστε το @@ απόδραση για το @ σύμβολο στις απόψεις Razor - JSON-LD χρησιμοποιεί @context και @type που διαφορετικά θα ερμηνευόταν ως σύνταξη Razor.

Αυτό το δομημένο στοιχείο λέει στο Google:

  • Τι είδους περιεχόμενο είναι αυτό; (BlogPosting)
  • Ποιος το έγραψε; (Person with a URL to learn more)
  • Όταν δημοσιεύθηκε και τροποποιήθηκε
  • Τι θέματα καλύπτει (κλειδιά από κατηγορίες)
  • Πόσος καιρός είναι (λέξη Count)
  • Σε τι γλώσσα είναι.

Η Google μπορεί να χρησιμοποιήσει αυτό για να δείξει πλούσια snippets στα αποτελέσματα αναζήτησης, συμπεριλαμβανομένων των πληροφοριών συγγραφέα, να δημοσιεύσει ημερομηνίες, και πολλά άλλα.

4. Μοναδικές περιγραφές για τις βασικές σελίδες

Μην ξεχάσετε τις στατικές σας σελίδες. Κάθε μία θα πρέπει να έχει μια μοναδική, σχετική περιγραφή:

<!-- 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.";
}

Άλλα Απαραίτητα SEO

SitemapName

Εδώ είναι ένα απλό χειριστήριο που παράγει ένα δυναμικά:

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");
    }
}

Καταχωρήστε τη διαδρομή:

app.MapControllerRoute(
    name: "sitemap",
    pattern: "sitemap.xml",
    defaults: new { controller = "SiteMap", action = "Index" });

ρομπότ. txt

Πείτε τις μηχανές αναζήτησης όπου το sitemap σας είναι και τι να συρθεί:

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

Πολλοί προγραμματιστές χρησιμοποιούν RSS αναγνώστες. Έχοντας μια τροφοδοσία RSS βοηθά επίσης στην ανακάλυψη:

<link rel="alternate" type="application/atom+xml"
      title="RSS Feed for mostlylucid.net"
      href="https://mostlylucid.net/rss" />

Τι θα Λεχθή για τις Εικόνες;

Μπορεί να αναρωτιέστε για τη δημιουργία μοναδικών εικόνων OG για κάθε δημοσίευση. Για ένα τεχνικό blog, πιθανότατα δεν αξίζει τον κόπο.

  • Αναζήτηση Google - οι περιγραφές έχουν μεγαλύτερη σημασία από τις εικόνες
  • Τροφές RSS - χωρίς εικόνες
  • Hacker News / Reddit - μικρογραφίες ίσα που φαίνονται
  • Απευθείας σύνδεσμοι - προγραμματιστές μοιράζονται URLs

Μια συνεπής επώνυμη εικόνα είναι καλό για την αναγνώριση. Προσαρμοσμένη παραγωγή εικόνας θέματα περισσότερο για το οπτικό περιεχόμενο, ιστοσελίδες ειδήσεων, ή σελίδες μάρκετινγκ που ανταγωνίζονται για κλικ στο Facebook και το Twitter.

Αν ήθελες να τα δημιουργήσεις, θα μπορούσες να χρησιμοποιήσεις ImageSharp (την οποία ήδη χρησιμοποιώ για επεξεργασία εικόνας) για την επικάλυψη κειμένου σε ένα πρότυπο:

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";
}

Αλλά για ένα τεχνικό μπλογκ;

Δοκιμή SEO σας

Δοκιμή πλούσιων αποτελεσμάτων της GoogleName

Χρήση The Google's Rich Results Test για την επικύρωση των δομημένων δεδομένων σας. Επικόλληση URL και θα σας πει αν JSON-LD σας είναι έγκυρη και ποια πλούσια αποτελέσματα είστε επιλέξιμοι για.

Προβολή πηγής σελίδας

Η απλούστερη δοκιμή - δείτε την πηγή της σελίδας και ελέγξτε:

  • Είναι η <meta name="description"> Μοναδικό για αυτή τη σελίδα;
  • Υπάρχει κάποια <link rel="canonical">?
  • Υπάρχει κάποια <script type="application/ld+json"> Μπλόκαρε;

Κονσόλα αναζήτησης GoogleName

Μετά την ανάπτυξη, υποβάλλει sitemap σας σε Κονσόλα αναζήτησης GoogleName. Μπορείτε επίσης να χρησιμοποιήσετε το εργαλείο επιθεώρησης URL για να δείτε ακριβώς πώς η Google βλέπει τις σελίδες σας και να ζητήσει εκ νέου-δείκτη.

Περίληψη

Οι διορθώσεις ήταν σαφείς:

Πρόβλημα Φτιάξε |---------|-----| Στατική μετα-περιγραφές Δυναμική ViewBag.Description Αυτόματη παραγωγή από το περιεχόμενο Δεν έχει προστεθεί κανονική URL <link rel="canonical"> στη διάταξη □ Δεν υπάρχουν δομημένα δεδομένα JSON-LD BlogPosting schema σε κάθε θέση Λείπει τα μεταδεδομένα του άρθρου article:published_time, article:author, article:tag meta tags Περιγραφή Στατικής σελίδας Περιγραφή: Μοναδικές περιγραφές για το Σπίτι, Blog, Επικοινωνία, Αναζήτηση σελίδων

Η βασική διορατικότητα: Η Google δεν μπορεί να διαβάσει το μυαλό σου. Εάν κάθε σελίδα έχει την ίδια περιγραφή, η Google δεν έχει κανένα τρόπο να ξέρει τι κάνει κάθε σελίδα μοναδική και πολύτιμη. Πείτε στο Google τι κάθε σελίδα είναι περίπου, και θα βαθμολογήσετε καλύτερα.

Δώστε του μερικές εβδομάδες για το Google να ξανασυντρίψει το site σας, και θα πρέπει να δείτε βελτιώσεις. SEO είναι ένα μεγάλο παιχνίδι, αλλά αυτά τα βασικά είναι το θεμέλιο όλα τα άλλα βασίζεται σε.

Περαιτέρω Ανάγνωση

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.