structured-data — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited structured-data (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Complete reference for Schema.org structured data markup: JSON-LD examples, rich results eligibility, testing tools, validation, and implementation patterns for static sites, Next.js, React, and WordPress.
Full docs: https://cogny.com/docs/structured-data-reference
/structured-data # Full reference overview
/structured-data Product # Show Product schema example
/structured-data FAQPage # Show FAQPage example (no longer a Google rich result)
/structured-data audit <url> # Fetch a live page, extract its JSON-LD, flag errors
/structured-data LocalBusiness # Show LocalBusiness example
/structured-data validate # Testing and validation guide
/structured-data best-practices # Schema best practices
/structured-data rich-results # Rich results eligibility tableYou are a Schema.org structured data expert. Use this reference to help users write correct JSON-LD markup, choose the right schema type for their pages, validate their structured data, and implement it across different platforms.
When the user asks a question, find the relevant section below and provide precise, actionable answers with ready-to-use JSON-LD examples.
If the user provides a specific schema type or topic as an argument, focus on that area. Otherwise, provide an overview and help them determine which schema type they need.
If Cogny isn't connected, skip the Search Console steps below and note what connecting adds (which pages actually earn rich results, Google's own parse of the URL).
When Search Console MCP tools are available, use them to:
tool_get_search_analytics (filter by search appearance)tool_inspect_urltool_list_propertiesWriting and validating JSON-LD needs no accounts. Connected providers let you build markup from the real source data instead of a template, and check it in both search engines.
| Job | Primary | Also answers it | No account |
|---|---|---|---|
| Is markup seen / rich results earned | Google Search Console (tool_inspect_url, tool_get_search_analytics) | Bing Webmaster (tool_get_url_info, tool_get_crawl_issues) | /structured-data audit <url> (curl), Schema Markup Validator; Rich Results Test needs a browser |
| Product, Offer, AggregateRating values | Shopify (tool_list_products, tool_get_product, tool_get_metafields for review data) | WooCommerce (list_products, list_product_variations, list_product_reviews) | WebFetch the product page |
| Article / BlogPosting values | WordPress (list_posts), Ghost (list_posts), Sanity (tool_list_documents), Contentful (contentful_list_entries) | — | WebFetch the article |
Enhanced when a store or CMS is connected: If Cogny isn't connected, skip this and note what connecting adds (markup built from the real catalogue or CMS, and drift between source data and live markup).
mcp__cogny__mcp__<Prefix>__ prefix, e.g. mcp__cogny__mcp__Shopify__tool_list_products with first: 50).name, price + currency → offers.price / priceCurrency (from the store, never assumed USD), inventory → availability, SKU/GTIN → sku/gtin, published/updated dates → datePublished/dateModified.<script> blocks) and diff its JSON-LD against the source: wrong price, stale availability or a rating that doesn't match the reviews are policy risks, not just bugs.Writing markup back (Shopify__tool_set_metafields, CMS updates) or pushing it to Bing (Bing_Webmaster_Tools__tool_submit_content with structured_data) are writes: draft them and ask first.
/structured-data audit <url>)Works with zero accounts. WebFetch can't see <head> or <script> content, so use curl:
U="<url>"
curl -sL -A "Mozilla/5.0" "$U" -o page.html
python3 -I - page.html <<'PY'
import json, re, sys
html = open(sys.argv[1], encoding="utf-8", errors="replace").read()
blocks = re.findall(r'<script[^>]+application/ld\+json[^>]*>(.*?)</script>', html, re.S | re.I)
print(f"{len(blocks)} JSON-LD block(s)")
for i, b in enumerate(blocks):
try:
print(f"--- block {i}\n" + json.dumps(json.loads(b), indent=2)[:4000])
except ValueError as e:
print(f"--- block {i}: INVALID JSON ({e})")
PYThen validate each entity against the type's section below and Google's docs, and check for these common errors:
| Check | How | Why it matters |
|---|---|---|
| JSON parses | Script above | One syntax error drops the whole block |
| Required properties present | Compare with the type section below | Missing required = no rich result |
logo / image URLs resolve | curl -sI -o /dev/null -w "%{http_code} %{content_type}\n" <url> on each | A 404 logo or an HTML page served as image is a common, silent failure |
| Prices consistent | offers.price vs the price visible in the HTML vs other blocks (e.g. Product vs @graph duplicates, plugin + theme both emitting markup) | Mismatched prices violate Google's Product guidelines |
price numeric, priceCurrency ISO 4217 | Inspect | "$49" is invalid |
Self-serving AggregateRating | aggregateRating on the site's own Organization / LocalBusiness (reviews it controls about itself) | Ineligible for star snippets per Google's review-snippet guidelines |
| Rating with no visible reviews | Grep the HTML for the review count/stars | Markup must match visible content |
dateModified = build/deploy time | Fetch 2-3 pages (and the same page twice a day apart); identical timestamps across unrelated pages, or always "now", mean it's generated at build | Misleading freshness signal; set it from the content's real edit date |
datePublished after dateModified, or in the future | Compare | Validation warning |
| Relative URLs | Any url/image/@id not starting https:// | Use absolute URLs |
| Deprecated types | HowTo, FAQPage | No Google rich result (see eligibility table); harmless, but don't promise one |
| Duplicate entities | Two Organization or Product blocks with different values | Conflicting signals |
Paste the extracted JSON into the Schema Markup Validator (https://validator.schema.org, works on code snippets) for a vocabulary check. The Google Rich Results Test (https://search.google.com/test/rich-results) renders the page in a browser and has no public API: give the user the link to run it rather than claiming a pass. Output a table of findings (severity, entity, property, fix) plus corrected JSON-LD.
Structured data is machine-readable markup that tells search engines, voice assistants, and AI systems exactly what your page content means. You declare it explicitly using the Schema.org vocabulary.
Benefits:
Three formats exist. Google explicitly recommends JSON-LD.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Example Corp"
}
</script>Why JSON-LD: Decoupled from HTML, injectable by JS frameworks, easy to validate, no layout risk.
Inline HTML attributes (itemscope, itemtype, itemprop). Use only in legacy systems that cannot add <script> tags.
Inline attributes (vocab, typeof, property). Rare on the web — more common in XML/SVG contexts.
Bottom line: Use JSON-LD for all new implementations.
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Cogny AI",
"url": "https://cogny.com",
"logo": "https://cogny.com/images/logo.png",
"sameAs": [
"https://twitter.com/cognyai",
"https://linkedin.com/company/cogny",
"https://github.com/cognyai"
],
"contactPoint": {
"@type": "ContactPoint",
"telephone": "+46-8-123-4567",
"contactType": "customer service",
"availableLanguage": ["English", "Swedish"]
},
"foundingDate": "2023",
"numberOfEmployees": {
"@type": "QuantitativeValue",
"value": 15
}
}Required: name | Recommended: url, logo, sameAs, contactPoint Rich result: Knowledge panel
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Nordic Coffee Roasters",
"image": "https://example.com/photos/storefront.jpg",
"url": "https://nordiccoffee.se",
"telephone": "+46-8-765-4321",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "Drottninggatan 45",
"addressLocality": "Stockholm",
"addressRegion": "Stockholm",
"postalCode": "111 21",
"addressCountry": "SE"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 59.3293,
"longitude": 18.0686
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "07:00",
"closes": "18:00"
},
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Saturday", "Sunday"],
"opens": "09:00",
"closes": "16:00"
}
]
}Required: name, address | Recommended: geo, openingHoursSpecification, telephone, priceRange, image Rich result: Local pack, knowledge panel with map/hours/phone
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Wireless Noise-Cancelling Headphones",
"image": [
"https://example.com/photos/headphones-front.jpg",
"https://example.com/photos/headphones-side.jpg"
],
"description": "Premium wireless headphones with active noise cancellation, 30-hour battery life, and multipoint Bluetooth connectivity.",
"sku": "WH-1000XM5",
"brand": {
"@type": "Brand",
"name": "AudioTech"
},
"offers": {
"@type": "Offer",
"url": "https://example.com/headphones-wh1000xm5",
"priceCurrency": "USD",
"price": "349.99",
"priceValidUntil": "2025-12-31",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"seller": {
"@type": "Organization",
"name": "AudioTech Store"
}
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"bestRating": "5",
"reviewCount": "2847"
}
}Required for rich results: name, image, offers (with price, priceCurrency, availability) Recommended: sku, brand, aggregateRating, description Rich result: Product snippet with price, availability, star rating
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is structured data?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Structured data is machine-readable markup added to HTML pages that helps search engines understand your content. It uses the Schema.org vocabulary and is typically implemented in JSON-LD format."
}
},
{
"@type": "Question",
"name": "Does structured data improve SEO rankings?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Structured data does not directly affect rankings. However, it enables rich results that significantly improve click-through rates, which can indirectly improve performance through higher engagement signals."
}
}
]
}Required: mainEntity array with Question items containing acceptedAnswer Rich result: None in Google Search any more. From September 2023 it was shown only for well-known, authoritative government and health sites; Google stopped showing it entirely on May 7, 2026 and removed the documentation in June 2026 (https://developers.google.com/search/updates). The markup is still valid Schema.org and other consumers may read it, but don't promise a rich result.
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "How to Implement JSON-LD Structured Data",
"description": "A step-by-step guide to adding Schema.org JSON-LD structured data to your website.",
"totalTime": "PT15M",
"estimatedCost": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": "0"
},
"tool": [
{ "@type": "HowToTool", "name": "Text editor or CMS" },
{ "@type": "HowToTool", "name": "Google Rich Results Test" }
],
"step": [
{
"@type": "HowToStep",
"name": "Choose your schema type",
"text": "Identify the primary content type of your page and look up the required properties at schema.org.",
"url": "https://example.com/guide#step1",
"image": "https://example.com/images/step1.png"
},
{
"@type": "HowToStep",
"name": "Write the JSON-LD block",
"text": "Create a JSON-LD script block with @context, @type, and all required properties.",
"url": "https://example.com/guide#step2",
"image": "https://example.com/images/step2.png"
},
{
"@type": "HowToStep",
"name": "Insert into your page",
"text": "Place the script tag in the head or body of your HTML document.",
"url": "https://example.com/guide#step3",
"image": "https://example.com/images/step3.png"
},
{
"@type": "HowToStep",
"name": "Validate with testing tools",
"text": "Run your page through the Google Rich Results Test and Schema Markup Validator.",
"url": "https://example.com/guide#step4",
"image": "https://example.com/images/step4.png"
}
]
}Required: name, step (with text each) | Recommended: image per step, totalTime, tool Rich result: None. Google deprecated How-to rich results on September 13, 2023 (desktop and mobile) and removed the docs (https://developers.google.com/search/blog/2023/08/howto-faq-changes). Valid Schema.org, no Google SERP feature.
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Complete Guide to Schema.org Structured Data",
"description": "Learn how to implement structured data markup to earn rich results in Google Search.",
"image": [
"https://example.com/images/guide-16x9.jpg",
"https://example.com/images/guide-4x3.jpg",
"https://example.com/images/guide-1x1.jpg"
],
"author": {
"@type": "Person",
"name": "Anna Lindqvist",
"url": "https://example.com/authors/anna-lindqvist"
},
"publisher": {
"@type": "Organization",
"name": "Example Publishing",
"logo": { "@type": "ImageObject", "url": "https://example.com/logo.png" }
},
"datePublished": "2025-01-15",
"dateModified": "2025-02-10",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://example.com/guides/structured-data"
}
}Use Article for news, BlogPosting for blogs, NewsArticle for Google News publishers.
Required: headline, image, datePublished, author Rich result: Article carousel, Top Stories (NewsArticle), author/date in results
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
{ "@type": "ListItem", "position": 2, "name": "Docs", "item": "https://example.com/docs" },
{ "@type": "ListItem", "position": 3, "name": "Structured Data", "item": "https://example.com/docs/structured-data" }
]
}Required: itemListElement with position, name, item Rich result: Breadcrumb trail replaces URL in search results
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Cloud Analytics Platform",
"review": [
{
"@type": "Review",
"reviewRating": { "@type": "Rating", "ratingValue": "5", "bestRating": "5" },
"author": { "@type": "Person", "name": "Erik Johansson" },
"reviewBody": "Transformed our data pipeline. The BigQuery integration is seamless.",
"datePublished": "2025-01-20"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"bestRating": "5",
"ratingCount": "312",
"reviewCount": "189"
}
}Reviews must be nested inside the item they review — standalone Review markup without context will not generate rich results.
Required: ratingValue, bestRating, author (Review); ratingValue, ratingCount (AggregateRating) Rich result: Star rating snippet
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Nordic Growth Marketing Summit 2025",
"description": "Two-day conference on performance marketing and AI-driven analytics.",
"startDate": "2025-09-15T09:00:00+02:00",
"endDate": "2025-09-16T17:00:00+02:00",
"eventStatus": "https://schema.org/EventScheduled",
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
"location": {
"@type": "Place",
"name": "Stockholm Waterfront Congress Centre",
"address": {
"@type": "PostalAddress",
"streetAddress": "Nils Ericsons Plan 4",
"addressLocality": "Stockholm",
"postalCode": "111 64",
"addressCountry": "SE"
}
},
"performer": { "@type": "Organization", "name": "Cogny AI" },
"offers": {
"@type": "Offer",
"url": "https://example.com/tickets",
"price": "4999",
"priceCurrency": "SEK",
"availability": "https://schema.org/InStock",
"validFrom": "2025-03-01T00:00:00+01:00"
},
"organizer": { "@type": "Organization", "name": "Growth Hackers Stockholm", "url": "https://growthhackers.se" },
"image": "https://example.com/images/summit-2025.jpg"
}Required: name, startDate, location | Recommended: endDate, offers, performer, eventStatus, image Rich result: Event listing with date/location/ticket; event pack in SERP
{
"@context": "https://schema.org",
"@type": "VideoObject",
"name": "How to Set Up GA4 BigQuery Export",
"description": "Step-by-step tutorial for connecting GA4 to BigQuery.",
"thumbnailUrl": "https://example.com/thumbnails/ga4-setup.jpg",
"uploadDate": "2025-01-10",
"duration": "PT12M30S",
"contentUrl": "https://example.com/videos/ga4-setup.mp4",
"embedUrl": "https://youtube.com/embed/abc123",
"interactionStatistic": {
"@type": "InteractionCounter",
"interactionType": { "@type": "WatchAction" },
"userInteractionCount": 15420
}
}Required: name, thumbnailUrl, uploadDate | Recommended: description, duration, contentUrl or embedUrl Rich result: Video carousel, video thumbnail in search results
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Cogny Analytics Platform",
"operatingSystem": "Web",
"applicationCategory": "BusinessApplication",
"description": "AI-powered analytics platform for automated growth insights.",
"offers": { "@type": "Offer", "price": "99", "priceCurrency": "USD" },
"aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.8", "ratingCount": "156" },
"screenshot": "https://example.com/images/dashboard.png"
}Required: name, offers (with price, priceCurrency) | Recommended: operatingSystem, applicationCategory, aggregateRating Rich result: Software snippet with rating and price
{
"@context": "https://schema.org",
"@type": "Course",
"name": "Advanced BigQuery for Marketing Analytics",
"description": "Learn to write efficient BigQuery SQL for GA4 data, build attribution models, and create automated reporting.",
"provider": { "@type": "Organization", "name": "Cogny Academy", "sameAs": "https://cogny.com/academy" },
"courseCode": "BQ-301",
"hasCourseInstance": {
"@type": "CourseInstance",
"courseMode": "online",
"courseSchedule": {
"@type": "Schedule",
"repeatFrequency": "P1W",
"startDate": "2025-03-01",
"endDate": "2025-04-15"
}
},
"offers": { "@type": "Offer", "price": "499", "priceCurrency": "USD", "category": "Paid" }
}Required: name, description, provider | Recommended: offers, hasCourseInstance Rich result: Course listing with provider and enrollment info
{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Senior Growth Engineer",
"description": "Build and optimize marketing analytics infrastructure including BigQuery pipelines, A/B testing, and automated reporting.",
"datePosted": "2025-02-01",
"validThrough": "2025-04-01T23:59:59+01:00",
"employmentType": "FULL_TIME",
"hiringOrganization": {
"@type": "Organization",
"name": "Cogny AI",
"sameAs": "https://cogny.com",
"logo": "https://cogny.com/images/logo.png"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "Stockholm",
"addressRegion": "Stockholm",
"addressCountry": "SE"
}
},
"jobLocationType": "TELECOMMUTE",
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "SEK",
"value": { "@type": "QuantitativeValue", "minValue": 55000, "maxValue": 75000, "unitText": "MONTH" }
},
"applicantLocationRequirements": { "@type": "Country", "name": "Sweden" }
}Required: title, description, datePosted, hiringOrganization, jobLocation Recommended: validThrough, employmentType, baseSalary, jobLocationType Rich result: Google Jobs listing with salary, location, apply button
URL: https://search.google.com/test/rich-results
Test individual pages or code snippets for rich result eligibility. Shows detected types, validation errors, and warnings. It runs in a browser (no public API, and WebFetch can't drive it), so hand the user the link; for an automated check use the curl audit above.
URL: https://validator.schema.org
Validates against the full Schema.org specification — catches structural errors the Rich Results Test may miss.
Location: Search Console > Enhancements > [specific rich result type]
Aggregate data across your site: valid pages, error counts, specific error types. Updated daily.
| Error | Cause | Fix |
|---|---|---|
Missing field "image" | Product/Article missing image | Add image with valid crawlable URL |
Invalid URL in field "url" | Relative URL | Use fully qualified URLs (https://...) |
Missing field "author" | Article/Review missing author | Add author as Person or Organization with name |
Invalid value in field "price" | Currency symbol in price | Use numeric value only ("349.99" not "$349.99") |
Invalid enum for "availability" | Plain text instead of URL | Use https://schema.org/InStock, not "In Stock" |
Array expected, single value | Single image instead of array | Wrap in array: "image": ["https://..."] |
datePublished is in the future | Date set ahead of publish | Set to actual publication date |
Match the primary schema type to the page purpose. Product pages use Product, blog posts use BlogPosting, FAQ pages may use FAQPage (no Google rich result). Combine with BreadcrumbList as a complementary type.
Nest when there is a parent-child relationship (Product > Offer). Use @graph for independent entities on the same page:
{
"@context": "https://schema.org",
"@graph": [
{ "@type": "BreadcrumbList", "itemListElement": [...] },
{ "@type": "Product", "name": "Widget", "offers": {...} }
]
}Required properties must be present for the rich result to appear. Recommended properties improve quality and appearance. Always include both.
Google manual actions for structured data spam can remove all rich results from your entire domain.
Generate structured data from the same data source as page content. Include schema updates in your CMS publishing workflow. Audit quarterly or after major site changes.
| Schema Type | Rich Result | SERP Appearance |
|---|---|---|
Product | Product snippet | Price, availability, stars |
FAQPage | None (retired) | Gov/health only from Sept 2023; not shown at all from May 7, 2026 |
HowTo | None (retired) | Deprecated Sept 13, 2023 on desktop and mobile |
Article / BlogPosting | Article result | Author, date, thumbnail |
NewsArticle | Top Stories | Carousel at top of results |
BreadcrumbList | Breadcrumb trail | Replaces URL with nav path |
Review / AggregateRating | Review snippet | Star rating below listing (not for self-serving reviews on your own Organization/LocalBusiness) |
Event | Event listing | Date, location, tickets |
VideoObject | Video result | Thumbnail, duration |
LocalBusiness | Local pack | Map, hours, phone |
JobPosting | Google Jobs | Salary, location, apply |
SoftwareApplication | Software result | Rating, price |
Course | Course listing | Provider, enrollment |
Organization | Knowledge panel | Logo, social links |
<head>
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "Product", ... }
</script>
</head>export default function ProductPage({ product }) {
const jsonLd = {
"@context": "https://schema.org",
"@type": "Product",
name: product.name,
image: product.images,
offers: {
"@type": "Offer",
price: product.price,
priceCurrency: product.currency,
availability: product.inStock
? "https://schema.org/InStock"
: "https://schema.org/OutOfStock",
},
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
{/* content */}
</>
);
}Use Yoast SEO, Rank Math, or Schema Pro plugins. For custom implementation:
add_action('wp_head', function() {
if (is_singular('product')) {
$product = get_post();
$price = get_post_meta($product->ID, '_price', true);
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $product->post_title,
'offers' => [
'@type' => 'Offer',
'price' => $price,
'priceCurrency' => 'USD',
'availability' => 'https://schema.org/InStock',
],
];
echo '<script type="application/ld+json">' . json_encode($schema) . '</script>';
}
});function generateProductSchema(cmsData: CMSProduct): object {
return {
"@context": "https://schema.org",
"@type": "Product",
name: cmsData.title,
image: cmsData.media.map(m => m.url),
offers: {
"@type": "Offer",
price: cmsData.variants[0].price.toString(),
priceCurrency: cmsData.currency,
availability: cmsData.inStock
? "https://schema.org/InStock"
: "https://schema.org/OutOfStock",
},
};
}Key principle: generate structured data from the same data source that populates the page, never hardcode separately.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.