Optimization Guide

Shopify Food & Beverage Nutrition Schema for AI Shopping Agents

AI shopping agents answering "gluten-free protein bars under 200 calories," "nut-free snacks for kids," and "USDA Organic coffee beans" rely entirely on structured nutrition and allergen data — not text descriptions or label images. Shopify has no built-in NutritionInformation output, leaving every food brand's nutrition facts invisible to AI dietary and allergen queries.

TL;DR Add a nutrition property to your Product JSON-LD pointing to a NutritionInformation type with calories, servingSize, and macro fields. Use additionalProperty: containsAllergen for each allergen. Declare dietary certifications via hasCertification or additionalProperty: dietaryRestriction using schema.org RestrictedDiet values. Store all values in a nutrition.* metafield namespace and inject via Liquid with a food-product tag gate.

Why Food Brands Are Invisible to AI Dietary Queries

The food and beverage category is one of the most AI-agent-driven verticals in e-commerce. Users routinely ask AI shopping agents questions that are structurally nutritional: "low-sodium crackers under 140mg per serving," "high-protein vegan snacks with at least 20g protein," "tree nut-free granola bars," "Certified Vegan protein powder." These queries require structured, machine-readable nutritional data — not text descriptions or product imagery.

Shopify's default product JSON-LD outputs only name, description, price, and availability. Nutrition facts — even when displayed beautifully as an FDA-compliant label image or an app-generated HTML table — are completely invisible to AI agent crawlers. The nutrition data exists on the page for humans; it is not in the structured data for machines.

The schema.org NutritionInformation type and the RestrictedDiet enumeration exist precisely to solve this problem. Adding them to your Shopify product JSON-LD lets AI agents accurately filter, rank, and surface your products in response to dietary-intent queries that represent a substantial and fast-growing share of food e-commerce traffic.

Food product query types requiring structured data

Query type Example Required signal AI shopping behavior
Calorie filter "protein bars under 200 calories" nutrition.calories: "190 calories" Filters products where calorie count is below query threshold
Allergen exclusion "nut-free granola bars" containsAllergen: "Tree nuts" absent Excludes products containing the queried allergen from results
Dietary certification "USDA Organic coffee beans" hasCertification: USDA Organic Surfaces products with the specified certification from a recognized issuing body
Macro target "high-protein vegan snacks 20g protein" nutrition.proteinContent: "22 g" + dietaryRestriction: VeganDiet Filters products meeting both protein threshold and dietary restriction
May-contain cross-contact "completely nut-free facility dark chocolate" mayContainAllergen absent for nuts Distinguishes products free from both intentional and cross-contamination allergens

Shopify default vs. nutrition-aware JSON-LD

Shopify default (no nutrition data)
{
  "@type": "Product",
  "name": "Dark Chocolate Protein Bar",
  "description": "20g protein. Gluten free.
    Contains: Milk, Soy.",
  // nutrition in text only
  // allergens in description text
  // invisible to AI dietary filters
}
With NutritionInformation schema
{
  "@type": "Product",
  "nutrition": {
    "@type": "NutritionInformation",
    "calories": "210 calories",
    "servingSize": "1 bar (60g)",
    "proteinContent": "20 g"
  },
  "additionalProperty": [{
    "propertyID": "containsAllergen",
    "value": "Milk"
  }]
}

Food Product JSON-LD Patterns

Minimum viable NutritionInformation

The baseline pattern: add a nutrition property to your Product with a NutritionInformation type. At minimum, include calories and servingSize — these two fields unlock the broadest set of AI dietary queries:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Dark Chocolate Almond Protein Bar",
  "description": "20g protein per bar. Made with real almonds and 72% dark chocolate.",
  "brand": { "@type": "Brand", "name": "NutriCraft" },
  "nutrition": {
    "@type": "NutritionInformation",
    "servingSize": "1 bar (60g)",
    "calories": "210 calories",
    "fatContent": "9 g",
    "saturatedFatContent": "3 g",
    "carbohydrateContent": "18 g",
    "sugarContent": "6 g",
    "fiberContent": "4 g",
    "proteinContent": "20 g",
    "sodiumContent": "180 mg"
  },
  "offers": {
    "@type": "Offer",
    "price": "32.00",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}

Allergen declaration with containsAllergen

Declare each allergen as a separate additionalProperty entry with propertyID: "containsAllergen". Use standard allergen names matching FDA Big-9 and EU Big-14 allergen lists. Add mayContainAllergen as a distinct propertyID for cross-contact risk so AI agents can distinguish between intentional ingredients and manufacturing cross-contamination:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Dark Chocolate Almond Protein Bar",
  "nutrition": {
    "@type": "NutritionInformation",
    "servingSize": "1 bar (60g)",
    "calories": "210 calories",
    "proteinContent": "20 g"
  },
  "additionalProperty": [
    {
      "@type": "PropertyValue",
      "propertyID": "containsAllergen",
      "name": "Contains allergen",
      "value": "Milk"
    },
    {
      "@type": "PropertyValue",
      "propertyID": "containsAllergen",
      "name": "Contains allergen",
      "value": "Tree nuts"
    },
    {
      "@type": "PropertyValue",
      "propertyID": "containsAllergen",
      "name": "Contains allergen",
      "value": "Soy"
    },
    {
      "@type": "PropertyValue",
      "propertyID": "mayContainAllergen",
      "name": "May contain allergen (cross-contact)",
      "value": "Peanuts"
    }
  ]
}

Dietary certifications — Organic, Vegan, Kosher, Non-GMO

Use hasCertification for third-party verified certifications with an issuing body. For self-declared dietary designations (no certifying body), use additionalProperty: dietaryRestriction with schema.org RestrictedDiet enumeration values:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Single-Origin Ethiopian Espresso Beans",
  "hasCertification": [
    {
      "@type": "Certification",
      "name": "USDA Organic",
      "certificationStatus": "https://schema.org/CertificationActive",
      "issuedBy": {
        "@type": "Organization",
        "name": "USDA Agricultural Marketing Service",
        "url": "https://www.ams.usda.gov"
      }
    },
    {
      "@type": "Certification",
      "name": "Fair Trade Certified",
      "certificationStatus": "https://schema.org/CertificationActive",
      "issuedBy": {
        "@type": "Organization",
        "name": "Fair Trade USA",
        "url": "https://www.fairtradecertified.org"
      }
    }
  ],
  "additionalProperty": [
    {
      "@type": "PropertyValue",
      "propertyID": "dietaryRestriction",
      "name": "Dietary restriction",
      "value": "https://schema.org/VeganDiet"
    },
    {
      "@type": "PropertyValue",
      "propertyID": "dietaryRestriction",
      "name": "Dietary restriction",
      "value": "https://schema.org/GlutenFreeDiet"
    }
  ]
}

Full food product pattern — nutrition + allergens + certifications

Production-ready pattern combining all three signal types. This is the complete JSON-LD for a food product surfaceable across calorie, allergen, macro, and certification queries:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Pea Protein Powder — Vanilla Bean",
  "brand": { "@type": "Brand", "name": "PlantForce" },
  "nutrition": {
    "@type": "NutritionInformation",
    "servingSize": "1 scoop (30g)",
    "calories": "120 calories",
    "fatContent": "2 g",
    "saturatedFatContent": "0 g",
    "carbohydrateContent": "3 g",
    "sugarContent": "1 g",
    "fiberContent": "1 g",
    "proteinContent": "25 g",
    "sodiumContent": "340 mg"
  },
  "additionalProperty": [
    {
      "@type": "PropertyValue",
      "propertyID": "dietaryRestriction",
      "value": "https://schema.org/VeganDiet"
    },
    {
      "@type": "PropertyValue",
      "propertyID": "dietaryRestriction",
      "value": "https://schema.org/GlutenFreeDiet"
    }
  ],
  "hasCertification": {
    "@type": "Certification",
    "name": "Certified Vegan",
    "certificationStatus": "https://schema.org/CertificationActive",
    "issuedBy": {
      "@type": "Organization",
      "name": "Vegan Action",
      "url": "https://vegan.org"
    }
  },
  "offers": {
    "@type": "Offer",
    "price": "54.00",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}

Shopify Liquid implementation with metafields

Store nutrition data in a nutrition metafield namespace. Gate on a product tag (food-product) to avoid injecting nutrition schema on non-food products in a mixed catalog:

{% if product.tags contains 'food-product' %}
{% assign n = product.metafields.nutrition %}
{% if n.calories %}

{% endif %}
{% endif %}

Nutrition property reference

schema.org property Value format Example AI query type
calories String: "[N] calories" "210 calories" Calorie filter (under/over N cal)
servingSize String: human-readable "1 bar (60g)" Per-serving normalization
proteinContent String: "[N] g" "20 g" High-protein filter (at least N grams)
carbohydrateContent String: "[N] g" "18 g" Low-carb filter
sodiumContent String: "[N] mg" "180 mg" Low-sodium filter (under N mg)
sugarContent String: "[N] g" "6 g" No-added-sugar / low-sugar filter
fatContent String: "[N] g" "9 g" Low-fat filter
fiberContent String: "[N] g" "4 g" High-fiber filter

Common Mistakes

1. Putting nutrition facts only in the product description or image

An FDA-compliant nutrition label image, a formatted HTML nutrition table, or a description line like "190 calories per serving" — all invisible to AI agent crawlers. Text and images are not machine-readable for structured filtering. AI agents answering "protein bars under 200 calories" read the NutritionInformation.calories property in JSON-LD, not description text. The nutrition panel on your page can remain for human readers; the JSON-LD serves AI agents.

2. Listing allergens only as a sentence in the ingredients text

Writing "Contains: Milk, Soy, Almonds" in product description or ingredients text is not machine-readable for allergen exclusion queries. AI agents filtering "nut-free protein bars" look at the containsAllergen additionalProperty — not description text. Allergen sentence in description plus structured containsAllergen declaration is the correct pattern: keep both for legal compliance and AI readability.

3. Conflating "contains" with "may contain" allergens

Using containsAllergen for both intentional allergen ingredients and cross-contact manufacturing risk overstates the actual allergen content. For users with severe allergies filtering on "completely peanut-free," a product that says containsAllergen: Peanuts but is actually peanut-free with a "may contain" warning will be excluded unnecessarily. Use containsAllergen for intentional ingredients only; use a separate mayContainAllergen additionalProperty for cross-contact risk.

4. Using self-declared organic without a certification entity

Declaring hasCertification: { name: "Organic" } without an issuedBy Organization leaves the certification claim unverifiable. AI agents may discount or ignore uncertified organic claims. For USDA Organic certification, include issuedBy: { name: "USDA Agricultural Marketing Service" } to tie the claim to a recognized authority. For uncertified products made with organic ingredients, use additionalProperty: organicIngredients rather than a certification claim.

5. Injecting nutrition schema on non-food products in a mixed catalog

Shopify stores selling both food and non-food products (e.g., a wellness brand selling supplements, yoga mats, and apparel together) must gate nutrition JSON-LD on a tag. Injecting NutritionInformation on a yoga mat or water bottle creates invalid structured data and can cause schema validation errors that degrade all structured data on that page. Use a product tag like food-product or edible to restrict injection.

Implementation Checklist

Frequently Asked Questions

How do I add calorie and nutrition facts to a Shopify food product in JSON-LD?

Add a nutrition property to your Product JSON-LD pointing to a NutritionInformation type. Include calories (string: "210 calories"), servingSize ("1 bar (60g)"), and macros (proteinContent, carbohydrateContent, fatContent, sugarContent, sodiumContent) as "[N] g" or "[N] mg" strings. Store values in nutrition.* metafields and inject via Liquid.

How do I mark allergens in Shopify product structured data?

Use additionalProperty with propertyID: "containsAllergen" for each intentional allergen — one PropertyValue per allergen. For cross-contact manufacturing risk, use a separate propertyID: "mayContainAllergen" entry. Common values: Milk, Eggs, Fish, Shellfish, Peanuts, Tree nuts, Wheat, Soy, Sesame. AI agents use these to filter allergen-safe products for users with dietary restrictions.

What schema.org type represents food dietary certifications like Organic, Kosher, Vegan?

Use hasCertification with a Certification type for third-party verified certifications. Include name, certificationStatus: "https://schema.org/CertificationActive", and issuedBy Organization with the certifying body. For self-declared dietary designations without an issuing body, use additionalProperty: dietaryRestriction with schema.org RestrictedDiet values (VeganDiet, GlutenFreeDiet, KosherDiet, HalalDiet, etc.).

Does Shopify output NutritionInformation in its default product JSON-LD?

No. Shopify's default JSON-LD outputs name, description, price, and availability only. Nutrition facts displayed as images, HTML tables, or description text are invisible to AI agent crawlers. Food and beverage brands must manually add NutritionInformation, containsAllergen, and hasCertification in product.liquid to be surfaced in dietary and allergen queries.

How do I handle nutrition data for products with multiple flavors or variants in Shopify?

If nutritional values differ across variants (chocolate vs. vanilla have different calorie counts), use ProductGroup with hasVariant — each variant is a separate Product with its own nutrition block. If all variants share the same nutritional profile, declare nutrition on the parent Product only. Store variant nutrition in per-variant metafields and inject conditionally.

Related Resources