Skip to content

A Complete Guide to Blog SEO — From Meta Tags to Structured Data

Mar 27, 2026 1 min
TL;DR SEO is more than keywords. Structured data (JSON-LD), Open Graph, hreflang, and robots.txt are the technical optimizations that actually help search engines understand your content. This guide walks through a complete implementation using an Astro blog as the example.
Table of Contents
  1. How Search Engines See Your Page
  2. Meta Tags: The Basics That Are Easiest to Overlook
    1. Title and Description
    2. Open Graph (Social Sharing)
    3. Automated OG Image Generation
  3. JSON-LD Structured Data
    1. Common Schema Types (as of August 2026)
    2. BreadcrumbList Example
    3. Organization (replacing the retired WebSite + SearchAction)
    4. Security Considerations
  4. Multilingual SEO: hreflang
    1. Multilingual RSS Feeds
  5. robots.txt and Sitemap
    1. robots.txt
    2. Sitemap
  6. SEO Checklist
  7. The Big Picture
  8. Changelog
  9. References

🌏 中文版

The core goal of technical SEO is simple: help search engines understand your content at the lowest possible cost. This guide uses an Astro static blog as a concrete example and walks through everything from meta tags to structured data. By the end, you'll know what each optimization does and why it matters.

How Search Engines See Your Page

Search engine crawlers (Googlebot, Bingbot, etc.) don't see your carefully designed UI — they see raw HTML. They rely on:

  1. Semantic HTML elements (<h1>, <article>, <nav>) to infer page structure
  2. Meta tags (<meta name="description">) for page summaries
  3. Structured data (JSON-LD) to precisely understand content type and attributes
  4. robots.txt / Sitemap to know what to crawl and what to skip

If your page has beautiful CSS but a messy HTML structure and missing meta information, search engines are left guessing — and they guess wrong more often than you'd expect.

Meta Tags: The Basics That Are Easiest to Overlook

Title and Description

<title>A Complete Guide to Blog SEO — quidproquo</title>
<meta name="description" content="Using an Astro blog as a practical example..." />
<link rel="canonical" href="https://quidproquo.cc/posts/tech/2026-03-27-blog-seo-optimization-guide" />
  • Title: The blue headline in Google search results — keep it under 60 characters
  • Description: The gray summary snippet in search results — keep it under 155 characters
  • Canonical: Tells search engines "this is the authoritative URL for this page," preventing duplicate content issues

In Astro, these are typically handled centrally in a Layout component:

---
// src/layouts/PostLayout.astro
interface Props {
  title: string;
  description?: string;
}
const { title, description } = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---
<head>
  <title>{title} — quidproquo</title>
  {description && <meta name="description" content={description} />}
  <link rel="canonical" href={canonicalURL} />
</head>

Open Graph (Social Sharing)

Open Graph is a meta standard originally created by Facebook. Today virtually every social platform — Twitter, LINE, Slack, Discord — supports it:

<meta property="og:title" content="A Complete Guide to Blog SEO" />
<meta property="og:description" content="Using an Astro blog as a practical example..." />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://quidproquo.cc/posts/..." />
<meta property="og:image" content="https://quidproquo.cc/og/post.png" />
<meta property="og:locale" content="en_US" />

Key point: The og:type for post pages should be article, not website. This isn't just a semantic nicety — it unlocks article-specific meta tags:

<meta property="article:published_time" content="2026-03-27T00:00:00.000Z" />
<meta property="article:author" content="xiaoxu" />
<meta property="article:tag" content="seo" />
<meta property="article:tag" content="astro" />

Automated OG Image Generation

Manually creating an OG image for every post isn't realistic. You can use Satori + Resvg to generate images automatically at build time:

// scripts/generate-og-images.mjs
import satori from 'satori';
import { Resvg } from '@resvg/resvg-js';

const svg = await satori(
  { type: 'div', props: { children: post.title, style: { fontSize: 48 } } },
  { width: 1200, height: 630, fonts: [notoSansTC] }
);

const png = new Resvg(svg).render().asPng();

1200x630 is the optimal size for social platforms.

JSON-LD Structured Data

JSON-LD is the highest priority item in technical SEO. It removes the guesswork for search engines — you're telling them directly what your content is:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "A Complete Guide to Blog SEO",
  "datePublished": "2026-03-27T00:00:00.000Z",
  "author": {
    "@type": "Person",
    "name": "xiaoxu",
    "url": "https://quidproquo.cc"
  },
  "publisher": {
    "@type": "Organization",
    "name": "quidproquo",
    "url": "https://quidproquo.cc"
  },
  "keywords": "seo, astro, structured-data"
}
</script>

Common Schema Types (as of August 2026)

Google has been steadily retiring rich result types, which means a large share of the SEO tutorials you'll find online are describing features that no longer exist. Treat the official list of supported types as the only source of truth:

SchemaUsed OnStill produces a rich result?
Article / BlogPostingPost pagesYes (Article feature)
BreadcrumbListBreadcrumb navigationYes
OrganizationSite-wide / homepageYes (logo, name, identifiers; feeds the knowledge panel)
ProfilePageAuthor pagesYes
FAQPageFAQ pagesNo — FAQ rich results stopped appearing on 2026-05-07
HowToTutorial postsNo — stopped showing back in 2023; docs removed
WebSite + SearchActionHomepageNo — the sitelinks search box was retired in October 2024

The FAQ removal played out over three years: in August 2023 Google restricted it to "well-known, authoritative government and health websites"; on 2026-05-07 it stopped appearing for those too; and the documentation came down on 2026-06-15. The dates are all in Google's documentation changelog.

So is schema without a rich result wasted effort? Not entirely. Google's generative AI optimization guide, published in May 2026, states plainly that structured data is not required for generative AI search and that there is no special schema.org markup to add — while still recommending you keep using it as part of overall SEO, because it's what makes you eligible for rich results. Treat schema as a rich-result eligibility tool, not as a way to court AI systems.

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://quidproquo.cc" },
    { "@type": "ListItem", "position": 2, "name": "tech", "item": "https://quidproquo.cc/categories/tech" },
    { "@type": "ListItem", "position": 3, "name": "A Complete Guide to Blog SEO", "item": "https://quidproquo.cc/posts/..." }
  ]
}

Organization (replacing the retired WebSite + SearchAction)

Older SEO guides tell you to put WebSite + SearchAction on your homepage to earn a sitelinks search box. Google retired that feature in October 2024, removing both the documentation and the nositelinkssearchbox rule. Marking it up today does nothing.

What your homepage should carry instead is Organization, which drives the knowledge panel and site identity:

{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "quidproquo",
  "url": "https://quidproquo.cc",
  "logo": "https://quidproquo.cc/logo.png",
  "sameAs": ["https://github.com/vincentxuu"]
}

Security Considerations

When injecting JSON-LD in Astro using set:html, guard against XSS:

<script type="application/ld+json"
  set:html={JSON.stringify(data).replace(/</g, '\\u003c')}
/>

JSON.stringify does not escape </script>. If a post title contains that string, it will break your HTML structure. The .replace(/</g, '\\u003c') pattern is the standard mitigation.

Multilingual SEO: hreflang

If your site has multiple language versions, hreflang is how you tell search engines that these pages are different language variants of the same content:

<link rel="alternate" hreflang="zh-TW" href="https://quidproquo.cc/" />
<link rel="alternate" hreflang="en" href="https://quidproquo.cc/en/" />
<link rel="alternate" hreflang="x-default" href="https://quidproquo.cc/" />
  • Every language version must include hreflang tags for all versions (including itself)
  • x-default points to the fallback language used when no language match is found
  • hreflang must be bidirectional: if A points to B, then B must also point to A

Multilingual RSS Feeds

Don't forget to create a separate RSS feed for each language:

// src/pages/en/rss.xml.ts
export async function GET(context: APIContext) {
  const posts = await getCollection('posts', ({ data }) =>
    !data.draft && data.lang === 'en'
  );
  return rss({
    title: 'quidproquo',
    description: 'Tech, climbing, surfing, coffee, and everything else.',
    site: context.site ?? 'https://quidproquo.cc',
    items: posts.map(post => ({ ... })),
    customData: '<language>en</language>',
  });
}

robots.txt and Sitemap

robots.txt

Place this in the site root to give crawlers their basic instructions:

User-agent: *
Allow: /

Sitemap: https://quidproquo.cc/sitemap-index.xml

Keep it simple. If there are pages you don't want indexed (admin panels, API endpoints), exclude them with Disallow.

Sitemap

Astro's @astrojs/sitemap integration generates a sitemap automatically. Make sure site is configured in astro.config.mjs:

export default defineConfig({
  site: 'https://quidproquo.cc',
  integrations: [sitemap()],
});

SEO Checklist

Before publishing each post, verify:

  • Has a <title> within 60 characters
  • Has <meta name="description"> within 155 characters
  • Has <link rel="canonical">
  • og:type is article (post pages) or website (homepage)
  • Has an OG image (1200x630)
  • Has JSON-LD Article / BlogPosting structured data
  • Has JSON-LD BreadcrumbList
  • Isn't spending effort on FAQPage / HowTo / SearchAction (those rich results are gone)
  • Multilingual pages have hreflang tags
  • robots.txt exists and points to the sitemap
  • Validated with Google Rich Results Test

The Big Picture

Technical SEO is a one-time investment: set it up in your Layout and build pipeline, and every future post benefits automatically. Priority order: JSON-LD structured data > Open Graph > hreflang > robots.txt. Structured data has the biggest impact because it directly determines how precisely search engines can understand your content.

You don't need to chase perfection — getting the three core schemas right (Article/BlogPosting, BreadcrumbList, Organization) already puts you ahead of 90% of personal blogs out there. Don't spend the remaining effort chasing rich result types that have already been retired; Google prunes the list every year, and the pruning is logged in the documentation changelog.


Changelog

  • 2026-08-19: Fact-checked against primary sources and refreshed; perishable details handed back to official docs. Added to the "AEO, GEO, and AI Search" series.

References