Recipe Schema Markup: Winning Rich Results in the Food SERP

No Comments

Recipe pages live in one of the most visually aggressive corners of Google Search. Ratings stars, photo carousels, cook times, and calorie counts all sit above the fold, and the structured data behind them is what decides whether your dish shows up or stays invisible. Getting Recipe structured data right is the difference between a blue link and a thumbnail that earns the click.

Why Recipe structured data is non-negotiable in this vertical

Food queries trigger two distinct rich result types: the standard single-recipe rich result (star rating, image, time, reviewer count) and the host carousel, the scrollable strip of recipes from a single site that appears for queries like "chicken thigh recipes." The carousel is gated behind correct markup plus correct page architecture. You cannot win it on content alone.

Google reads recipe data from JSON-LD, Microdata, or RDFa. Use JSON-LD. It decouples your structured data from your rendered HTML, survives template changes, and is the format Google explicitly recommends. Inject it in a <script type="application/ld+json"> block in the <head> or body.

The required and recommended properties

A recipe will not be eligible for any rich result unless the core fields are present and valid. Build from this skeleton:

  • name, the recipe title, not the page title with branding appended.
  • image, multiple high-resolution images in different aspect ratios (1:1, 4:3, 16:9). This is the single most common eligibility blocker. Supply an array of URLs, not a CSS background or a lazy-loaded placeholder.
  • recipeIngredient, one string per ingredient, quantity included ("2 cups all-purpose flour"). Do not merge the full list into one string.
  • recipeInstructions, use an array of HowToStep objects, each with text and ideally a url fragment and image. A single text blob works but forfeits step-level richness and voice-assistant eligibility.

The properties that actually drive the visual upgrades:

  • aggregateRating, drives the stars. Requires ratingValue and either ratingCount or reviewCount. The ratings must be genuine and visible on the page.
  • prepTime, cookTime, totalTime, all in ISO 8601 duration format. Twenty minutes is PT20M; one hour thirty is PT1H30M. If you supply prepTime and cookTime, also supply totalTime, Google does not reliably sum them for you.
  • nutrition, at minimum calories as a NutritionInformation object. Powers the calorie chip.
  • recipeYield, keywords, recipeCategory, recipeCuisine, refine classification and carousel matching.
  • video, a VideoObject with contentUrl or embedUrl earns a video thumbnail badge. Highly worth it in this vertical.

A minimal but complete example

{
 "@context": "https://schema.org/",
 "@type": "Recipe",
 "name": "Weeknight Garlic Butter Chicken",
 "image": [
 "https://example.com/photos/1x1/chicken.jpg",
 "https://example.com/photos/4x3/chicken.jpg",
 "https://example.com/photos/16x9/chicken.jpg"
 ],
 "author": { "@type": "Person", "name": "Dana Reyes" },
 "datePublished": "2026-05-18",
 "prepTime": "PT10M",
 "cookTime": "PT20M",
 "totalTime": "PT30M",
 "recipeYield": "4 servings",
 "recipeCuisine": "American",
 "recipeCategory": "Main course",
 "keywords": "garlic butter chicken, weeknight dinner",
 "nutrition": {
 "@type": "NutritionInformation",
 "calories": "420 calories"
 },
 "recipeIngredient": [
 "4 boneless chicken thighs",
 "3 tablespoons butter",
 "4 cloves garlic, minced"
 ],
 "recipeInstructions": [
 { "@type": "HowToStep", "text": "Sear the chicken 5 minutes per side." },
 { "@type": "HowToStep", "text": "Add butter and garlic; baste for 3 minutes." }
 ],
 "aggregateRating": {
 "@type": "AggregateRating",
 "ratingValue": "4.7",
 "ratingCount": "238"
 }
}

Winning the host carousel

The carousel uses a separate mechanism. You mark up your list page (a "best soup recipes" roundup or a category page) with an ItemList, where each ListItem points by url to a dedicated recipe page that itself carries full Recipe markup. The pattern:

  1. Build a summary or category page with an ordered ItemList.
  2. Give each ListItem a position and a url to a full-page recipe, never a fragment, anchor, or modal.
  3. Ensure every target URL renders its own complete Recipe JSON-LD and returns 200 independently.

The frequent failure here is putting the Recipe markup directly on the list page or pointing list items at on-page anchors. Carousel eligibility demands one canonical recipe per destination URL.

Match the markup to the page, exactly

Google's policy is unambiguous: structured data must reflect content visible to the user. Stars require visible ratings. recipeIngredient entries must match the ingredient list on the page. Inflated rating counts, ingredients that do not appear, or cook times that contradict the body copy are the kinds of mismatches that trigger manual actions and silent suppression. Treat the JSON-LD as a mirror of the rendered DOM, not a wish list.

Common mistakes that kill eligibility

  • Durations in plain English. "30 minutes" is invalid. Only ISO 8601 (PT30M) parses.
  • Low-resolution or single-aspect images. Google wants large images, ideally 1200px wide, in multiple ratios. Thumbnails get you parsed but rarely featured.
  • Lazy-loaded images Google can't fetch. If the image URL only resolves after JavaScript, confirm it renders. Reference a crawlable, absolute URL in the markup.
  • Self-serving or fabricated ratings. Ratings the site assigns to itself are ineligible and risky. Aggregate genuine user reviews.
  • Instructions as one giant string. Use discrete HowToStep items to unlock step segmentation and Assistant read-aloud.
  • Multiple conflicting Recipe blocks. One Recipe entity per page. Plugin-plus-theme double injection is a classic duplicate.
  • Markup present, content blocked. If the recipe body is behind a paywall, a "jump to recipe" interstitial, or noindex, the markup is moot.

Validate, deploy, monitor

Before shipping, run every template through Google's Rich Results Test on the live or rendered HTML, not just a paste of the JSON, since rendering issues hide image and lazy-load problems. Use the Schema Markup Validator (schema.org's own tool) to catch vocabulary errors the Rich Results Test ignores. After deployment, watch the Recipe enhancement report in Search Console: it surfaces invalid items at scale and confirms valid-item growth as Google reprocesses your pages. Eligibility is not a guarantee of display, Google still chooses per query, but invalid markup guarantees you are never in the running.

FAQ

Do I need a separate page per recipe? For carousel eligibility, yes. Each recipe should have its own indexable URL with its own Recipe markup.

Will stars appear if I add aggregateRating? Only if the ratings are real, visible, and Google chooses to show them. Adding the property makes you eligible, not guaranteed.

JSON-LD or Microdata? JSON-LD, every time. It's cleaner to maintain and is Google's stated preference.

Want this handled properly on your site?

It is exactly the kind of work an advanced technical SEO audit covers. See how an advanced SEO audit works →

Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.

    About SEO ProCheck

    Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.

    Work With Me

    Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.

    Subscribe to our newsletter!

    More from our blog