Optimization Guide
Shopify Print-on-Demand Schema — MadeToOrder Availability, POD Product Markup & Fulfillment Signals
Print-on-demand stores on Shopify (powered by Printful, Printify, Gelato, or SPOD) have a fundamental schema problem: the products don't exist as physical inventory until an order is placed. Using InStock availability is technically false. Leaving out lead times leaves AI agents unable to answer "custom hoodie delivered by Friday." The base material, fabric weight, and print method stay invisible in Shopify's default JSON-LD. This guide fixes all three gaps with POD-specific structured data patterns.
BackOrder availability (not InStock) for POD products since items are manufactured after order. Add deliveryLeadTime as a min/max QuantitativeValue range covering production + shipping. Use additionalProperty for print method, fabric weight (GSM), fabric composition, and base product brand (Bella+Canvas, Gildan). Set itemCondition: NewCondition explicitly. For personalized/custom POD, add additionalType with a custom order note and potentialAction OrderAction.
Why POD Products Need Custom Schema Treatment
Print-on-demand products have characteristics that break the assumptions built into Shopify's default JSON-LD generator. Understanding these breaks is the prerequisite for fixing them:
| Default Shopify behavior | POD reality | Schema fix |
|---|---|---|
Outputs InStock when any variant is purchasable |
POD items have no physical stock — they're manufactured on demand | BackOrder availability + deliveryLeadTime |
| No shipping/fulfillment time in JSON-LD | POD has 2–5 day production lead time before shipping | deliveryLeadTime QuantitativeValue on Offer |
| Material field empty or just product title words | POD base product has specific fabric: 180 GSM ring-spun cotton | material + additionalProperty Fabric Weight + Composition |
| No print process information | DTG vs sublimation vs embroidery determines durability and care | additionalProperty Print Method |
| Brand = store name | Base product brand (Bella+Canvas, Gildan, etc.) matters to buyers | additionalProperty Base Product Brand + Base Product SKU |
| No customization information | POD product is personalized to buyer's design/text | additionalProperty Customization Type + potentialAction |
Full POD Product Schema — Custom T-Shirt Example
The following example covers the highest-value structured data additions for a DTG-printed t-shirt on Bella+Canvas 3001 base product, sold as a POD item through Printful.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Mountain Sunrise Custom Graphic Tee — Unisex, 100% Cotton, DTG Printed",
"description": "Custom graphic t-shirt featuring the Mountain Sunrise original design. Printed using direct-to-garment (DTG) technology on a Bella+Canvas 3001 unisex jersey t-shirt. 100% Airlume combed and ring-spun cotton, 145 GSM. Available in sizes XS–3XL. Printed and shipped within 3–5 business days.",
"sku": "MTN-SUNRISE-BC3001",
"brand": { "@type": "Brand", "name": "Summit Prints Co." },
"material": "100% Airlume combed and ring-spun cotton, 145 GSM",
"itemCondition": "https://schema.org/NewCondition",
"additionalProperty": [
{ "@type": "PropertyValue", "name": "Print Method", "value": "Direct-to-Garment (DTG)" },
{ "@type": "PropertyValue", "name": "Fabric Composition", "value": "100% Airlume combed and ring-spun cotton" },
{ "@type": "PropertyValue", "name": "Fabric Weight", "value": "145", "unitCode": "GM2", "description": "145 g/m² (GSM)" },
{ "@type": "PropertyValue", "name": "Base Product Brand", "value": "Bella+Canvas" },
{ "@type": "PropertyValue", "name": "Base Product Style", "value": "3001 Unisex Jersey Short Sleeve Tee" },
{ "@type": "PropertyValue", "name": "Fit Type", "value": "Unisex Regular Fit" },
{ "@type": "PropertyValue", "name": "Neck Style", "value": "Crew Neck" },
{ "@type": "PropertyValue", "name": "Sleeve Type", "value": "Short Sleeve" },
{ "@type": "PropertyValue", "name": "Customization Type", "value": "Fixed Design — Pre-designed graphic, not buyer-personalized" },
{ "@type": "PropertyValue", "name": "Fulfillment Method", "value": "Print-on-Demand via Printful" },
{ "@type": "PropertyValue", "name": "Care Instructions", "value": "Machine wash cold, inside out. Tumble dry low. Do not iron directly on print." }
],
"offers": {
"@type": "Offer",
"price": "29.99",
"priceCurrency": "USD",
"availability": "https://schema.org/BackOrder",
"itemCondition": "https://schema.org/NewCondition",
"deliveryLeadTime": {
"@type": "QuantitativeValue",
"minValue": 3,
"maxValue": 7,
"unitCode": "DAY",
"description": "3–5 business days production + 2–3 days standard US shipping"
},
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": { "@type": "MonetaryAmount", "value": "4.99", "currency": "USD" },
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"businessDays": {
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["https://schema.org/Monday","https://schema.org/Tuesday","https://schema.org/Wednesday","https://schema.org/Thursday","https://schema.org/Friday"]
},
"handlingTime": { "@type": "QuantitativeValue", "minValue": 3, "maxValue": 5, "unitCode": "DAY" },
"transitTime": { "@type": "QuantitativeValue", "minValue": 2, "maxValue": 5, "unitCode": "DAY" }
}
}
}
}
</script>
The separation between handlingTime (production) and transitTime (shipping) inside ShippingDeliveryTime is the most granular way to communicate POD fulfillment windows. AI agents answering "how soon can I get this custom t-shirt?" use the handlingTime + transitTime sum to calculate the earliest delivery date.
Availability Values for POD: BackOrder vs PreOrder vs MadeToOrder
Schema.org's availability vocabulary has three values relevant to print-on-demand, and the distinction matters for AI query matching:
| Value | Schema.org URL | When to use for POD | AI query match |
|---|---|---|---|
| BackOrder | https://schema.org/BackOrder |
Standard POD product — always available to order, always manufactured post-order. Best default for Printful/Printify products. | "custom t-shirt," "order now for delivery in X days" |
| PreOrder | https://schema.org/PreOrder |
POD product launching on a specific date — e.g., "new design drops May 15, orders before then ship day-of-launch." Use availabilityStarts with the launch date. |
"pre-order custom hoodie," "reserve before launch" |
| InStock | https://schema.org/InStock |
Do NOT use for pure POD products — only if you maintain a physical pre-printed inventory buffer. Using InStock for POD creates false delivery expectations and may generate AI agent misinformation about same-day dispatch. | Immediate fulfillment queries — wrong for POD |
If your store uses a hybrid model — some designs pre-printed in bulk (true stock) and others POD — use different availability values per Offer based on a product.metafields.pod.fulfillment_type metafield flag.
Print Method Reference for additionalProperty
Print method determines washability, color vibrancy, print placement, and care instructions — all signals that AI shopping agents use when answering product-quality queries. Use the full descriptive name as the property value.
| Print method | Use as value | Best for | Durability |
|---|---|---|---|
| Direct-to-Garment | "Direct-to-Garment (DTG)" |
Cotton t-shirts, complex photo designs | Moderate — fades gradually with washing |
| Dye Sublimation | "Dye Sublimation" |
All-over-print polyester apparel, mugs, phone cases | Excellent — dye infused into substrate |
| Screen Printing | "Screen Printing" |
Spot-color designs, bulk runs, apparel | Excellent — thick ink layer, long-lasting |
| Embroidery | "Embroidery" |
Hats, structured garments, patches | Excellent — stitched, not printed |
| UV Direct Print | "UV Direct Print" |
Hard goods: phone cases, mugs, signs, wood panels | Very good — UV-cured ink, scratch-resistant |
| Laser Engraving | "Laser Engraving" |
Wood, metal, acrylic, leather | Permanent — material is etched, not coated |
| Puff Print | "Puff Print (3D)" |
Apparel with raised texture effect | Good — raised ink, moderate durability |
| Giclee Print | "Giclee Fine Art Print" |
Art prints, posters, canvas | Very good — archival inks on acid-free paper/canvas |
Buyer-Personalized POD: Custom Text and Design Uploads
Some POD stores allow buyers to personalize products with their own text, monograms, or uploaded photos. This is distinct from a fixed-design POD product. For personalized POD, add customization signals that help AI agents answer "custom name necklace," "personalized photo mug," or "monogrammed hoodie" queries.
{
"@type": "Product",
"name": "Custom Name Embroidery Beanie — Personalized Hat, Your Text",
"description": "Beanie with custom embroidered name or text. Enter your name or message (up to 12 characters) at checkout. Embroidered in your choice of 8 thread colors. 100% acrylic, one-size-fits-most. Fulfilled in 4–6 business days.",
"additionalProperty": [
{ "@type": "PropertyValue", "name": "Customization Type", "value": "Buyer-Personalized — Custom text input at checkout" },
{ "@type": "PropertyValue", "name": "Personalization Field", "value": "Name or text (up to 12 characters)" },
{ "@type": "PropertyValue", "name": "Available Colors", "value": "8 thread colors: Red, Navy, Black, White, Pink, Gold, Forest Green, Royal Blue" },
{ "@type": "PropertyValue", "name": "Print Method", "value": "Embroidery" },
{ "@type": "PropertyValue", "name": "Base Product Brand", "value": "Richardson" },
{ "@type": "PropertyValue", "name": "Base Product Style", "value": "115 Low Profile Structured Snapback" },
{ "@type": "PropertyValue", "name": "Fabric Composition", "value": "100% cationic polyester" }
],
"potentialAction": {
"@type": "OrderAction",
"target": {
"@type": "EntryPoint",
"urlTemplate": "https://example.myshopify.com/cart/add?id={variant_id}",
"actionPlatform": ["https://schema.org/DesktopWebPlatform", "https://schema.org/MobileWebPlatform"]
},
"actionStatus": "https://schema.org/PotentialActionStatus"
},
"offers": {
"@type": "Offer",
"availability": "https://schema.org/BackOrder",
"deliveryLeadTime": {
"@type": "QuantitativeValue",
"minValue": 4,
"maxValue": 8,
"unitCode": "DAY",
"description": "4–6 business days production for personalized embroidery + 2–3 days shipping"
}
}
}
For buyer-personalized POD, set a longer deliveryLeadTime than standard POD — personalization review adds time. If your POD provider allows rush processing for personalized items, add a second Offer with a higher price and shorter lead time alongside the standard offer.
Dawn Liquid Snippet: POD Product JSON-LD from Metafields
Save as snippets/pod-product-schema.liquid. Activates for products tagged print-on-demand or in the pod-products collection. Uses a pod.* metafield namespace.
{% comment %} pod-product-schema.liquid — print-on-demand product schema {% endcomment %}
{% assign is_pod = false %}
{% if product.tags contains 'print-on-demand' or product.tags contains 'pod' or product.tags contains 'custom-print' %}
{% assign is_pod = true %}
{% endif %}
{% for collection in product.collections %}
{% if collection.handle == 'pod-products' or collection.handle == 'custom-apparel' or collection.handle == 'print-on-demand' %}
{% assign is_pod = true %}
{% endif %}
{% endfor %}
{% if is_pod %}
{% assign print_method = product.metafields.pod.print_method %}
{% assign fabric_gsm = product.metafields.pod.fabric_weight_gsm %}
{% assign fabric_comp = product.metafields.pod.fabric_composition %}
{% assign base_brand = product.metafields.pod.base_product_brand %}
{% assign base_style = product.metafields.pod.base_product_style %}
{% assign lead_min = product.metafields.pod.lead_time_min_days | default: '3' %}
{% assign lead_max = product.metafields.pod.lead_time_max_days | default: '7' %}
{% assign customization = product.metafields.pod.customization_type %}
{% assign care_instructions = product.metafields.pod.care_instructions %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": {{ product.title | json }},
"description": {{ product.description | strip_html | truncatewords: 80 | json }},
"url": "{{ shop.url }}{{ product.url }}",
"sku": {{ product.selected_or_first_available_variant.sku | json }},
"itemCondition": "https://schema.org/NewCondition"
{% if product.vendor != blank %}
,"brand": { "@type": "Brand", "name": {{ product.vendor | json }} }
{% endif %}
{% if fabric_comp != blank %}
,"material": {% if fabric_gsm != blank %}{{ fabric_comp | append: ', ' | append: fabric_gsm | append: ' GSM' | json }}{% else %}{{ fabric_comp | json }}{% endif %}
{% endif %}
,"additionalProperty": [
{% assign ap_started = false %}
{% if print_method != blank %}
{ "@type": "PropertyValue", "name": "Print Method", "value": {{ print_method | json }} }
{% assign ap_started = true %}
{% endif %}
{% if fabric_comp != blank %}
{% if ap_started %},{% endif %}{ "@type": "PropertyValue", "name": "Fabric Composition", "value": {{ fabric_comp | json }} }
{% assign ap_started = true %}
{% endif %}
{% if fabric_gsm != blank %}
,{ "@type": "PropertyValue", "name": "Fabric Weight", "value": {{ fabric_gsm | json }}, "unitCode": "GM2", "description": {{ fabric_gsm | append: ' g/m² (GSM)' | json }} }
{% endif %}
{% if base_brand != blank %}
,{ "@type": "PropertyValue", "name": "Base Product Brand", "value": {{ base_brand | json }} }
{% endif %}
{% if base_style != blank %}
,{ "@type": "PropertyValue", "name": "Base Product Style", "value": {{ base_style | json }} }
{% endif %}
{% if customization != blank %}
,{ "@type": "PropertyValue", "name": "Customization Type", "value": {{ customization | json }} }
{% endif %}
,{ "@type": "PropertyValue", "name": "Fulfillment Method", "value": "Print-on-Demand" }
{% if care_instructions != blank %}
,{ "@type": "PropertyValue", "name": "Care Instructions", "value": {{ care_instructions | json }} }
{% endif %}
]
,"offers": {
"@type": "Offer",
"price": {{ product.selected_or_first_available_variant.price | money_without_currency | json }},
"priceCurrency": {{ cart.currency.iso_code | json }},
"availability": "https://schema.org/BackOrder",
"itemCondition": "https://schema.org/NewCondition",
"url": "{{ shop.url }}{{ product.url }}",
"deliveryLeadTime": {
"@type": "QuantitativeValue",
"minValue": {{ lead_min }},
"maxValue": {{ lead_max }},
"unitCode": "DAY"
}
}
}
</script>
{% endif %}
pod.* metafield namespace
| Metafield | Type | Example value |
|---|---|---|
pod.print_method | Single line text | Direct-to-Garment (DTG), Dye Sublimation, Embroidery |
pod.fabric_weight_gsm | Single line text | 145, 180, 220 |
pod.fabric_composition | Single line text | 100% ring-spun cotton, 65% polyester 35% cotton |
pod.base_product_brand | Single line text | Bella+Canvas, Gildan, Next Level, AS Colour |
pod.base_product_style | Single line text | 3001 Unisex Jersey Short Sleeve Tee |
pod.lead_time_min_days | Integer | 3 |
pod.lead_time_max_days | Integer | 7 |
pod.customization_type | Single line text | Fixed Design, Buyer-Personalized — Custom text at checkout |
pod.care_instructions | Single line text | Machine wash cold, tumble dry low, do not iron on print |
5 Common Print-on-Demand Schema Mistakes
| # | Mistake | Impact | Fix |
|---|---|---|---|
| 1 | Using InStock availability for POD products |
AI shopping agents answering "in-stock custom hoodies" exclude POD products (correctly — they're not in stock), but worse, agents answering "fast delivery" queries may return your POD product expecting same-day dispatch and then generate incorrect delivery estimates | Use BackOrder for all standard POD products. Combine with deliveryLeadTime so AI agents can calculate realistic delivery windows instead of treating it as indefinitely unavailable |
| 2 | No deliveryLeadTime on POD product Offers | Without a lead time, AI agents cannot answer "can I get a custom t-shirt by [date]?" — they'll either skip the product or give an incorrect estimate based on generic shipping data. POD's 3–7 day production window is the most commercially important signal to communicate | Add deliveryLeadTime as a QuantitativeValue with minValue, maxValue, and unitCode: "DAY" representing total production + standard shipping time |
| 3 | Base product brand and style absent from structured data | Shoppers researching "Bella+Canvas 3001 custom tee" or "Gildan 18500 hoodie custom" use the base product model number as a quality/fit proxy — it's the same blank worn by professional merchandise brands. Without the base product brand in structured data, this research query can't match your POD listing | Add additionalProperty: { 'name': 'Base Product Brand', 'value': 'Bella+Canvas' } and { 'name': 'Base Product Style', 'value': '3001' } |
| 4 | Print method absent — all POD products appear identical in AI structured data | DTG and sublimation produce fundamentally different products — DTG is suitable for 100% cotton in spot colors; sublimation covers the entire garment and requires 100% polyester. Without print method in structured data, AI agents conflate the two types and cannot answer "all-over-print hoodie sublimation" queries | Add additionalProperty for "Print Method" using the full descriptive name (not abbreviations) so AI agents can filter by print technology |
| 5 | Fabric weight (GSM) missing — only fabric type in description text | GSM is the primary quality signal for apparel shoppers — "heavyweight cotton tee" vs "lightweight" maps directly to GSM ranges. Without structured GSM data, AI agents cannot answer "thick cotton t-shirt" vs "thin summer tee" queries against your catalog | Add additionalProperty: { 'name': 'Fabric Weight', 'value': '180', 'unitCode': 'GM2', 'description': '180 g/m² (GSM)' } for every POD apparel product |
Frequently Asked Questions
What availability value should I use for POD products?
Use BackOrder (https://schema.org/BackOrder) as the default for all standard POD products. Never use InStock for pure POD — it implies physical inventory ready to ship. For POD designs that haven't launched yet, use PreOrder with availabilityStarts. The BackOrder value, combined with deliveryLeadTime, gives AI agents the information they need to answer delivery timeline queries accurately. See also Shopify Made-to-Order Product Schema for the broader made-to-order availability pattern.
How do I express print method in schema.org?
Use additionalProperty with name: "Print Method" and the full descriptive value: "Direct-to-Garment (DTG)", "Dye Sublimation", "Embroidery", etc. Avoid abbreviations — DTG, Sub, and Emb are not AI-agent-friendly. The print method signals durability and care requirements to AI agents handling "wash-safe print" or "permanent custom embroidery" queries. For products using multiple print methods (e.g., DTG on body + embroidery on chest pocket), list both as separate additionalProperty entries.
How do I add base product material (fabric weight, composition)?
Set material to the full human-readable description: "100% Airlume combed ring-spun cotton, 145 GSM". Add additionalProperty for machine-readable breakdowns: { 'name': 'Fabric Weight', 'value': '145', 'unitCode': 'GM2' } and { 'name': 'Fabric Composition', 'value': '100% Airlume combed ring-spun cotton' }. The unitCode GM2 is grams per square metre (g/m² = GSM). AI agents use this for fabric-weight filtering ("heavyweight cotton," "lightweight summer tee").
Should POD products have a SKU?
Yes — always include a SKU, even for POD products without physical stock. Use your Shopify variant SKU (which may be the Printful/Printify base product code with color and size, e.g., AA-8000-BLK-S). The SKU appears in the sku field of the Product or the variant's sku in the Offer. It serves as the fulfillment routing identifier and enables catalog matching for AI procurement agents. See Shopify Product Variant SEO for variant-level SKU implementation.
How do I handle deliveryLeadTime for variable POD fulfillment?
Use a min/max range: { '@type': 'QuantitativeValue', 'minValue': 3, 'maxValue': 7, 'unitCode': 'DAY' } for standard POD. The range should cover total customer-visible time (production + standard shipping). For rush fulfillment, add a second Offer with a higher price, shorter lead time, and express shipping rate. For the most granular delivery data, use ShippingDeliveryTime inside shippingDetails to separately express handlingTime (production) and transitTime (shipping). See Ecommerce Shipping Time Structured Data for the full ShippingDeliveryTime pattern.
Are your POD products showing InStock when they're made to order?
CatalogScan audits your Shopify store's structured data and identifies incorrect availability values, missing lead times, absent print method and fabric specs, and base product data gaps — ensuring your print-on-demand listings are accurate and discoverable in AI custom product queries.
Run Free Scan