Concept
Technical SEO is the machinery layer beneath content SEO: structured data that lets search engines understand entities and relationships (not just text), sitemaps that aid discovery at scale, social preview metadata, and the crawling/indexing mechanics (redirects, canonicalization, status codes) that determine whether your intended URL is the one that actually ranks.
Structured data (JSON-LD)
Structured data is machine-readable markup describing entities on the page, a product, a recipe, an article, an FAQ, an event, using the shared schema.org vocabulary. Search engines use it to generate rich results: star ratings, price ranges, FAQ dropdowns, recipe cook times, directly in search results.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Closures in JavaScript, A Deep Dive",
"author": {
"@type": "Person",
"name": "Jane Doe"
},
"datePublished": "2026-07-12",
"dateModified": "2026-07-12",
"publisher": {
"@type": "Organization",
"name": "Frontend Mastery",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
}
}
}
</script>JSON-LD (a <script type="application/ld+json"> block) is the format Google explicitly recommends over the older Microdata/RDFa (inline attribute-based) approaches, it's separate from the visual markup, so it doesn't get tangled up with CSS classes and doesn't risk mismatching the visible content, and it's dramatically easier to generate programmatically (just serialize an object) or template into a page.
Common schema types worth knowing: Article, Product (with AggregateRating, Offer), FAQPage, HowTo, Recipe, Event, BreadcrumbList, Organization, LocalBusiness. Each has required and recommended fields defined at schema.org, validate with Google's Rich Results Test before shipping, since a single missing required field silently disqualifies the page from that rich result type.
<!-- FAQPage, commonly earns an expandable FAQ dropdown directly in search results -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [{
"@type": "Question",
"name": "What is a closure?",
"acceptedAnswer": {
"@type": "Answer",
"text": "A function bundled with its lexical environment..."
}
}]
}
</script>Open Graph and Twitter Cards
Structured data controls search engine understanding; Open Graph (originally Facebook's protocol, now the de facto standard used by Slack, Discord, iMessage, LinkedIn, and most link-preview generators) controls how a link looks when shared.
<meta property="og:title" content="Closures in JavaScript, A Deep Dive" />
<meta property="og:description" content="How closures work, common mistakes, and real React bugs they cause." />
<meta property="og:image" content="https://example.com/og/closures.png" />
<meta property="og:url" content="https://example.com/topic/javascript.closures" />
<meta property="og:type" content="article" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title"
og:image should point to a dedicated share-card image, ideally 1200×630px (the widely-adopted safe size across platforms), not a random content image that happens to exist on the page. Missing or wrong OG tags are why links sometimes preview as a blank card or the wrong image when shared in Slack/Twitter/iMessage; verify with Facebook's Sharing Debugger or Twitter Card Validator (both also force a cache refresh, since these previews are aggressively cached by the platforms).
Sitemaps
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/topic/javascript.closures</loc>
<lastmod>2026-07-12</lastmod>
<changefreq>monthly</changefreq>
</url>
</urlset>A sitemap is a machine-readable index of URLs you want crawled, helps discovery at scale (especially for large sites, or pages with few internal links pointing to them) and communicates lastmod so crawlers can prioritize re-crawling changed content. It doesn't guarantee indexing (that's determined by content quality/uniqueness/policy), only aids discovery. Reference it from robots.txt (Sitemap: https://example.com/sitemap.xml) and submit it directly in Google Search Console. Next.js apps typically generate this via a sitemap.ts/sitemap.xml route handler that queries the same data source as the pages themselves, so it can't drift out of sync.
Redirects and status codes: the SEO-relevant subset
- 301 (permanent redirect), passes the vast majority of ranking signal to the new URL. Use for permanent URL changes (renamed slugs, domain migrations).
- 302 (temporary redirect), signals the original URL should remain the canonical/indexed one. Using 302 for a permanent change is a common mistake that leaves ranking signal stranded on the old URL.
- 404, correct for genuinely removed content with no replacement. A "soft 404" (page returns 200 OK but displays "not found" content) confuses crawlers into indexing an empty/error page as if it were real content, always verify your custom error pages return the actual matching HTTP status.
- 410 (gone), stronger signal than 404 that content was intentionally, permanently removed (vs. possibly a temporary/broken link), treated more aggressively for deindexing.
Canonicalization at scale
<link rel="canonical" href="https://example.com/products/widget" />Needed whenever the same content is reachable at multiple URLs, ?utm_source=... tracking params, ?sort=price filtered variants of a listing, www. vs. non-www., trailing slash vs. not, http vs. https. Without canonicalization, search engines may split ranking signal across duplicate URLs instead of consolidating it onto one, or pick the "wrong" one (e.g. the tracking-param version) as canonical themselves.
hreflang for internationalized sites
<link rel="alternate" hreflang="en-US" href="https://example.com/en/" />
<link rel="alternate" hreflang="es-ES" href="https://example.com/es/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />Tells search engines which language/region variant to show to which searchers, and prevents translated pages from being flagged as duplicate content of each other.
Common Mistakes
1. Missing required schema.org fields, silently disqualifying rich results
Structured data with a typo'd field name or a missing required property (e.g. Product without a price inside Offer) doesn't throw a visible error, the page simply never earns the rich result, with no warning in normal usage. Always validate with the Rich Results Test after any change to structured data templates.
2. og:image pointing to a broken or wrong-sized image
A missing or incorrectly-sized og:image produces a blank or cropped share card, one of the most visible, embarrassing SEO/marketing bugs since it's directly user-facing every time a link is shared. Verify with the actual platform debugger tools (they bypass cache), not just by eyeballing the meta tag.
3. Using 302 for permanent redirects
Silently strands ranking signal on the old URL instead of transferring it, the new URL never fully inherits the old page's search equity.
4. Soft 404s
A "Page Not Found" message rendered with a 200 OK status code. Crawlers treat it as real, indexable content rather than recognizing it as an error, sometimes indexing thousands of generic error pages as if they were unique content, actively harmful, not just wasted opportunity.
5. Sitemap and robots.txt drifting out of sync with reality
A sitemap listing URLs that 404, or robots.txt disallowing paths that are still linked in the sitemap, sends contradictory signals. Generate the sitemap from the same source of truth as routing/content, not maintained by hand.
6. Duplicate/conflicting canonical tags
<!-- Wrong: self-referencing AND pointing elsewhere -->
<link rel="canonical" href="https://example.com/page-a" />
<link rel="canonical" href="https://example.com/page-b" />Multiple or conflicting canonical tags on one page are ignored or resolved unpredictably by search engines, exactly one canonical URL per page.
Best Practices
- Use JSON-LD for structured data, validated with the Rich Results Test as part of your review process for any template change.
- Generate sitemaps and canonical URLs programmatically from the same routing/data source as the actual pages, so they can't silently drift out of sync.
- Dedicated 1200×630px
og:imageper page (or a sensible template-generated default), verified with platform debugger tools. - 301 for permanent URL changes, 302 only for genuinely temporary ones.
- Verify custom error pages return real 404/410 status codes, not 200 with error content.
- Treat
robots.txt, sitemap, and canonical tags as part of your deploy verification, not a set-and-forget config.
Further Resources
- schema.org, the shared vocabulary for structured data.
- Google Search Central, Structured data markup
- Google Rich Results Test, validate structured data.
- The Open Graph protocol, official spec.
- Google Search Central, Sitemaps
- Google Search Central, Redirects and Google Search
