mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-07 23:02:39 +02:00
feat: enhance SurfSense with new skills, blog section, and improve SEO metadata
Some checks failed
Build and Push Docker Images / tag_release (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend) (push) Has been cancelled
Build and Push Docker Images / create_manifest (web, surfsense-web) (push) Has been cancelled
Some checks failed
Build and Push Docker Images / tag_release (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend) (push) Has been cancelled
Build and Push Docker Images / create_manifest (web, surfsense-web) (push) Has been cancelled
- Added multiple new skills to skills-lock.json from the repository `aaron-he-zhu/seo-geo-claude-skills`. - Introduced `fuzzy-search` dependency in package.json for improved search functionality. - Updated pnpm-lock.yaml to include the new `fuzzy-search` package. - Enhanced SEO metadata across various pages, including canonical links and descriptions for better search visibility. - Improved layout and structure of several components, including the homepage and changelog, to enhance user experience.
This commit is contained in:
parent
61b3f0d7e3
commit
7ea840dbb2
120 changed files with 25729 additions and 352 deletions
|
|
@ -0,0 +1,65 @@
|
|||
# Schema Type Decision Tree
|
||||
|
||||
Guidelines for selecting the right schema types based on content, industry, and implementation priority.
|
||||
|
||||
---
|
||||
|
||||
## When to Use Which Schema
|
||||
|
||||
| Your Content | Primary Schema | Add If Applicable | Rich Result Eligibility |
|
||||
|-------------|---------------|-------------------|----------------------|
|
||||
| Blog post / article | Article | FAQ, HowTo, Speakable | Article carousel, FAQ rich result |
|
||||
| Product page | Product | Review, Offer, AggregateRating | Product snippet with price/rating |
|
||||
| Service page | Service | FAQ, LocalBusiness | Service snippet |
|
||||
| How-to guide | HowTo | Article, FAQ | How-to rich result with steps |
|
||||
| FAQ page | FAQPage | Article | FAQ accordion in SERP |
|
||||
| Recipe | Recipe | Video, AggregateRating | Recipe carousel |
|
||||
| Event | Event | Offer, Organization | Event snippet with date/location |
|
||||
| Video | VideoObject | Article | Video carousel, key moments |
|
||||
| Local business | LocalBusiness | Review, OpeningHoursSpecification | Local pack, knowledge panel |
|
||||
| Person/author | Person | Organization | Knowledge panel |
|
||||
| Organization | Organization | ContactPoint, Logo | Knowledge panel |
|
||||
| Course | Course | Organization | Course rich result |
|
||||
| Job posting | JobPosting | Organization | Google for Jobs listing |
|
||||
| Breadcrumb | BreadcrumbList | (Always add alongside other schema) | Breadcrumb trail in SERP |
|
||||
| Software/App | SoftwareApplication | Review, Offer | App snippet |
|
||||
|
||||
---
|
||||
|
||||
## Industry-Specific Schema Recommendations
|
||||
|
||||
| Industry | Essential Schema | High-Value Additions |
|
||||
|----------|-----------------|---------------------|
|
||||
| E-commerce | Product, BreadcrumbList, Organization | AggregateRating, FAQ, Review |
|
||||
| SaaS | SoftwareApplication, FAQPage, Organization | HowTo, VideoObject, Review |
|
||||
| Local Services | LocalBusiness, Service | FAQ, Review, Event |
|
||||
| Publishing/Media | Article, Person, Organization | FAQ, Speakable, VideoObject |
|
||||
| Education | Course, Organization | FAQ, HowTo, Event |
|
||||
| Healthcare | MedicalWebPage, Organization | FAQ, Physician, MedicalClinic |
|
||||
| Real Estate | RealEstateListing, Organization | LocalBusiness, FAQ |
|
||||
| Restaurants | Restaurant, Menu | Review, Event, FAQ |
|
||||
|
||||
---
|
||||
|
||||
## Schema Implementation Priority
|
||||
|
||||
| Priority | Schema Types | Why |
|
||||
|----------|-------------|-----|
|
||||
| P0 -- Always | Organization, BreadcrumbList, WebSite (SearchAction) | Foundation for all sites |
|
||||
| P1 -- Content | Article, FAQPage, HowTo | Direct rich result eligibility |
|
||||
| P2 -- Commercial | Product, Review, AggregateRating, Offer | Revenue-impacting rich results |
|
||||
| P3 -- Authority | Person, SameAs, Speakable | E-E-A-T signals, AI citation |
|
||||
| P4 -- Specialized | Industry-specific types | Niche rich results |
|
||||
|
||||
---
|
||||
|
||||
## Schema Validation Quick Reference
|
||||
|
||||
| Issue | Impact | Fix |
|
||||
|-------|--------|-----|
|
||||
| Missing required property | Schema ignored by Google | Add all required fields (check schema.org) |
|
||||
| Invalid date format | Warning, may lose rich result | Use ISO 8601: "2026-02-11" |
|
||||
| Incorrect @type | Schema misinterpreted | Match @type exactly to schema.org |
|
||||
| Self-referencing sameAs | Warning | sameAs should link to EXTERNAL profiles |
|
||||
| Missing image for Article | Loses article rich result | Add image property with valid URL |
|
||||
| Review without itemReviewed | Review not connected | Nest review inside Product/Service/etc. |
|
||||
|
|
@ -0,0 +1,631 @@
|
|||
# Schema.org JSON-LD Templates
|
||||
|
||||
Complete, copy-ready structured data templates for all major schema types. Customize the bracketed values to match your content.
|
||||
|
||||
## FAQPage Schema
|
||||
|
||||
For pages with frequently asked questions. Minimum 2 Q&A pairs required.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
"mainEntity": [
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "[Question text - exactly as shown on page]",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "[Complete answer text - must match visible content]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "[Question 2]",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "[Answer 2]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "[Question 3]",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "[Answer 3]"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Requirements**: Questions must be complete questions, answers must be comprehensive, content must match visible page content.
|
||||
|
||||
---
|
||||
|
||||
## HowTo Schema
|
||||
|
||||
For step-by-step instructional content.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "HowTo",
|
||||
"name": "[How-to title - what will users learn]",
|
||||
"description": "[Brief description of what this tutorial teaches]",
|
||||
"image": {
|
||||
"@type": "ImageObject",
|
||||
"url": "[Main image URL]",
|
||||
"height": "[height in pixels]",
|
||||
"width": "[width in pixels]"
|
||||
},
|
||||
"totalTime": "PT[X]H[Y]M",
|
||||
"estimatedCost": {
|
||||
"@type": "MonetaryAmount",
|
||||
"currency": "USD",
|
||||
"value": "[estimated cost or 0]"
|
||||
},
|
||||
"supply": [
|
||||
{
|
||||
"@type": "HowToSupply",
|
||||
"name": "[Supply item 1]"
|
||||
},
|
||||
{
|
||||
"@type": "HowToSupply",
|
||||
"name": "[Supply item 2]"
|
||||
}
|
||||
],
|
||||
"tool": [
|
||||
{
|
||||
"@type": "HowToTool",
|
||||
"name": "[Tool 1]"
|
||||
},
|
||||
{
|
||||
"@type": "HowToTool",
|
||||
"name": "[Tool 2]"
|
||||
}
|
||||
],
|
||||
"step": [
|
||||
{
|
||||
"@type": "HowToStep",
|
||||
"position": 1,
|
||||
"name": "[Step 1 title]",
|
||||
"text": "[Step 1 detailed instructions]",
|
||||
"url": "[Page URL]#step1",
|
||||
"image": "[Step 1 image URL - optional]"
|
||||
},
|
||||
{
|
||||
"@type": "HowToStep",
|
||||
"position": 2,
|
||||
"name": "[Step 2 title]",
|
||||
"text": "[Step 2 detailed instructions]",
|
||||
"url": "[Page URL]#step2",
|
||||
"image": "[Step 2 image URL - optional]"
|
||||
},
|
||||
{
|
||||
"@type": "HowToStep",
|
||||
"position": 3,
|
||||
"name": "[Step 3 title]",
|
||||
"text": "[Step 3 detailed instructions]",
|
||||
"url": "[Page URL]#step3",
|
||||
"image": "[Step 3 image URL - optional]"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Time format**: PT[X]H[Y]M where X = hours, Y = minutes. Example: PT1H30M = 1 hour 30 minutes.
|
||||
|
||||
---
|
||||
|
||||
## Article / BlogPosting / NewsArticle Schema
|
||||
|
||||
For blog posts, articles, and news content.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BlogPosting",
|
||||
"headline": "[Article title - max 110 characters for best display]",
|
||||
"description": "[Article summary or excerpt]",
|
||||
"image": [
|
||||
"[Featured image URL - 1200px wide recommended]",
|
||||
"[Alternative image URL - 4:3 ratio]",
|
||||
"[Alternative image URL - 16:9 ratio]"
|
||||
],
|
||||
"datePublished": "[ISO 8601 date: 2024-01-15T08:00:00+00:00]",
|
||||
"dateModified": "[ISO 8601 date - same as published if never modified]",
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "[Author Full Name]",
|
||||
"url": "[Author profile URL]",
|
||||
"jobTitle": "[Author job title - optional]"
|
||||
},
|
||||
"publisher": {
|
||||
"@type": "Organization",
|
||||
"name": "[Publisher/Company Name]",
|
||||
"logo": {
|
||||
"@type": "ImageObject",
|
||||
"url": "[Publisher logo URL - max 600px wide, 60px high]",
|
||||
"width": "[width]",
|
||||
"height": "[height]"
|
||||
}
|
||||
},
|
||||
"mainEntityOfPage": {
|
||||
"@type": "WebPage",
|
||||
"@id": "[Canonical URL of this article]"
|
||||
},
|
||||
"articleBody": "[Full article text - optional but recommended]",
|
||||
"wordCount": "[word count - optional]"
|
||||
}
|
||||
```
|
||||
|
||||
**Type variants**: Use `Article` for general articles, `BlogPosting` for blog posts, `NewsArticle` for news content, `TechArticle` for technical documentation.
|
||||
|
||||
---
|
||||
|
||||
## Product Schema
|
||||
|
||||
For e-commerce product pages.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Product",
|
||||
"name": "[Product Name]",
|
||||
"image": [
|
||||
"[Product image URL 1]",
|
||||
"[Product image URL 2]",
|
||||
"[Product image URL 3]"
|
||||
],
|
||||
"description": "[Product description]",
|
||||
"sku": "[SKU code]",
|
||||
"mpn": "[Manufacturer Part Number - optional]",
|
||||
"brand": {
|
||||
"@type": "Brand",
|
||||
"name": "[Brand Name]"
|
||||
},
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"url": "[Product page URL]",
|
||||
"priceCurrency": "USD",
|
||||
"price": "[Price as number: 29.99]",
|
||||
"priceValidUntil": "[Date price is valid until: 2024-12-31]",
|
||||
"availability": "https://schema.org/InStock",
|
||||
"seller": {
|
||||
"@type": "Organization",
|
||||
"name": "[Seller/Store Name]"
|
||||
},
|
||||
"shippingDetails": {
|
||||
"@type": "OfferShippingDetails",
|
||||
"shippingRate": {
|
||||
"@type": "MonetaryAmount",
|
||||
"value": "[shipping cost]",
|
||||
"currency": "USD"
|
||||
},
|
||||
"shippingDestination": {
|
||||
"@type": "DefinedRegion",
|
||||
"addressCountry": "US"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aggregateRating": {
|
||||
"@type": "AggregateRating",
|
||||
"ratingValue": "[4.5]",
|
||||
"reviewCount": "[89]",
|
||||
"bestRating": "5",
|
||||
"worstRating": "1"
|
||||
},
|
||||
"review": [
|
||||
{
|
||||
"@type": "Review",
|
||||
"reviewRating": {
|
||||
"@type": "Rating",
|
||||
"ratingValue": "[5]",
|
||||
"bestRating": "5"
|
||||
},
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "[Reviewer Name]"
|
||||
},
|
||||
"reviewBody": "[Review text]",
|
||||
"datePublished": "[Review date: 2024-01-15]"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Availability options**: `InStock`, `OutOfStock`, `PreOrder`, `Discontinued`, `LimitedAvailability`, `OnlineOnly`, `InStoreOnly`, `SoldOut`
|
||||
|
||||
---
|
||||
|
||||
## LocalBusiness Schema
|
||||
|
||||
For local business pages with physical locations.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "LocalBusiness",
|
||||
"name": "[Business Name]",
|
||||
"image": "[Business image or logo URL]",
|
||||
"@id": "[Business page URL]",
|
||||
"url": "[Website URL]",
|
||||
"telephone": "[Phone number: +1-555-555-5555]",
|
||||
"priceRange": "[$$$ or price range like $10-$50]",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"streetAddress": "[Street address]",
|
||||
"addressLocality": "[City]",
|
||||
"addressRegion": "[State/Province]",
|
||||
"postalCode": "[ZIP/Postal code]",
|
||||
"addressCountry": "US"
|
||||
},
|
||||
"geo": {
|
||||
"@type": "GeoCoordinates",
|
||||
"latitude": "[latitude as number: 40.7128]",
|
||||
"longitude": "[longitude as number: -74.0060]"
|
||||
},
|
||||
"openingHoursSpecification": [
|
||||
{
|
||||
"@type": "OpeningHoursSpecification",
|
||||
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
|
||||
"opens": "09:00",
|
||||
"closes": "17:00"
|
||||
},
|
||||
{
|
||||
"@type": "OpeningHoursSpecification",
|
||||
"dayOfWeek": "Saturday",
|
||||
"opens": "10:00",
|
||||
"closes": "15:00"
|
||||
}
|
||||
],
|
||||
"aggregateRating": {
|
||||
"@type": "AggregateRating",
|
||||
"ratingValue": "[4.5]",
|
||||
"reviewCount": "[123]"
|
||||
},
|
||||
"servesCuisine": "[Cuisine type - for restaurants only]"
|
||||
}
|
||||
```
|
||||
|
||||
**Type variants**: Use more specific types when applicable: `Restaurant`, `Store`, `AutoRepair`, `HealthAndBeautyBusiness`, `LegalService`, etc.
|
||||
|
||||
---
|
||||
|
||||
## Organization Schema
|
||||
|
||||
For brand/company homepage.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
"name": "[Organization Name]",
|
||||
"url": "[Website URL]",
|
||||
"logo": "[Logo URL - recommended 112x112px or larger]",
|
||||
"description": "[Company description]",
|
||||
"sameAs": [
|
||||
"[Facebook URL]",
|
||||
"[Twitter URL]",
|
||||
"[LinkedIn URL]",
|
||||
"[Instagram URL]",
|
||||
"[YouTube URL]"
|
||||
],
|
||||
"contactPoint": {
|
||||
"@type": "ContactPoint",
|
||||
"telephone": "[Phone number]",
|
||||
"contactType": "customer service",
|
||||
"email": "[Email address]",
|
||||
"availableLanguage": ["English", "Spanish"],
|
||||
"areaServed": "US"
|
||||
},
|
||||
"founder": {
|
||||
"@type": "Person",
|
||||
"name": "[Founder name - optional]"
|
||||
},
|
||||
"foundingDate": "[YYYY-MM-DD - optional]",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"streetAddress": "[Street address]",
|
||||
"addressLocality": "[City]",
|
||||
"addressRegion": "[State]",
|
||||
"postalCode": "[ZIP]",
|
||||
"addressCountry": "US"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## BreadcrumbList Schema
|
||||
|
||||
For navigation breadcrumbs.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
"itemListElement": [
|
||||
{
|
||||
"@type": "ListItem",
|
||||
"position": 1,
|
||||
"name": "Home",
|
||||
"item": "[Homepage URL]"
|
||||
},
|
||||
{
|
||||
"@type": "ListItem",
|
||||
"position": 2,
|
||||
"name": "[Category Name]",
|
||||
"item": "[Category URL]"
|
||||
},
|
||||
{
|
||||
"@type": "ListItem",
|
||||
"position": 3,
|
||||
"name": "[Subcategory Name]",
|
||||
"item": "[Subcategory URL]"
|
||||
},
|
||||
{
|
||||
"@type": "ListItem",
|
||||
"position": 4,
|
||||
"name": "[Current Page Name]",
|
||||
"item": "[Current Page URL]"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Important**: Position numbers must be sequential starting from 1. Last item should be the current page.
|
||||
|
||||
---
|
||||
|
||||
## VideoObject Schema
|
||||
|
||||
For video content.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "VideoObject",
|
||||
"name": "[Video title]",
|
||||
"description": "[Video description]",
|
||||
"thumbnailUrl": "[Video thumbnail URL - minimum 160x90px]",
|
||||
"uploadDate": "[ISO 8601 date: 2024-01-15T08:00:00+00:00]",
|
||||
"duration": "PT[X]M[Y]S",
|
||||
"contentUrl": "[Video file URL]",
|
||||
"embedUrl": "[Video embed URL]",
|
||||
"interactionStatistic": {
|
||||
"@type": "InteractionCounter",
|
||||
"interactionType": { "@type": "WatchAction" },
|
||||
"userInteractionCount": "[view count]"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Duration format**: PT[X]M[Y]S where X = minutes, Y = seconds. Example: PT5M30S = 5 minutes 30 seconds.
|
||||
|
||||
---
|
||||
|
||||
## Event Schema
|
||||
|
||||
For events, conferences, concerts, etc.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Event",
|
||||
"name": "[Event Name]",
|
||||
"description": "[Event description]",
|
||||
"image": "[Event image URL]",
|
||||
"startDate": "[ISO 8601 date: 2024-06-15T19:00:00-05:00]",
|
||||
"endDate": "[ISO 8601 date: 2024-06-15T22:00:00-05:00]",
|
||||
"eventStatus": "https://schema.org/EventScheduled",
|
||||
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
|
||||
"location": {
|
||||
"@type": "Place",
|
||||
"name": "[Venue Name]",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"streetAddress": "[Street address]",
|
||||
"addressLocality": "[City]",
|
||||
"addressRegion": "[State]",
|
||||
"postalCode": "[ZIP]",
|
||||
"addressCountry": "US"
|
||||
}
|
||||
},
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"url": "[Ticket purchase URL]",
|
||||
"price": "[ticket price]",
|
||||
"priceCurrency": "USD",
|
||||
"availability": "https://schema.org/InStock",
|
||||
"validFrom": "[Sale start date]"
|
||||
},
|
||||
"organizer": {
|
||||
"@type": "Organization",
|
||||
"name": "[Organizer name]",
|
||||
"url": "[Organizer website]"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Event status options**: `EventScheduled`, `EventCancelled`, `EventPostponed`, `EventRescheduled`, `EventMovedOnline`
|
||||
|
||||
**Attendance mode**: `OfflineEventAttendanceMode`, `OnlineEventAttendanceMode`, `MixedEventAttendanceMode`
|
||||
|
||||
---
|
||||
|
||||
## Course Schema
|
||||
|
||||
For online courses and educational content.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Course",
|
||||
"name": "[Course Name]",
|
||||
"description": "[Course description]",
|
||||
"provider": {
|
||||
"@type": "Organization",
|
||||
"name": "[Provider name]",
|
||||
"sameAs": "[Provider URL]"
|
||||
},
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"category": "Paid",
|
||||
"price": "[price]",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"hasCourseInstance": {
|
||||
"@type": "CourseInstance",
|
||||
"courseMode": "online",
|
||||
"courseWorkload": "PT[X]H",
|
||||
"instructor": {
|
||||
"@type": "Person",
|
||||
"name": "[Instructor name]"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recipe Schema
|
||||
|
||||
For cooking recipes.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Recipe",
|
||||
"name": "[Recipe name]",
|
||||
"image": "[Recipe image URL]",
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "[Author name]"
|
||||
},
|
||||
"datePublished": "[ISO 8601 date]",
|
||||
"description": "[Recipe description]",
|
||||
"prepTime": "PT[X]M",
|
||||
"cookTime": "PT[X]M",
|
||||
"totalTime": "PT[X]M",
|
||||
"recipeYield": "[Servings: e.g., '4 servings']",
|
||||
"recipeCategory": "[Category: e.g., 'Dinner']",
|
||||
"recipeCuisine": "[Cuisine: e.g., 'Italian']",
|
||||
"keywords": "[comma, separated, keywords]",
|
||||
"nutrition": {
|
||||
"@type": "NutritionInformation",
|
||||
"calories": "[calories per serving]"
|
||||
},
|
||||
"recipeIngredient": [
|
||||
"[Ingredient 1 with quantity]",
|
||||
"[Ingredient 2 with quantity]",
|
||||
"[Ingredient 3 with quantity]"
|
||||
],
|
||||
"recipeInstructions": [
|
||||
{
|
||||
"@type": "HowToStep",
|
||||
"text": "[Step 1 instructions]"
|
||||
},
|
||||
{
|
||||
"@type": "HowToStep",
|
||||
"text": "[Step 2 instructions]"
|
||||
}
|
||||
],
|
||||
"aggregateRating": {
|
||||
"@type": "AggregateRating",
|
||||
"ratingValue": "[4.5]",
|
||||
"reviewCount": "[number of reviews]"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SoftwareApplication Schema
|
||||
|
||||
For software, apps, and tools.
|
||||
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
"name": "[Software name]",
|
||||
"operatingSystem": "[Windows, macOS, iOS, Android, Web]",
|
||||
"applicationCategory": "BusinessApplication",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "[price or 0 for free]",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"aggregateRating": {
|
||||
"@type": "AggregateRating",
|
||||
"ratingValue": "[4.5]",
|
||||
"reviewCount": "[number of reviews]"
|
||||
},
|
||||
"screenshot": "[Screenshot URL - optional]",
|
||||
"softwareVersion": "[version number]",
|
||||
"fileSize": "[file size with units: e.g., '50MB']",
|
||||
"datePublished": "[Release date]",
|
||||
"downloadUrl": "[Download URL - optional]"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Multiple Schema Types (Combined Array)
|
||||
|
||||
To include multiple schema types on one page, wrap them in an array:
|
||||
|
||||
```html
|
||||
<script type="application/ld+json">
|
||||
[
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
"headline": "[Article title]",
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "[Author]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
"mainEntity": [
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "[Question]",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "[Answer]"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
"itemListElement": [
|
||||
{
|
||||
"@type": "ListItem",
|
||||
"position": 1,
|
||||
"name": "Home",
|
||||
"item": "[URL]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Always validate schema at https://validator.schema.org/ and https://search.google.com/test/rich-results
|
||||
- Remove bracketed placeholders and replace with actual content
|
||||
- Use absolute URLs, not relative paths
|
||||
- Dates must be in ISO 8601 format
|
||||
- Schema must match visible page content (Google policy requirement)
|
||||
- No trailing commas in JSON (invalid syntax)
|
||||
|
|
@ -0,0 +1,444 @@
|
|||
# Schema Markup Validation Guide
|
||||
|
||||
Complete reference for validating, testing, and troubleshooting structured data.
|
||||
|
||||
## Validation Tools
|
||||
|
||||
### Google Rich Results Test
|
||||
- **URL**: https://search.google.com/test/rich-results
|
||||
- **Purpose**: Check if your schema is eligible for Google rich results
|
||||
- **Tests**: Live URL or code snippet
|
||||
- **Output**: Errors, warnings, eligible rich result types
|
||||
|
||||
### Schema.org Validator
|
||||
- **URL**: https://validator.schema.org/
|
||||
- **Purpose**: Validate against official Schema.org specification
|
||||
- **Tests**: URL, code snippet, or microdata
|
||||
- **Output**: Technical validation errors
|
||||
|
||||
### Google Search Console
|
||||
- **Location**: Search Console → Enhancements section
|
||||
- **Purpose**: Monitor rich results performance and errors at scale
|
||||
- **Reports**: Rich results status, coverage, issues over time
|
||||
|
||||
---
|
||||
|
||||
## Common JSON-LD Syntax Errors
|
||||
|
||||
### Trailing Commas
|
||||
|
||||
**Error**: Invalid JSON syntax
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
"headline": "Title", ← Trailing comma here
|
||||
}
|
||||
```
|
||||
|
||||
**Fix**: Remove the comma after the last property
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
"headline": "Title"
|
||||
}
|
||||
```
|
||||
|
||||
### Missing Required Quotes
|
||||
|
||||
**Error**: Property names must be quoted
|
||||
```json
|
||||
{
|
||||
@context: "https://schema.org"
|
||||
}
|
||||
```
|
||||
|
||||
**Fix**: Quote all property names
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org"
|
||||
}
|
||||
```
|
||||
|
||||
### Incorrect Date Format
|
||||
|
||||
**Error**: Invalid date format
|
||||
```json
|
||||
{
|
||||
"datePublished": "01/15/2024"
|
||||
}
|
||||
```
|
||||
|
||||
**Fix**: Use ISO 8601 format
|
||||
```json
|
||||
{
|
||||
"datePublished": "2024-01-15T08:00:00+00:00"
|
||||
}
|
||||
```
|
||||
|
||||
### Relative URLs Instead of Absolute
|
||||
|
||||
**Error**: Relative URLs are not allowed
|
||||
```json
|
||||
{
|
||||
"image": "/images/photo.jpg"
|
||||
}
|
||||
```
|
||||
|
||||
**Fix**: Use absolute URLs
|
||||
```json
|
||||
{
|
||||
"image": "https://example.com/images/photo.jpg"
|
||||
}
|
||||
```
|
||||
|
||||
### Incorrect Array Syntax
|
||||
|
||||
**Error**: Multiple values not in array
|
||||
```json
|
||||
{
|
||||
"image": "url1.jpg", "url2.jpg"
|
||||
}
|
||||
```
|
||||
|
||||
**Fix**: Use array brackets for multiple values
|
||||
```json
|
||||
{
|
||||
"image": ["url1.jpg", "url2.jpg"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Required vs Recommended Properties
|
||||
|
||||
### FAQPage Schema
|
||||
|
||||
| Property | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| @type | Required | Must be "FAQPage" |
|
||||
| mainEntity | Required | Array of Question objects |
|
||||
| Question.name | Required | The question text |
|
||||
| Answer.text | Required | The answer text |
|
||||
|
||||
**Minimum**: 2 Q&A pairs
|
||||
|
||||
### HowTo Schema
|
||||
|
||||
| Property | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| @type | Required | Must be "HowTo" |
|
||||
| name | Required | Title of the how-to |
|
||||
| step | Required | Array of HowToStep objects |
|
||||
| step.text | Required | Step instructions |
|
||||
| image | Recommended | Improves visibility |
|
||||
| totalTime | Recommended | Shows duration in results |
|
||||
| supply | Recommended | Lists materials needed |
|
||||
| tool | Recommended | Lists tools needed |
|
||||
|
||||
**Minimum**: 2 steps with text
|
||||
|
||||
### Article Schema
|
||||
|
||||
| Property | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| @type | Required | Article/BlogPosting/NewsArticle |
|
||||
| headline | Required | Max 110 characters |
|
||||
| image | Required | Minimum 1200px wide |
|
||||
| datePublished | Required | ISO 8601 format |
|
||||
| author | Required | Person or Organization |
|
||||
| publisher | Required | Organization with logo |
|
||||
| publisher.logo | Required | Max 600px wide, 60px high |
|
||||
| dateModified | Recommended | Update when content changes |
|
||||
| description | Recommended | Improves display |
|
||||
|
||||
### Product Schema
|
||||
|
||||
| Property | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| @type | Required | Must be "Product" |
|
||||
| name | Required | Product name |
|
||||
| image | Required | Product images |
|
||||
| description | Recommended | Product description |
|
||||
| offers | Recommended | Required for price display |
|
||||
| offers.price | Recommended | Required for price display |
|
||||
| offers.priceCurrency | Recommended | Required for price display |
|
||||
| offers.availability | Recommended | Stock status |
|
||||
| aggregateRating | Recommended | Required for star ratings |
|
||||
| review | Recommended | Individual reviews |
|
||||
| sku | Recommended | Product identifier |
|
||||
| brand | Recommended | Brand information |
|
||||
|
||||
### LocalBusiness Schema
|
||||
|
||||
| Property | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| @type | Required | LocalBusiness or subtype |
|
||||
| name | Required | Business name |
|
||||
| address | Required | PostalAddress object |
|
||||
| address.streetAddress | Required | Street address |
|
||||
| address.addressLocality | Required | City |
|
||||
| address.addressRegion | Required | State/province |
|
||||
| address.postalCode | Required | ZIP/postal code |
|
||||
| address.addressCountry | Required | Country code |
|
||||
| geo | Recommended | Latitude/longitude |
|
||||
| telephone | Recommended | Phone number |
|
||||
| openingHoursSpecification | Recommended | Business hours |
|
||||
| priceRange | Recommended | Price range indicator |
|
||||
| aggregateRating | Recommended | Customer ratings |
|
||||
|
||||
### Organization Schema
|
||||
|
||||
| Property | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| @type | Required | Must be "Organization" |
|
||||
| name | Required | Organization name |
|
||||
| url | Required | Website URL |
|
||||
| logo | Recommended | Brand logo |
|
||||
| sameAs | Recommended | Social media profiles |
|
||||
| contactPoint | Recommended | Contact information |
|
||||
|
||||
---
|
||||
|
||||
## Google Rich Result Eligibility Requirements
|
||||
|
||||
### FAQ Rich Results
|
||||
|
||||
**Eligibility checklist**:
|
||||
- [ ] Minimum 2 Q&A pairs
|
||||
- [ ] Questions are actual questions (contain "?")
|
||||
- [ ] Answers are complete and comprehensive
|
||||
- [ ] Content matches visible page content exactly
|
||||
- [ ] Not a forum or Q&A page where users can submit answers
|
||||
- [ ] Not advertising or promotional in nature
|
||||
- [ ] Not for medical, legal, or financial advice without proper E-E-A-T
|
||||
|
||||
**Ineligible content**:
|
||||
- Medical advice without credentials
|
||||
- Legal advice
|
||||
- Product/service comparisons that are promotional
|
||||
- User-generated Q&A (use QAPage instead)
|
||||
|
||||
### How-To Rich Results
|
||||
|
||||
**Eligibility checklist**:
|
||||
- [ ] Minimum 2 steps with clear instructions
|
||||
- [ ] Complete process from start to finish
|
||||
- [ ] Each step has meaningful text (not just a title)
|
||||
- [ ] Not advertising or promotional
|
||||
- [ ] Not harmful or dangerous content
|
||||
- [ ] Steps are actionable and practical
|
||||
|
||||
**Ineligible content**:
|
||||
- Single-step processes
|
||||
- Recipes (use Recipe schema instead)
|
||||
- Promotional tutorials
|
||||
|
||||
### Product Rich Results
|
||||
|
||||
**For price display**:
|
||||
- [ ] Valid Product schema
|
||||
- [ ] `offers` with `price` property
|
||||
- [ ] `priceCurrency` specified
|
||||
- [ ] `availability` status
|
||||
|
||||
**For review stars**:
|
||||
- [ ] Valid `aggregateRating` OR individual `review`
|
||||
- [ ] Minimum 1 review for individual review display
|
||||
- [ ] Honest, unbiased reviews (not paid/incentivized)
|
||||
|
||||
**For product markup**:
|
||||
- [ ] `name` property present
|
||||
- [ ] At least one `image`
|
||||
- [ ] Valid product type (not person, organization, etc.)
|
||||
|
||||
### Article Rich Results
|
||||
|
||||
**Eligibility checklist**:
|
||||
- [ ] Valid Article/BlogPosting/NewsArticle schema
|
||||
- [ ] High-quality, original content
|
||||
- [ ] Proper `publisher` with valid logo
|
||||
- [ ] Valid `author` information
|
||||
- [ ] Images meet size requirements (1200px wide)
|
||||
- [ ] Not short-form content (minimum ~300 words)
|
||||
|
||||
---
|
||||
|
||||
## Testing Workflow
|
||||
|
||||
### Initial Implementation
|
||||
|
||||
1. **Add schema to development/staging environment**
|
||||
2. **Validate syntax at validator.schema.org**
|
||||
- Paste code or test URL
|
||||
- Fix all errors before proceeding
|
||||
3. **Test at Google Rich Results Test**
|
||||
- Check for Google-specific issues
|
||||
- Verify eligible rich result types
|
||||
4. **Visual inspection**
|
||||
- View page source to confirm schema is present
|
||||
- Check JSON formatting in browser
|
||||
|
||||
### Pre-Launch Testing
|
||||
|
||||
1. **Test on staging URL with Rich Results Test**
|
||||
2. **Verify all required properties present**
|
||||
3. **Confirm content matches visible page content**
|
||||
4. **Check for policy violations**
|
||||
5. **Test multiple schema types if combining**
|
||||
6. **Validate images are accessible and meet size requirements**
|
||||
|
||||
### Post-Launch Monitoring
|
||||
|
||||
1. **Submit sitemap to Google Search Console**
|
||||
2. **Monitor Enhancements reports**
|
||||
- Check for validation errors
|
||||
- Watch for policy violations
|
||||
- Track rich result impressions
|
||||
3. **Re-test pages if content changes**
|
||||
4. **Update `dateModified` when updating content**
|
||||
5. **Fix errors within 30 days to avoid rich result removal**
|
||||
|
||||
---
|
||||
|
||||
## Common Policy Violations
|
||||
|
||||
### Content Mismatch
|
||||
|
||||
**Violation**: Schema content doesn't match visible page content
|
||||
|
||||
**Example**: FAQ schema includes Q&A pairs not visible on page
|
||||
|
||||
**Fix**: Ensure all structured data reflects actual page content exactly
|
||||
|
||||
### Deceptive Content
|
||||
|
||||
**Violation**: Schema contains misleading information
|
||||
|
||||
**Example**: Product reviews that are fake or incentivized
|
||||
|
||||
**Fix**: Only include genuine, verifiable information
|
||||
|
||||
### Spammy Markup
|
||||
|
||||
**Violation**: Excessive or irrelevant schema
|
||||
|
||||
**Example**: Adding Product schema to every blog post
|
||||
|
||||
**Fix**: Only use schema types relevant to page content
|
||||
|
||||
### Hidden Content
|
||||
|
||||
**Violation**: Schema references content hidden from users
|
||||
|
||||
**Example**: FAQ answers only in schema, not visible on page
|
||||
|
||||
**Fix**: Make all schema content visible to users
|
||||
|
||||
### Promotional Content in FAQ
|
||||
|
||||
**Violation**: Using FAQ schema for promotional purposes
|
||||
|
||||
**Example**: Questions like "Why is [Brand] the best?"
|
||||
|
||||
**Fix**: Use neutral, informational questions
|
||||
|
||||
---
|
||||
|
||||
## Debugging Common Issues
|
||||
|
||||
### Schema Not Appearing in Rich Results Test
|
||||
|
||||
**Possible causes**:
|
||||
- JSON syntax error (validate at validator.schema.org)
|
||||
- Schema in incorrect location (should be in `<head>` or `<body>`)
|
||||
- Script tag missing `type="application/ld+json"`
|
||||
- Content served dynamically after page load (bot can't see it)
|
||||
|
||||
**Debug steps**:
|
||||
1. View page source (not inspect element)
|
||||
2. Search for `"@type"`
|
||||
3. Copy JSON to validator.schema.org
|
||||
4. Fix syntax errors
|
||||
|
||||
### Rich Results Not Showing in Search
|
||||
|
||||
**Possible causes**:
|
||||
- Schema is new (can take days/weeks to appear)
|
||||
- Page not indexed by Google
|
||||
- Schema has errors in Search Console
|
||||
- Content doesn't meet quality guidelines
|
||||
- Competition for rich results is high
|
||||
|
||||
**Debug steps**:
|
||||
1. Check Search Console → Enhancements
|
||||
2. Use URL Inspection tool to request indexing
|
||||
3. Verify schema passes Rich Results Test
|
||||
4. Check for manual actions
|
||||
|
||||
### Warnings vs Errors
|
||||
|
||||
**Errors** (must fix):
|
||||
- Invalid syntax
|
||||
- Missing required properties
|
||||
- Invalid property values
|
||||
- Schema type doesn't exist
|
||||
|
||||
**Warnings** (should fix when possible):
|
||||
- Missing recommended properties
|
||||
- Suboptimal property values
|
||||
- Non-standard extensions
|
||||
- Property not recognized for this type
|
||||
|
||||
---
|
||||
|
||||
## Schema Maintenance Checklist
|
||||
|
||||
### Monthly
|
||||
- [ ] Check Search Console for new errors
|
||||
- [ ] Verify rich results are still appearing
|
||||
- [ ] Update `dateModified` on changed content
|
||||
|
||||
### Quarterly
|
||||
- [ ] Audit all schema implementations
|
||||
- [ ] Test key pages with Rich Results Test
|
||||
- [ ] Update any outdated information (prices, dates, etc.)
|
||||
- [ ] Check for new schema types relevant to your content
|
||||
|
||||
### After Content Changes
|
||||
- [ ] Update schema to match new content
|
||||
- [ ] Update `dateModified` timestamp
|
||||
- [ ] Re-validate with Rich Results Test
|
||||
- [ ] Request re-indexing in Search Console if major changes
|
||||
|
||||
### After Site Migration
|
||||
- [ ] Verify schema preserved on new URLs
|
||||
- [ ] Update all absolute URLs in schema
|
||||
- [ ] Submit new sitemap
|
||||
- [ ] Monitor for errors in new domain's Search Console
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference: Error Messages and Fixes
|
||||
|
||||
| Error Message | Cause | Fix |
|
||||
|---------------|-------|-----|
|
||||
| "Missing required field" | Required property not included | Add the required property |
|
||||
| "Invalid date format" | Date not in ISO 8601 | Use format: 2024-01-15T08:00:00+00:00 |
|
||||
| "URL is not absolute" | Relative URL used | Add full URL with https:// |
|
||||
| "Unexpected token" | JSON syntax error | Check for missing quotes, brackets, commas |
|
||||
| "This markup is not eligible for rich results" | Schema type or content doesn't qualify | Review eligibility requirements |
|
||||
| "Image too small" | Image doesn't meet size requirements | Use image at least 1200px wide |
|
||||
| "The attribute price is required" | Product missing price | Add offers.price property |
|
||||
| "Logo must be 600x60 or smaller" | Publisher logo too large | Resize logo to meet requirements |
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
- **Schema.org Documentation**: https://schema.org/
|
||||
- **Google Search Central**: https://developers.google.com/search/docs/appearance/structured-data
|
||||
- **Rich Results Test**: https://search.google.com/test/rich-results
|
||||
- **Schema Validator**: https://validator.schema.org/
|
||||
- **JSON-LD Playground**: https://json-ld.org/playground/
|
||||
Loading…
Add table
Add a link
Reference in a new issue