pseo-schema
Skill54 starsChanged 15 days agoMITView on GitHub
Implement JSON-LD structured data for programmatic SEO pages using types that still produce Google rich results (Product, Organization, LocalBusiness, BreadcrumbList, Article, JobPosting, Event, Review snippets and similar). Use when adding or fixing schema markup, removing retired types (FAQ, HowTo), or when Google Search Console reports schema errors. Markup must match visible content; no special schema is needed for AI features.
1 other project uses a version of this, 1 of them edited.
Adopted by
Most recently taken up by
- karrolcia/hippocampusedited, first seen Mar 2, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 1
- karrolcia/hippocampus★ 1356% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository17 other files it gives its agents.
- gscSkill
- pseo-auditSkill
- pseo-dataSkill
- pseo-discoverySkill
- pseo-linkingSkill
- pseo-llm-visibilitySkill
- pseo-metadataSkill
- pseo-orchestrateSkill
- pseo-performanceSkill
- pseo-quality-guardSkill
- pseo-scaleSkill
- pseo-templatesSkill
- seo-content-refreshSkill
- seo-i18nSkill
- seo-log-analysisSkill
- seo-migrationSkill
- seo-regression-guardSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
18 rules. About 0 are common, 14 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈14
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
JSON-LD format: Always use JSON-LD, not Microdata or RDFa
- Distinctive: line 19
Valid and complete: Every schema block must pass Google's Rich Results Test
- Distinctive: line 20
No fabrication: Only include fields backed by real data
- Distinctive: line 55
Only types in Google's Search Gallery (page last updated 2026-06-15) are listed as primary.
- Very specific: line 169
Keep JSON-LD small: it counts toward the Googlebot 2MB limit (pseo-templates section 6b), so do not inline huge ItemList or dataset blobs …
- Distinctive: line 200
Never include empty strings or placeholder values
- Distinctive: line 201
Never include fields with fabricated data (e.g., fake reviews)
- Distinctive: line 202
Every value must be visible on the page or derivable from what is visible
- Distinctive: line 205
Only mark up real, first-party-visible reviews and ratings
- Distinctive: line 206
Avoid multiple ways of indicating the reviewed item (Google, 2025-11-12)
- Distinctive: line 207
No fake or undisclosed incentivized reviews (Google guideline, 2026-07-24)
- Very specific: line 208
Never generate AggregateRating from invented numbers
- Very specific: line 210
Product sale pricing: use validFrom, validThrough and priceValidUntil for sale durations (Google, 2026-07-07).
- Distinctive: line 222
Not include deprecated properties or retired types
- Distinctive: line 223
Not include fields with empty or placeholder values
- Distinctive: line 224
Use absolute URLs, not relative paths
- Distinctive: line 263
dateModified must be accurate: Never set dateModified to today's date if the content has not actually changed.
- Very specific: line 321
Never fabricate people, credentials or sameAs links.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
pSEO Schema Markup
Implement JSON-LD structured data that describes what is visibly on each programmatic page, so eligible pages can qualify for rich results.
Research basis: https://github.com/lisbeth718/pseo-skills/blob/main/docs/research-2026-10.md (primary sources, 2026-10-12).
Core Principles
- JSON-LD format: Always use JSON-LD, not Microdata or RDFa
- Context-appropriate types: Match schema type to the page's actual content
- Data-driven generation: Schema is built from the same data that drives the page
- Valid and complete: Every schema block must pass Google's Rich Results Test
- No fabrication: Only include fields backed by real data
- Matches visible content: Structured data must match the text users see on the page (Google's AI features docs repeat this)
- Review it like content: Google says to manually fact-check AI-generated structured data, along with titles, meta descriptions and alt text
Scope parameter
types selects what to implement. Article, Product, LocalBusiness, JobPosting, Event, Breadcrumb, Organization = sections 1-5 plus the matching rule in section 4 (Product also section 8, LocalBusiness also section 9). Author = sections 6 and 7 (author, reviewer and entity pages). all (default) = everything.
What Schema Does and Does Not Do (as of 2026-10-12)
- Rich results only. The value of schema in Google Search is rich-result eligibility. It is not a ranking tactic.
- No special schema for AI features. Google states AI Overviews and AI Mode need no special schema.org markup, and tells sites not to over-focus on structured data. Do not add markup "for AI" or "for LLM extraction".
- Retired in Google Search, do not generate for rich results:
- FAQ rich results: no longer shown from 2026-05-07, docs removed 2026-06-15
- HowTo (removed 2023) and Sitelinks search box (removed 2024)
- Practice problems (deprecated 2025-11-05, docs removed 2026-01-06)
- Course info, Estimated salary, Learning video, Special announcement, Vehicle listing (phased out, docs removed 2025-09-09)
- ClaimReview: being phased out in Google Search
- Dataset markup is only used by Dataset Search since 2025-11-05, not Google Search.
- Breadcrumbs: mobile results show the domain only since 2025-01-23. Desktop still shows breadcrumbs, and BreadcrumbList markup remains supported.
FAQPage: Optional Semantic Markup Only
FAQPage no longer produces a rich result in Google. Do not add it for SERP real estate, ranking, or AI visibility. Keep it only if another consumer needs it (for example a non-Google parser) and the Q&A is fully visible on the page. If you have existing FAQPage or HowTo generators, remove them from the default page composition. Visible FAQ sections on the page can stay if they help users; they just do not need markup.
Baseline Schema
BreadcrumbList: on every page with a navigation hierarchy (desktop breadcrumb display)Organization: site-level, once per site (homepage or shared layout). The logo now lives in the Organization docs.WebPage/WebSite: optional semantic markup. They produce no Google rich result by themselves, so treat as low priority. Do not add a sitelinks search box (retired).
These are in addition to the content-specific types below.
Schema Types by Page Context
Only types in Google's Search Gallery (page last updated 2026-06-15) are listed as primary.
| Page Type | Primary Schema | Supporting Schema |
| Content/article page | Article | BreadcrumbList, Organization |
| Product page | Product (product snippet / merchant listing) | BreadcrumbList, Offer, review snippet fields where real |
| Category/hub page | BreadcrumbList (no hub-specific rich result exists) | CollectionPage, ItemList (optional semantic markup, no rich result; carousel only if eligible) |
| Local/location page | LocalBusiness | BreadcrumbList, Organization |
| Job page | JobPosting | BreadcrumbList, Organization |
| Event page | Event (must be bookable by the public at a physical location) | BreadcrumbList |
| Software page | SoftwareApplication | BreadcrumbList |
| Q&A / forum page | QAPage or DiscussionForumPosting (real user content only) | BreadcrumbList |
Other Search Gallery types that fit some pSEO sites: Recipe, Video, Vacation rental, Profile page, Return policy, Shipping policy, Loyalty program, Employer rating, Image license metadata. Use them only when the page genuinely is that thing.
Implementation Steps
1. Create Schema Generator Functions
Build a module of pure functions that produce schema objects from page data:
// lib/schema.ts
export function generateArticleSchema(data: PageData, url: string) {
return {
"@context": "https://schema.org",
"@type": "Article",
headline: data.h1,
description: data.metaDescription,
url,
datePublished: data.publishedDate,
dateModified: data.lastModified,
author: { "@type": "Organization", name: "..." },
publisher: { "@type": "Organization", name: "..." },
};
}
export function generateProductSchema(data: ProductData, url: string) {
return {
"@context": "https://schema.org",
"@type": "Product",
name: data.name,
description: data.description,
url,
image: data.images,
...(data.category && { category: data.category }),
// Only include offers when price and availability are visible on the page
...(data.price && {
offers: {
"@type": "Offer",
price: data.price,
priceCurrency: data.currency,
availability: data.availabilityUrl,
...(data.priceValidUntil && { priceValidUntil: data.priceValidUntil }),
},
}),
};
}
// FAQPage: OPTIONAL semantic markup only. Google retired the FAQ rich
// result (not shown from 2026-05-07) and no special schema is needed for AI
// features. Do not use this as a ranking or AI tactic. If used, the Q&A
// must be visible in the rendered HTML, never only in the JSON-LD.
export function generateFAQSchema(faqs: FAQ[]) {
if (!faqs?.length) return null;
return {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: faqs.map((faq) => ({
"@type": "Question",
name: faq.question,
acceptedAnswer: {
"@type": "Answer",
text: faq.answer,
},
})),
};
}
export function generateBreadcrumbSchema(
items: { name: string; url: string }[]
) {
return {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: items.map((item, i) => ({
"@type": "ListItem",
position: i + 1,
name: item.name,
item: item.url,
})),
};
}2. Create the Schema Renderer Component
Build a reusable component that injects JSON-LD into the page. Escape < so data cannot close the script tag:
export function JsonLd({ data }: { data: Record<string, unknown> | null }) {
if (!data) return null;
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(data).replace(/</g, "\\u003c"),
}}
/>
);
}Keep JSON-LD small: it counts toward the Googlebot 2MB limit (pseo-templates section 6b), so do not inline huge ItemList or dataset blobs on every page.
3. Compose Schema per Page
Each page template composes its schema from multiple generators:
// In the page component
const schemas = [
generateArticleSchema(data, canonicalUrl),
generateBreadcrumbSchema(breadcrumbItems),
].filter(Boolean);
// Render each as a separate script tag
{schemas.map((schema, i) => <JsonLd key={i} data={schema} />)}4. Schema Field Rules
Required fields per type (check the type's current Google doc, requirements change):
Article: headline, url, datePublished, dateModified, author, publisherBreadcrumbList: itemListElement with position, name, itemProduct: name, description, image; offers or review if available and visible on the pageLocalBusiness: name, address; plus the fields Google lists for the business typeJobPosting,Event: follow the current Google doc for required properties
Field integrity rules:
headlinemust match the page's H1 or titleurlmust match the canonical URLdateModifiedmust be a valid ISO 8601 date- Never include empty strings or placeholder values
- Never include fields with fabricated data (e.g., fake reviews)
- Every value must be visible on the page or derivable from what is visible
Review snippets:
- Only mark up real, first-party-visible reviews and ratings
- Avoid multiple ways of indicating the reviewed item (Google, 2025-11-12)
- No fake or undisclosed incentivized reviews (Google guideline, 2026-07-24)
- Never generate
AggregateRatingfrom invented numbers
Product sale pricing: use validFrom, validThrough and priceValidUntil for sale durations (Google, 2026-07-07).
5. Handle Multiple Schema Types
A single page can have multiple schema blocks. Render them as separate <script type="application/ld+json"> tags, not as an array in one tag (for maximum compatibility).
Validation
Schema must:
- Pass Google's Rich Results Test (https://search.google.com/test/rich-results)
- Pass Schema.org validation
- Match the visible page content
- Not include deprecated properties or retired types
- Not include fields with empty or placeholder values
- Use absolute URLs, not relative paths
Watch Search Console enhancement reports. Retired features (FAQ, HowTo, Course info and others) are gone from reports and the Rich Results Test, so a clean report there does not mean the markup does anything.
6. E-E-A-T Schema Support
E-E-A-T is not a specific ranking factor, but trust matters, especially on YMYL topics. Schema can state authorship and responsibility clearly. It reinforces what the visible page already shows; it does not replace it.
Author/Organization schema:
interface AuthorInfo {
type: "person" | "organization";
name: string;
url: string;
role?: string;
credentialCategory?: string;
sameAs?: string[];
}
export function generateAuthorSchema(author: AuthorInfo) {
return {
"@context": "https://schema.org",
"@type": author.type === "person" ? "Person" : "Organization",
name: author.name,
url: author.url,
...(author.role && { jobTitle: author.role }),
...(author.credentialCategory && {
hasCredential: {
"@type": "EducationalOccupationalCredential",
credentialCategory: author.credentialCategory,
},
}),
...(author.sameAs && { sameAs: author.sameAs }),
};
}Add author and publisher to Article schema and show the same attribution on the page.
dateModified must be accurate. Never set dateModified to today's date if the content has not actually changed. Use the real last-modified date from the data source. The same rule applies to sitemap lastmod, which Google uses only if it is consistently accurate.
For YMYL content, additionally include:
reviewedByonWebPagepointing to aPerson(not a business type):jobTitleis the person's role, andhasCredentialis{ "@type": "EducationalOccupationalCredential", credentialCategory }. Show the same reviewer and credential visibly on the page.citationorisBasedOnfor content derived from authoritative sources
export function generateReviewedWebPage(url: string, reviewer: { name: string; url: string; role: string; credentialCategory: string }) {
return {
"@context": "https://schema.org",
"@type": "WebPage",
url,
reviewedBy: {
"@type": "Person",
name: reviewer.name,
url: reviewer.url,
jobTitle: reviewer.role,
hasCredential: {
"@type": "EducationalOccupationalCredential",
credentialCategory: reviewer.credentialCategory,
},
},
};
}reviewedBy, hasCredential and credentialCategory are schema.org vocabulary; the research doc does not verify Google reads them for any feature, so treat them as semantic markup of visible facts.
7. Author and Entity Pages (E-E-A-T)
Bylines should link to real pages, not just print names:
- Author profile page (
/authors/[slug]): visible bio, role, credentials, and the pages they wrote. Markup:ProfilePagewithmainEntityaPerson(name,jobTitle,sameAslinks to real profiles,hasCredentialas above). "Profile page" is listed in Google's Search Gallery (research doc, Search Gallery list and section 11); the page must be about one real person or organization, with first-party content. - Organization / about page (
/about): the single place for the site-levelOrganization(name, logo,sameAs, contact). Link to it from the footer and from bylines of organization-authored pages. - Bylines on every pSEO page link to the author or about page, using the same name as
authorin the Article schema. Organization attribution is acceptable for data-driven pages; do not invent a person.
export function generateProfilePageSchema(url: string, person: AuthorInfo) {
return {
"@context": "https://schema.org",
"@type": "ProfilePage",
url,
mainEntity: {
"@type": "Person",
name: person.name,
jobTitle: person.role,
sameAs: person.sameAs,
...(person.credentialCategory && {
hasCredential: {
"@type": "EducationalOccupationalCredential",
credentialCategory: person.credentialCategory,
},
}),
},
};
}Never fabricate people, credentials or sameAs links.
8. E-commerce (short)
Verified in the research doc: Merchant listing, Product variants, Return policy and Shipping policy are Search Gallery features; merchant shipping policy markup was added 2025-11-12; Product.category and sale-duration fields were added in 2026 (see above).
- Product and merchant listing data must match the Merchant Center feed (price, availability, identifiers) and the visible page.
- Shipping and returns:
shippingDetailsonOfferandhasMerchantReturnPolicyonOffer(or an organization-level policy). Property names are schema.org; check the current Google doc for required fields before shipping. - Variants:
ProductGroupwithhasVariant/variesByfor size or color variants. Check the Google Product variants doc for which properties it requires; this skill does not verify them. - Per-field requirements beyond the above are not verified here. Keep markup generic and follow the live Google docs.
9. Local SEO (short)
LocalBusiness only for a real location, one per location, with NAP (name, address, phone) identical to the visible page and the business profile. A location page without unique local data (real address, staff, inventory, local facts) is a doorway page, not a local page: see pseo-quality-guard section 7.
10. Video
VideoObject for pages whose main content is a video: see Google's video doc for required properties (2026-09-24 added creator/author and interactionStatistic).
File Organization
lib/
schema.ts # all schema generator functions
schema.test.ts # validation tests
components/
JsonLd.tsx # reusable JSON-LD rendererRelationship to Other Skills
- Depends on: pseo-data (structured fields feed schema generation)
- Works with: pseo-templates (schema components are rendered inside page templates)
- Breadcrumb data from: pseo-linking (breadcrumb trail structure)
Verify
Build, start the app, and run seo-regression-guard against localhost (npx -y tsx <seo-regression-guard-dir>/scripts/seo-check.ts --site http://localhost:3000). Zero errors for the touched templates; also run the Rich Results Test on one URL per template.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

