Structured Data Guide

Shopify Recipe Product Schema: Recipe JSON-LD for Meal Kit & Food Stores

Shopify powers thousands of meal kit, food subscription, and specialty grocery stores. When shoppers ask an AI agent "what gluten-free dinners can I make in under 30 minutes?" — those answers come from Recipe structured data, not product descriptions. Here's how to implement Recipe JSON-LD on Shopify product pages.

TL;DR Add a Recipe JSON-LD block alongside your Product block on food product pages. Essential properties: recipeIngredient, recipeInstructions (as HowToStep array), totalTime (ISO 8601), nutrition (NutritionInformation), recipeYield, and suitableForDiet (schema.org RestrictedDiet enumeration). Store recipe data in Shopify metafields and render both blocks in product.liquid.

Why Recipe Schema Matters for Food Stores on Shopify

Food and meal kit queries are among the most common shopping-adjacent questions AI agents receive. When someone asks ChatGPT Shopping or Google's AI Overviews "what meal kits work for a diabetic diet?" or "easy 20-minute family dinners," the answers are constructed from Recipe structured data on product pages — not from marketing copy in product descriptions.

Shopify food stores that omit Recipe JSON-LD miss out on three distinct discovery channels:

Most Shopify meal kit stores have zero Recipe markup. A single implementation session across your product template captures all three channels simultaneously.

Recipe vs. Product: Use Both on the Same Page

A common mistake is choosing one type over the other. Shopify meal kit pages should have both a Product block and a Recipe block as separate <script type="application/ld+json"> elements:

JSON-LD Block Answers Key Properties
Product "How much does this cost? Is it in stock? Where do I buy it?" name, Offer (price, priceCurrency, availability), AggregateRating, image, brand
Recipe "What do I make? How long does it take? What are the ingredients? Is it gluten-free?" recipeIngredient, recipeInstructions, totalTime, nutrition, suitableForDiet, recipeYield

Google and AI agents process both blocks independently. The Product block drives purchase-intent results; the Recipe block drives culinary-intent results. Neither replaces the other.

Recipe Schema Properties Reference

Property Type Description Required for Google
name Text Recipe name — typically product title for meal kits Yes
image ImageObject or URL Product/dish image — drives recipe carousel appearance Yes
author Organization or Person Recipe creator — your brand or a named chef Yes
recipeIngredient Array of Text Each ingredient as a string: "2 cloves garlic, minced" Recommended
recipeInstructions Array of HowToStep Step-by-step cooking instructions with text, position, name Recommended
totalTime Duration (ISO 8601) Total time including prep + cook: "PT45M" Recommended
prepTime Duration (ISO 8601) Active preparation time before cooking: "PT15M" Recommended
cookTime Duration (ISO 8601) Passive cooking time: "PT30M" Recommended
recipeYield Text Servings: "2 servings" or "4 portions" Recommended
nutrition NutritionInformation calories, proteinContent, carbohydrateContent, fatContent Optional (high value)
suitableForDiet RestrictedDiet URL e.g. "https://schema.org/GlutenFreeDiet" Optional (high value)
recipeCuisine Text "Italian", "Thai", "Mexican" — drives cuisine-type queries Optional
recipeCategory Text "Dinner", "Lunch", "Breakfast", "Appetizer" Optional
cookingMethod Text "Baking", "Grilling", "Stovetop" — method-specific queries Optional
keywords Text Comma-separated keywords for topical relevance Optional

NutritionInformation Properties

The nutrition property takes a NutritionInformation object. AI agents querying "low-calorie dinner kits" or "high-protein meal prep" rely on these values:

Property Unit Example
caloriesText (kcal string)"450 calories"
proteinContentText (grams)"32 g"
carbohydrateContentText (grams)"28 g"
fatContentText (grams)"18 g"
saturatedFatContentText (grams)"4 g"
sodiumContentText (milligrams)"620 mg"
fiberContentText (grams)"6 g"
sugarContentText (grams)"8 g"
servingSizeText"1 serving (340g)"

Recipe JSON-LD Example: Meal Kit Product Page

{
  "@context": "https://schema.org",
  "@type": "Recipe",
  "name": "Lemon Herb Salmon with Roasted Asparagus",
  "description": "A restaurant-quality salmon dinner kit for two — pre-portioned and ready to cook. Wild-caught Alaskan salmon, fresh asparagus, lemon-herb compound butter, and jasmine rice. On the table in 25 minutes.",
  "image": [
    "https://your-store.myshopify.com/cdn/shop/products/salmon-kit-hero.jpg"
  ],
  "author": {
    "@type": "Organization",
    "name": "FreshTable Meal Kits",
    "url": "https://your-store.myshopify.com"
  },
  "datePublished": "2026-01-15",
  "prepTime": "PT10M",
  "cookTime": "PT20M",
  "totalTime": "PT30M",
  "recipeYield": "2 servings",
  "recipeCategory": "Dinner",
  "recipeCuisine": "American",
  "cookingMethod": "Pan Sear",
  "keywords": "salmon dinner kit, easy weeknight dinner, meal kit, gluten free dinner",
  "suitableForDiet": [
    "https://schema.org/GlutenFreeDiet",
    "https://schema.org/LowLactoseDiet"
  ],
  "recipeIngredient": [
    "2 × 6oz wild-caught Alaskan salmon fillets",
    "1 bunch fresh asparagus, trimmed",
    "1 cup jasmine rice",
    "2 tbsp lemon-herb compound butter",
    "1 lemon, sliced",
    "2 cloves garlic, minced",
    "2 tbsp olive oil",
    "Salt and black pepper to taste"
  ],
  "recipeInstructions": [
    {
      "@type": "HowToStep",
      "position": 1,
      "name": "Cook the rice",
      "text": "Combine 1 cup jasmine rice with 1.5 cups water in a saucepan. Bring to boil, reduce heat to low, cover and simmer 15 minutes."
    },
    {
      "@type": "HowToStep",
      "position": 2,
      "name": "Roast the asparagus",
      "text": "Toss asparagus with 1 tbsp olive oil, salt, and pepper. Spread on a baking sheet and roast at 400°F for 10-12 minutes until tender-crisp."
    },
    {
      "@type": "HowToStep",
      "position": 3,
      "name": "Sear the salmon",
      "text": "Pat salmon dry and season with salt and pepper. Heat 1 tbsp olive oil in a skillet over medium-high heat. Cook salmon skin-side up for 4 minutes, flip, add garlic and butter, and cook 3-4 more minutes basting with pan juices."
    },
    {
      "@type": "HowToStep",
      "position": 4,
      "name": "Plate and serve",
      "text": "Divide rice between plates. Add salmon and asparagus. Garnish with lemon slices and fresh herbs from the compound butter."
    }
  ],
  "nutrition": {
    "@type": "NutritionInformation",
    "servingSize": "1 serving (480g)",
    "calories": "520 calories",
    "proteinContent": "42 g",
    "carbohydrateContent": "38 g",
    "fatContent": "18 g",
    "saturatedFatContent": "5 g",
    "sodiumContent": "480 mg",
    "fiberContent": "4 g",
    "sugarContent": "3 g"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.8",
    "reviewCount": "312",
    "bestRating": "5"
  }
}

Shopify Liquid Implementation

Store recipe data in a recipe metafield namespace, then render both Product and Recipe JSON-LD blocks from product.liquid. The conditional check on metafield presence ensures non-food products are unaffected:

{% comment %} product.liquid — Recipe JSON-LD for food/meal-kit products {% endcomment %}

{% assign recipe_ingredients = product.metafields.recipe.ingredients.value %}
{% if recipe_ingredients %}
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Recipe",
  "name": {{ product.title | json }},
  "description": {{ product.description | strip_html | truncate: 600 | json }},
  "image": [
    {% for image in product.images limit:3 %}
    "https://{{ shop.domain }}{{ image | image_url: width: 1200 }}"{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ],
  "author": {
    "@type": "Organization",
    "name": {{ shop.name | json }},
    "url": "https://{{ shop.domain }}"
  },
  "datePublished": {{ product.created_at | date: "%Y-%m-%d" | json }},
  "prepTime": {{ product.metafields.recipe.prep_time.value | default: "PT0M" | json }},
  "cookTime": {{ product.metafields.recipe.cook_time.value | default: "PT0M" | json }},
  "totalTime": {{ product.metafields.recipe.total_time.value | default: "PT30M" | json }},
  "recipeYield": {{ product.metafields.recipe.servings.value | append: " servings" | json }},
  "recipeCategory": {{ product.metafields.recipe.category.value | default: product.type | json }},
  "recipeCuisine": {{ product.metafields.recipe.cuisine.value | json }},
  "cookingMethod": {{ product.metafields.recipe.cooking_method.value | json }},
  "recipeIngredient": {{ recipe_ingredients | json }},
  {% assign instructions_json = product.metafields.recipe.instructions.value %}
  {% if instructions_json %}
  "recipeInstructions": {{ instructions_json }},
  {% endif %}
  {% assign calories = product.metafields.recipe.calories.value %}
  {% if calories %}
  "nutrition": {
    "@type": "NutritionInformation",
    "servingSize": {{ product.metafields.recipe.serving_size.value | json }},
    "calories": {{ calories | append: " calories" | json }},
    "proteinContent": {{ product.metafields.recipe.protein_g.value | append: " g" | json }},
    "carbohydrateContent": {{ product.metafields.recipe.carbs_g.value | append: " g" | json }},
    "fatContent": {{ product.metafields.recipe.fat_g.value | append: " g" | json }},
    "sodiumContent": {{ product.metafields.recipe.sodium_mg.value | append: " mg" | json }}
  },
  {% endif %}
  {% assign diets = product.metafields.recipe.suitable_diets.value %}
  {% if diets.size > 0 %}
  "suitableForDiet": {{ diets | json }},
  {% endif %}
  {% if product.metafields.reviews.rating %}
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "{{ product.metafields.reviews.rating.value }}",
    "reviewCount": "{{ product.metafields.reviews.rating_count.value }}"
  }
  {% endif %}
}
</script>
{% endif %}

Required metafields for recipe products

Metafield key Type Example value
recipe.ingredientsList of single-line text["2 × 6oz salmon fillets", "1 bunch asparagus", ...]
recipe.instructionsJSON (multi-line text)[{"@type":"HowToStep","position":1,"name":"...","text":"..."}]
recipe.total_timeSingle-line text"PT30M" (ISO 8601)
recipe.prep_timeSingle-line text"PT10M"
recipe.cook_timeSingle-line text"PT20M"
recipe.servingsInteger2
recipe.categorySingle-line text"Dinner"
recipe.cuisineSingle-line text"American"
recipe.cooking_methodSingle-line text"Pan Sear"
recipe.caloriesInteger520
recipe.protein_gInteger42
recipe.carbs_gInteger38
recipe.fat_gInteger18
recipe.sodium_mgInteger480
recipe.serving_sizeSingle-line text"1 serving (480g)"
recipe.suitable_dietsList of single-line text["https://schema.org/GlutenFreeDiet"]

suitableForDiet: Schema.org RestrictedDiet Values

Diet Type Schema.org Value When to Use
Gluten-freehttps://schema.org/GlutenFreeDietNo gluten-containing ingredients; suitable for celiac
Veganhttps://schema.org/VeganDietNo animal products whatsoever
Vegetarianhttps://schema.org/VegetarianDietNo meat/fish; may include dairy and eggs
Kosherhttps://schema.org/KosherDietCertified kosher ingredients and preparation
Halalhttps://schema.org/HalalDietMeets halal dietary standards
Diabetichttps://schema.org/DiabeticDietLow glycemic index, suitable for diabetes management
Low fathttps://schema.org/LowFatDietLess than 30% calories from fat per serving
Low lactosehttps://schema.org/LowLactoseDietMinimal lactose; lactose-intolerant friendly
Low salthttps://schema.org/LowSaltDietLow sodium content (<600mg per serving)

Common Recipe Schema Mistakes on Shopify

Mistake Effect Fix
Using Recipe @type instead of Product @type, or omitting Product entirely Loses purchase signals — AI agents can't surface your kit as a buyable product Always include both Product and Recipe JSON-LD blocks on meal kit pages
Putting ISO 8601 duration values as plain numbers ("30") instead of duration strings ("PT30M") Google validates this as an error; duration rich results suppressed Format all time values as ISO 8601: P(n)T(n)H(n)M(n)S — "PT30M" = 30 minutes
Omitting recipeInstructions or using a plain string instead of HowToStep array Structured instructions not extractable; AI agents can't enumerate steps Use an array of HowToStep objects with position, name, and text fields
Skipping suitableForDiet even for clearly dietary-specific products Invisible in dietary-filter queries ("gluten-free dinner kit") — highest-intent food queries Add suitableForDiet array with all applicable RestrictedDiet enum values
Adding Recipe markup to non-recipe products (clothing, electronics) Google manual action risk; structured data guidelines require relevant recipe content Gate Recipe JSON-LD output on presence of recipe.ingredients metafield

CatalogScan Recipe Schema Checks

CatalogScan's AI Readiness scan detects Shopify stores in food, meal kit, grocery, and specialty beverage categories and checks whether product pages include Recipe structured data alongside Product blocks. Stores missing Recipe markup on food products receive a recipe-signal gap warning. The scan validates: recipeIngredient presence, recipeInstructions structure (HowToStep objects vs. plain string), suitableForDiet coverage, and ISO 8601 format compliance on time fields.

Related guides: Food & beverage NutritionInformation schema · Product FAQ schema for pre-purchase queries · Ecommerce product schema markup overview · Shopify schema markup guide

FAQ

Should I use Recipe or Product schema for a Shopify meal kit?

Use both. Include a Product block (price, availability, AggregateRating) and a Recipe block (ingredients, instructions, nutrition, suitableForDiet) as separate JSON-LD scripts on the same page. Each block serves a different discovery channel — Product drives purchase-intent results; Recipe drives culinary and dietary-intent results.

What Recipe properties help AI shopping agents the most?

recipeIngredient (ingredient lists for allergy/preference queries), suitableForDiet (dietary restriction filtering), nutrition.calories (calorie-range queries), totalTime (cook-time filtering), and recipeInstructions as HowToStep objects (step enumeration). These six properties together cover most AI food-intent queries.

How do I implement Recipe schema at scale on Shopify?

Store all recipe data in a 'recipe' metafield namespace (ingredients as list, instructions as JSON, time values as ISO 8601 strings, nutrition fields as integers). In product.liquid, check for recipe.ingredients metafield presence and conditionally render the Recipe JSON-LD block. This scopes recipe markup to food products only.

Does Google show recipe rich results for Shopify product pages?

Yes. Google shows Recipe rich results (cook time, rating, calorie count) for any page with valid Recipe structured data — Shopify product pages are eligible. Required: name, image, author, and at least one of recipeIngredient or recipeInstructions. Meal kit product pages with valid Recipe markup can appear in Google's recipe carousel and image pack.

What are the ISO 8601 duration formats for recipe times?

Format: PT(hours)H(minutes)M(seconds)S. Examples: "PT30M" = 30 minutes, "PT1H" = 1 hour, "PT1H30M" = 90 minutes, "PT5M" = 5 minutes. Google's validator will flag plain numbers like "30" — always use the PT prefix format for prepTime, cookTime, and totalTime.