SEO & AI Engine Optimization Framework · May 2026

Schema.org & Structured Data: JSON-LD, @id graphs, sameAs networks

A comprehensive installation and audit reference for structured data — the machine-readable layer that tells Google, AI crawlers, and other consumers what entities a page is about and how they…

JSON-LD Implementation, the @id Graph Pattern, Per-Page Type Selection, and Validation

A comprehensive installation and audit reference for structured data — the machine-readable layer that tells Google, AI crawlers, and other consumers what entities a page is about and how they relate. Every meaningful SERP feature, AI citation, and Knowledge Panel claim depends on this layer being correct. Dual-purpose: installation manual and audit document.

Cross-stack implementation note: the code samples in this framework are written in plain HTML for clarity. For React, Vue, Svelte, Next.js, Nuxt, SvelteKit, Astro, Hugo, 11ty, Remix, WordPress, Shopify, and Webflow equivalents of every pattern below, see framework-cross-stack-implementation.md. For pure client-rendered SPAs (no SSR/SSG) see framework-react.md. For Tailwind-specific concerns (purge, dynamic classes, dark-mode CLS, focus accessibility) see framework-tailwind.md.


1. Document Purpose

This is the canonical reference for schema.org structured data implementation. Schema is no longer optional in 2026 — it is the foundation that lets Google's Knowledge Graph populate, AI search engines extract claims, and SERP rich results render. A site without proper structured data is invisible to half of modern search.

Schema in 2026 differs from schema in 2020 in three critical ways. First, the @id graph pattern (cross-referenced nodes within a single @graph block) has overtaken the older "one schema block per page" approach because it lets entities reference each other across the site. Second, AI search engines (ChatGPT, Perplexity, Claude, Gemini) rely on schema as a primary signal for entity extraction — accurate schema increases citation likelihood. Third, validation is non-negotiable: invalid schema is worse than no schema, because Google penalizes spam markup.

1.1 Required Tools

1.2 Document Scope

Covers: schema formats, @id graph pattern, the major schema types every site needs, type-specific implementation per content type, validation methodology, sameAs networks, and common pitfalls. Touches but does not exhaust: Knowledge Graph claiming (own framework: framework-knowledgegraph.md), AI citation mechanics (framework-aicitations.md), Local SEO schema (framework-localseo.md).


2. Client Variables Intake

business_type: ""                      # local | ecommerce | publisher | b2b_service | sdvosb
primary_entity: ""                     # Organization name
person_entity: ""                      # Founder/author Person if relevant
website_domain: ""
local_business_subtype: ""             # Restaurant | Plumber | Dentist | etc. — only if local
ecommerce_product_count: 0
existing_schema_present: false
existing_schema_format: ""             # JSON-LD | Microdata | RDFa
existing_schema_validated: false
wikidata_qid_org: ""                   # if claimed
wikidata_qid_person: ""                # if claimed
sameas_targets: []                     # LinkedIn, GitHub, Wikidata, Wikipedia, etc.
known_schema_errors: []

3. Schema Format Decision

Three formats are valid. Pick one and stick with it.

Format Recommendation Why
JSON-LD Use this. Decoupled from rendered HTML; survives template changes; preferred by Google; trivial to maintain.
Microdata Avoid for new builds Inline HTML attributes; brittle; tied to template structure.
RDFa Avoid for new builds Similar drawbacks to Microdata; less common.

JSON-LD lives in a <script type="application/ld+json"> block in the document head (or anywhere in the body — head is conventional). It does not need to mirror the visible HTML.


4. The @id Graph Pattern

This is the single most important pattern in modern schema implementation. Older sites declared one schema block per type per page, with no cross-references. The graph pattern declares all entities in one @graph block with cross-referenced @id URIs, letting Google reconstruct the entity relationships.

4.1 Anatomy of a Graph

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": ["Organization", "ProfessionalService", "LocalBusiness"],
      "@id": "https://example.com/#organization",
      "name": "Example Co",
      "url": "https://example.com/",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q12345",
        "https://www.linkedin.com/company/example",
        "https://github.com/example"
      ],
      "founder": { "@id": "https://example.com/#founder" }
    },
    {
      "@type": "Person",
      "@id": "https://example.com/#founder",
      "name": "Joseph W. Anady",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139592630",
        "https://www.linkedin.com/in/josephanady"
      ],
      "worksFor": { "@id": "https://example.com/#organization" },
      "knowsAbout": ["Technical SEO", "AI search optimization"]
    },
    {
      "@type": "WebSite",
      "@id": "https://example.com/#website",
      "url": "https://example.com/",
      "name": "Example Co",
      "publisher": { "@id": "https://example.com/#organization" }
    },
    {
      "@type": "WebPage",
      "@id": "https://example.com/about/#webpage",
      "url": "https://example.com/about/",
      "name": "About — Example Co",
      "isPartOf": { "@id": "https://example.com/#website" },
      "about": { "@id": "https://example.com/#organization" }
    }
  ]
}
</script>

4.2 The @id Convention

@id values are URIs. Use absolute URLs with a fragment identifier (#) to disambiguate entities on the same page:

The @id does NOT need to resolve to a real URL. It is just a unique identifier within the graph.

4.3 Cross-Page Consistency

Every page on the site declares the same Organization, WebSite, and Person entities (with the same @id URIs). Page-specific entities (WebPage, Article, Service, Product) reference back via @id:

{
  "@type": "Article",
  "@id": "https://example.com/blog/post/#article",
  "headline": "Post Title",
  "author": { "@id": "https://example.com/#founder" },
  "publisher": { "@id": "https://example.com/#organization" },
  "isPartOf": { "@id": "https://example.com/blog/post/#webpage" }
}

This cross-referencing is what gives Google's Knowledge Graph the connectivity it needs to attribute Articles to Authors, Authors to Organizations, and Organizations to Knowledge Panel entries.


5. The Foundation Schemas

Every meaningful site needs these. Implement them sitewide before any page-specific schema.

5.1 Organization

Required for every site. If the business has a physical location, extend with LocalBusiness; if it serves a profession, extend with ProfessionalService.

{
  "@type": ["Organization", "ProfessionalService", "LocalBusiness"],
  "@id": "https://example.com/#organization",
  "name": "Example Co",
  "alternateName": ["example.com", "Example"],
  "url": "https://example.com/",
  "logo": {
    "@type": "ImageObject",
    "url": "https://example.com/logo.png",
    "width": 600,
    "height": 600
  },
  "image": "https://example.com/og-default.png",
  "description": "Plain-English description matching the site's actual purpose.",
  "telephone": "+1-505-512-3662",
  "email": "hello@example.com",
  "priceRange": "$597-$11997",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "123 Main St",
    "addressLocality": "Cassville",
    "addressRegion": "MO",
    "postalCode": "65625",
    "addressCountry": "US"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": 36.6811,
    "longitude": -93.8702
  },
  "areaServed": [
    { "@type": "AdministrativeArea", "name": "Northwest Arkansas" },
    { "@type": "AdministrativeArea", "name": "Southwest Missouri" }
  ],
  "founder": { "@id": "https://example.com/#founder" },
  "foundingDate": "2017-01-01",
  "sameAs": [
    "https://www.wikidata.org/wiki/Q139592631",
    "https://www.linkedin.com/company/example",
    "https://github.com/example"
  ]
}

5.2 Person

For owner-operated businesses, sole-proprietor agencies, and any site with named editorial authors. Critical for E-E-A-T.

{
  "@type": "Person",
  "@id": "https://example.com/#founder",
  "name": "Joseph W. Anady",
  "givenName": "Joseph",
  "additionalName": "W.",
  "familyName": "Anady",
  "jobTitle": "Founder",
  "worksFor": { "@id": "https://example.com/#organization" },
  "image": "https://example.com/joseph.jpg",
  "url": "https://example.com/about/",
  "knowsAbout": [
    "Technical SEO", "Local SEO", "AI search optimization",
    "Schema markup", "SDVOSB digital marketing"
  ],
  "knowsLanguage": ["English"],
  "alumniOf": "U.S. Army",
  "sameAs": [
    "https://www.wikidata.org/wiki/Q139592630",
    "https://www.linkedin.com/in/josephanady",
    "https://github.com/josephanady"
  ]
}

Cross-reference: framework-eeat.md for Person schema's role in expertise signals; framework-knowledgegraph.md for sameAs network construction.

5.3 WebSite

Declares the site itself as an entity. Enables sitelinks search box.

{
  "@type": "WebSite",
  "@id": "https://example.com/#website",
  "url": "https://example.com/",
  "name": "Example Co",
  "publisher": { "@id": "https://example.com/#organization" },
  "inLanguage": "en-US",
  "potentialAction": {
    "@type": "SearchAction",
    "target": {
      "@type": "EntryPoint",
      "urlTemplate": "https://example.com/search?q={search_term_string}"
    },
    "query-input": "required name=search_term_string"
  }
}

5.4 WebPage (per-page)

Every page declares itself as a WebPage. Subtypes when applicable: AboutPage, ContactPage, FAQPage, CollectionPage.

{
  "@type": "WebPage",
  "@id": "https://example.com/about/#webpage",
  "url": "https://example.com/about/",
  "name": "About — Example Co",
  "description": "About page meta description.",
  "isPartOf": { "@id": "https://example.com/#website" },
  "about": { "@id": "https://example.com/#organization" },
  "primaryImageOfPage": {
    "@type": "ImageObject",
    "url": "https://example.com/about-hero.jpg"
  },
  "datePublished": "2026-01-15",
  "dateModified": "2026-05-05",
  "breadcrumb": { "@id": "https://example.com/about/#breadcrumb" }
}

5.5 BreadcrumbList

For every non-homepage. Drives breadcrumb display in SERPs.

{
  "@type": "BreadcrumbList",
  "@id": "https://example.com/about/#breadcrumb",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://example.com/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "About",
      "item": "https://example.com/about/"
    }
  ]
}

6. Per-Content-Type Schemas

6.1 Article (blog post, news story, editorial)

Use Article, NewsArticle, BlogPosting, or TechArticle depending on content. Article is the safe default.

{
  "@type": "Article",
  "@id": "https://example.com/blog/post-slug/#article",
  "headline": "Post headline (under 110 characters)",
  "description": "Meta description.",
  "image": [
    "https://example.com/post-image-1x1.jpg",
    "https://example.com/post-image-4x3.jpg",
    "https://example.com/post-image-16x9.jpg"
  ],
  "author": { "@id": "https://example.com/#founder" },
  "publisher": { "@id": "https://example.com/#organization" },
  "datePublished": "2026-04-15T10:00:00-05:00",
  "dateModified": "2026-05-05T14:30:00-05:00",
  "mainEntityOfPage": { "@id": "https://example.com/blog/post-slug/#webpage" },
  "wordCount": 2500,
  "articleBody": "First 200 characters of body, optional but improves AI extraction.",
  "keywords": ["technical seo", "schema", "json-ld"]
}

Image best practice: provide three images at three aspect ratios (1x1, 4x3, 16x9). Google selects the best fit per surface.

6.2 Service

For service-based businesses describing what they offer.

{
  "@type": "Service",
  "@id": "https://example.com/services/local-seo/#service",
  "name": "Local SEO for Northwest Arkansas",
  "description": "Description of the service offered.",
  "provider": { "@id": "https://example.com/#organization" },
  "serviceType": "Local SEO",
  "areaServed": [
    { "@type": "AdministrativeArea", "name": "Northwest Arkansas" }
  ],
  "hasOfferCatalog": {
    "@type": "OfferCatalog",
    "name": "Local SEO Services",
    "itemListElement": [
      {
        "@type": "Offer",
        "itemOffered": {
          "@type": "Service",
          "name": "Google Business Profile setup"
        },
        "price": "597",
        "priceCurrency": "USD"
      }
    ]
  }
}

6.3 Product (ecommerce)

Cross-reference: framework-ecommerceseo.md for full product schema depth.

{
  "@type": "Product",
  "@id": "https://example.com/products/sku-123/#product",
  "name": "Product Name",
  "description": "Product description.",
  "image": ["https://example.com/product.jpg"],
  "sku": "SKU-123",
  "gtin13": "1234567890123",
  "brand": { "@type": "Brand", "name": "Brand Name" },
  "offers": {
    "@type": "Offer",
    "url": "https://example.com/products/sku-123/",
    "priceCurrency": "USD",
    "price": "29.99",
    "priceValidUntil": "2026-12-31",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition",
    "shippingDetails": { "@type": "OfferShippingDetails" },
    "hasMerchantReturnPolicy": { "@type": "MerchantReturnPolicy" }
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.8",
    "reviewCount": "127"
  }
}

aggregateRating is only valid if you actually have those reviews on-site. Fabricating reviews is a manual-action violation. Cross-reference: framework-spampolicies.md.

6.4 LocalBusiness (with subtype)

For local businesses, use the most specific subtype available. Schema.org has hundreds: Restaurant, Plumber, Dentist, HVACBusiness, RealEstateAgent, LegalService, MedicalBusiness, HomeAndConstructionBusiness, etc.

{
  "@type": ["LocalBusiness", "Plumber"],
  "@id": "https://example.com/#organization",
  "name": "Example Plumbing",
  "telephone": "+1-555-555-5555",
  "address": { "@type": "PostalAddress", "..." : "..." },
  "openingHoursSpecification": [
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
      "opens": "08:00",
      "closes": "17:00"
    }
  ],
  "priceRange": "$$"
}

Cross-reference: framework-localseo.md for full LocalBusiness depth.

6.5 FAQPage

Only when the page actually answers questions. Misuse triggers manual actions.

{
  "@type": "FAQPage",
  "@id": "https://example.com/faq/#faqpage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "How long does local SEO take to show results?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Most clients see Local Pack improvements within 30-60 days..."
      }
    }
  ]
}

FAQ rich results were largely deprecated by Google in 2023 for non-government / non-health sites, but the schema still feeds AI extraction. Keep using it where it accurately describes the page; do not expect rich results.

6.6 HowTo

For genuine step-by-step instructions. Like FAQ, rich results were curtailed in 2023 but the schema remains useful for AI extraction.

{
  "@type": "HowTo",
  "name": "How to claim a Google Business Profile",
  "step": [
    {
      "@type": "HowToStep",
      "name": "Sign in to Google Business Profile",
      "text": "Visit business.google.com and sign in..."
    }
  ]
}

6.7 Event

For dated events.

{
  "@type": "Event",
  "name": "Workshop on Local SEO",
  "startDate": "2026-06-15T18:00:00-05:00",
  "endDate": "2026-06-15T20:00:00-05:00",
  "location": {
    "@type": "Place",
    "name": "Cassville Chamber",
    "address": { "@type": "PostalAddress", "..." : "..." }
  },
  "organizer": { "@id": "https://example.com/#organization" },
  "eventStatus": "https://schema.org/EventScheduled",
  "eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode"
}

6.8 Review (single review)

When a page is genuinely a single review of one product/service.

{
  "@type": "Review",
  "itemReviewed": { "@type": "Product", "name": "Product Name" },
  "author": { "@id": "https://example.com/#founder" },
  "reviewRating": {
    "@type": "Rating",
    "ratingValue": "4.5",
    "bestRating": "5"
  },
  "datePublished": "2026-04-01"
}

6.9 VideoObject

For pages embedding or hosting video. Required for video sitemap inclusion.

{
  "@type": "VideoObject",
  "name": "Video Title",
  "description": "Video description.",
  "thumbnailUrl": ["https://example.com/thumb.jpg"],
  "uploadDate": "2026-04-01T08:00:00-05:00",
  "duration": "PT5M30S",
  "contentUrl": "https://example.com/video.mp4",
  "embedUrl": "https://www.youtube.com/embed/abc123"
}

Cross-reference: framework-videoseo.md for full video implementation.

6.10 Other Useful Types


7. The sameAs Network

sameAs declares external canonical identifiers for an entity. This is how Google's Knowledge Graph builds entity confidence.

7.1 sameAs Hierarchy of Trust

Source Weight Notes
Wikidata Highest Entity ID format: https://www.wikidata.org/wiki/Q12345
Wikipedia Very high Article URL
Crunchbase (orgs) High Verified company entries
LinkedIn (orgs and persons) High Verified accounts
GitHub (devs/orgs) High when relevant
Twitter/X Medium Verified accounts only
Facebook Medium Page (not personal)
Instagram Medium Business profiles
YouTube Medium Channel URL
Personal website Low (when used as sameAs from another entity)
Random social network Low Avoid noise

Cross-reference: framework-knowledgegraph.md for Wikidata claiming methodology.

7.2 sameAs Hygiene


8. Schema Implementation Patterns

8.1 The Sitewide Block

Every page on the site emits the same Organization, WebSite, and Person entities. Implement once in your template head:

<!-- Sitewide schema graph (every page) -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [
    { /* Organization */ },
    { /* Person */ },
    { /* WebSite */ }
  ]
}
</script>

8.2 The Page-Specific Block

Each page adds its specific entities (WebPage, Article, BreadcrumbList, etc.) referencing the sitewide entities via @id. Two valid patterns:

Pattern A: Two separate script tags

Pattern B: Merged graph

Pattern A is easier to maintain. Pattern B is what Yoast / Rank Math output.

8.3 Dynamic Sites

For React, Next.js, Astro, Hugo, etc., the schema is built from data at render time. Maintain a single schema.ts (or equivalent) module that exports typed builders:

export function organizationSchema(): Organization { /* ... */ }
export function articleSchema(post: Post): Article { /* ... */ }
export function pageSchema(page: Page): WebPage { /* ... */ }

Tests assert the output validates. Cross-reference: framework-nextjs.md, framework-astrohugo.md.

8.4 WordPress Sites

Yoast and Rank Math both output JSON-LD using the @id graph pattern. Verify their output rather than rebuilding. Common gotchas:


9. Validation Methodology

9.1 Per-URL Validation

Three tools to run on every important page:

  1. Google Rich Results Test — confirms Google can parse and what rich results are eligible.
  2. Schema.org Validator — confirms strict schema.org compliance (catches issues Google's tool doesn't).
  3. Yandex Microdata Validator — third opinion; sometimes catches edge cases.

A page that passes all three is in good shape.

9.2 Sitewide Validation

For sites with many URLs, sample-test rather than per-URL:

9.3 GSC Enhancements Monitoring

Google Search Console's Enhancements section reports schema-related issues sitewide. Categories include Articles, Products, FAQs, How-tos, Breadcrumbs, Sitelinks searchbox, Logos, etc. Check monthly. New errors usually indicate a template change broke schema for a content type.


10. Schema for AI Search

In 2026, AI search engines (ChatGPT, Perplexity, Claude, Gemini, Copilot) use schema as a primary signal for entity extraction. Practical implications:

10.1 Make Claims Extractable

AI engines parse schema looking for atomic facts: "Joseph W. Anady is the founder of That Stupid Computer," "That Stupid Computer is a SDVOSB business in Cassville, Missouri." Express these as schema:

10.2 Don't Hide Facts in Prose Only

A page can have a clear fact in body text ("we serve all of Northwest Arkansas") but if it isn't also in the schema (areaServed), AI engines may miss it.

10.3 Use Specific Subtypes

Organization is too generic. LocalBusiness is better. Plumber (a LocalBusiness subtype) is best because it matches a query category. AI search engines weight specificity.

10.4 The answer-capsule Pattern

Pair schema with a 200-300 word "answer capsule" paragraph in the visible page content that AI extractors can copy verbatim. The schema gives them entity confidence; the prose gives them the quote. Cross-reference: framework-aicitations.md.


11. Audit Mode

# Criterion Pass/Fail
SC1 Format is JSON-LD (not Microdata or RDFa)
SC2 Sitewide Organization schema present on every page
SC3 Sitewide WebSite schema present on every page
SC4 Person schema for owner/key author present and referenced from Organization
SC5 Per-page WebPage schema present, references WebSite via @id
SC6 BreadcrumbList present on every non-homepage
SC7 @id graph pattern used (entities cross-reference via @id, not duplicated)
SC8 All @id values are absolute URLs with fragment identifier
SC9 sameAs network includes Wikidata Q-ID where claimed
SC10 sameAs network includes 3+ authoritative external profiles
SC11 Article schema on every editorial page with author + publisher refs
SC12 Service or Product schema on every commercial page
SC13 LocalBusiness with specific subtype if local business
SC14 All schema URLs use HTTPS
SC15 Image fields point to existing assets, correct dimensions
SC16 datePublished and dateModified accurate (not faked)
SC17 aggregateRating only present if reviews actually exist
SC18 FAQPage schema only on pages that genuinely answer questions
SC19 No deprecated types (hCard, hReview, etc.)
SC20 Google Rich Results Test passes for sample of 5+ pages
SC21 Schema.org Validator passes for sample of 5+ pages
SC22 GSC Enhancements section shows zero errors (warnings acceptable)
SC23 No duplicate schema (multiple plugins emitting overlapping blocks)
SC24 sameAs targets verified to resolve and represent same entity
SC25 Schema present in initial HTML (not added by client-side JS)
SC26 Schema identical on mobile and desktop
SC27 Article images provided in 1x1, 4x3, 16x9 ratios
SC28 Wikidata Q-ID present in Person and Organization sameAs if claimed
SC29 Specific LocalBusiness subtype used (not generic LocalBusiness)
SC30 Sitewide schema validated quarterly

Score: 30. World-class: 28+/30.


12. Common Mistakes

  1. Microdata or RDFa instead of JSON-LD. Maintainability nightmare.
  2. One schema per page, no @graph. Misses the cross-referencing benefit.
  3. No Person schema. Erases E-E-A-T author signals.
  4. Generic LocalBusiness. Plumber or Dentist is far stronger than LocalBusiness.
  5. Fabricated aggregateRating. Manual-action territory.
  6. FAQ schema on pages that aren't FAQs. Same.
  7. Schema added by client-side JavaScript. Some crawlers see it; many don't.
  8. Duplicate schema from multiple plugins. Yoast + Rank Math + theme = three Organization blocks. Conflicting signals.
  9. @id values that aren't URIs. Use absolute URLs with # fragments.
  10. Image fields pointing to broken assets. Schema validates but rich results don't show.
  11. datePublished after dateModified. Logical impossibility, occasionally happens.
  12. sameAs targets that don't resolve. Dead links erode signal.
  13. Schema on staging visible to crawlers. Robots-blocked staging still gets indexed sometimes; schema there pollutes the entity graph.
  14. Schema not updated when content changes. Stale wordCount, stale dateModified, stale description.
  15. Skipping BreadcrumbList. Trivial to implement, immediate SERP benefit.
  16. Over-decorating schema with marketing language. "Best plumber in Cassville" in description instead of plain prose. AI extractors discount marketing phrases.

13. Maintenance

Weekly:

Monthly:

Quarterly:

Annually:


14. Companion Documents


Document version: 1.0 Last updated: 2026-05-05 Owner: Joseph W. Anady — ThatDeveloperGuy — SDVOSB

Want this framework implemented on your site?

ThatDevPro ships these frameworks as productized services. SDVOSB-certified veteran owned. Cassville, Missouri.

See Engine Optimization service ›