Subscription Commerce
Shopify subscription box
structured data and schema markup
How to implement schema.org Product markup for Shopify subscription boxes — recurring price signaling, contents description, cancellation policy, and AI shopping agent visibility for box subscription products.
UnitPriceSpecification (billing period + amount), a description covering box contents and retail value, and AggregateRating from subscriber reviews. Make the subscription price visible in plain text on the page — AI agents cross-check JSON-LD against page copy and suppress products where they disagree.
The structured data challenge unique to subscription boxes
Subscription boxes present three structured data challenges that standard Shopify product pages don't have:
- Recurring price vs. one-time price — The "price" shown ($39/month, $129/quarter) is fundamentally different from a product price. Schema.org's standard Offer.price is designed for one-time purchases. Subscription pricing requires UnitPriceSpecification with billing period context.
- Variable contents — A mystery box that ships different items each month can't have a stable product description. AI agents may classify the product inconsistently across months if description changes aren't managed carefully.
- Subscription apps own the checkout — Recharge, Bold Subscriptions, and Skio handle billing logic but leave structured data entirely to the store theme. The result: most subscription box Shopify stores have either no Product JSON-LD or standard one-time-purchase markup that misrepresents the actual pricing model.
Implementing subscription pricing in schema.org
Schema.org's UnitPriceSpecification is the correct type for recurring prices. It supports billing period, billing increment, and price per unit:
Monthly subscription box markup
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Monthly Artisan Snack Box",
"description": "Monthly curated box of 5–7 artisan snacks from small-batch US producers. Retail value $60+. Allergen info included. Cancel anytime.",
"image": "https://yourstore.com/products/snack-box.jpg",
"brand": { "@type": "Brand", "name": "Snack Collective" },
"offers": {
"@type": "Offer",
"url": "https://yourstore.com/products/monthly-snack-box",
"availability": "https://schema.org/InStock",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": "39.00",
"priceCurrency": "USD",
"referenceQuantity": {
"@type": "QuantitativeValue",
"value": "1",
"unitCode": "MON"
},
"billingIncrement": 1
}
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "312",
"bestRating": "5",
"worstRating": "1"
}
}
The unitCode: "MON" signals a monthly billing period. Use "ANN" for annual subscriptions. billingIncrement: 1 means one billing period per cycle — use 3 for quarterly (every 3 months).
Multi-tier subscription box markup (monthly / quarterly / annual)
If you offer multiple subscription tiers, use AggregateOffer to expose the price range, and list individual offers for each tier:
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Artisan Snack Box",
"description": "Curated artisan snack subscription. Choose monthly, quarterly, or annual. 5–7 items per box, retail value $60+.",
"offers": {
"@type": "AggregateOffer",
"lowPrice": "34.00",
"highPrice": "39.00",
"priceCurrency": "USD",
"offerCount": "3",
"offers": [
{
"@type": "Offer",
"name": "Monthly",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": "39.00",
"priceCurrency": "USD",
"referenceQuantity": { "@type": "QuantitativeValue", "value": "1", "unitCode": "MON" },
"billingIncrement": 1
},
"availability": "https://schema.org/InStock"
},
{
"@type": "Offer",
"name": "Quarterly (save 10%)",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": "105.00",
"priceCurrency": "USD",
"referenceQuantity": { "@type": "QuantitativeValue", "value": "3", "unitCode": "MON" },
"billingIncrement": 3
},
"availability": "https://schema.org/InStock"
},
{
"@type": "Offer",
"name": "Annual (save 13%)",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": "408.00",
"priceCurrency": "USD",
"referenceQuantity": { "@type": "QuantitativeValue", "value": "1", "unitCode": "ANN" },
"billingIncrement": 1
},
"availability": "https://schema.org/InStock"
}
]
}
}
Implementing in Shopify Liquid with subscription app metafields
Since subscription apps manage pricing logic separately from Shopify's native product price, the cleanest approach is to store subscription pricing data in metafields and output it in Liquid:
{% comment %}
Requires metafields:
- subscription.monthly_price (number)
- subscription.quarterly_price (number)
- subscription.annual_price (number)
- subscription.billing_currency (single_line_text, default: store currency)
Set these in Shopify admin → Products → Metafields
{% endcomment %}
{% if product.metafields.subscription.monthly_price %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "{{ product.title | escape }}",
"description": "{{ product.description | strip_html | truncate: 500 | escape }}",
"image": "{{ product.featured_image | img_url: 'master' | prepend: 'https:' }}",
"brand": { "@type": "Brand", "name": "{{ product.vendor | escape }}" },
"offers": {
"@type": "Offer",
"availability": "https://schema.org/InStock",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": "{{ product.metafields.subscription.monthly_price }}",
"priceCurrency": "{{ cart.currency.iso_code }}",
"referenceQuantity": {
"@type": "QuantitativeValue",
"value": "1",
"unitCode": "MON"
},
"billingIncrement": 1
}
}
{% if product.metafields.reviews.rating_count > 0 %}
,"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{{ product.metafields.reviews.rating | round: 1 }}",
"reviewCount": "{{ product.metafields.reviews.rating_count }}"
}
{% endif %}
}
</script>
{% endif %}
What to put in subscription box descriptions for AI agents
AI shopping agents match subscription boxes to queries like "best snack subscription box", "coffee subscription gift", "monthly book box under $30". Your Product.description is the primary relevance signal. Include all of these elements:
| Description element | Why it matters for AI agents | Example |
|---|---|---|
| Contents category | Matches category-intent queries | "artisan snacks", "specialty coffee", "beauty samples" |
| Item count per box | Answers "how many items" queries; differentiates from competitors | "5–7 full-size items" |
| Retail value of contents | AI agents use value vs. price differential to rank value | "retail value $60+" |
| Curation method | Quality signal for premium queries | "curated by certified sommeliers", "selected by our editorial team" |
| Audience / occasion fit | Gift query matching ("subscription box for coffee lover") | "perfect gift for coffee enthusiasts", "ideal for home bakers" |
| Cancellation policy | Trust signal; appears in "no commitment" queries | "cancel anytime, no commitment" |
| Shipping frequency + timing | Matches "monthly delivery" queries | "ships on the 15th of each month" |
Google Merchant Center for subscription boxes
Google AI Mode reads from GMC for product surfacing. Subscription boxes in GMC require specific handling:
- Use subscription_cost attribute — Google supports a
subscription_costattribute in GMC feeds for products with recurring charges. It requires amount, period (month/year), and period_length. - Set product_type to subscription category — Map your subscription box to an appropriate Google taxonomy:
Home & Garden > Food, Beverages & Tobacco > Food Itemsfor food boxes, or use Gift & Collectibles taxonomy for general boxes. - Price field in GMC — Use the subscription monthly price as the price attribute. Google displays it as the "starting from" or monthly price in shopping results.
Subscription box structured data checklist
| Check | Priority |
|---|---|
| Product JSON-LD present on subscription product page (server-rendered) | Critical |
| UnitPriceSpecification with unitCode MON or ANN instead of bare Offer.price | Critical |
| Monthly/recurring price matches visible page price (no discrepancy) | Critical |
| Description covers contents, item count, retail value, curation method | High |
| AggregateRating present if subscriber reviews collected | High |
| Cancellation policy visible in page text | High |
| GMC feed includes subscription_cost attribute | Medium |
| Gift-giving keywords in description for holiday query coverage | Medium |
Run a CatalogScan check on your subscription product pages to see exactly which structured data signals are present and how your store compares to the 100-store benchmark. Subscription boxes are an underserved category for AI agent optimization — the bar is low and the upside is real.
Related: Shopify subscription products and AI agents · Product bundles structured data · AI shopping agent ranking factors
Frequently asked questions
Does schema.org support recurring billing markup?
Not natively, but you can express recurring pricing with UnitPriceSpecification and referenceQuantity.unitCode: "MON" for monthly billing. Google's documentation recommends this pattern for subscription products. No Shopify subscription app generates this automatically — manual theme implementation is required.
How should I describe a mystery box with variable monthly contents?
Describe the value proposition, not the specific items: category of contents, item count range, retail value vs. subscription price, curation method, and audience fit. AI agents use this to match "subscription box for [category]" queries. Don't list specific monthly items in JSON-LD since they change — add a "past boxes" page for content depth instead.
Will subscription boxes appear in AI shopping agent results?
Yes, with proper setup. Requirements: accessible product page (no login required to view), complete Product JSON-LD with recurring price, description covering box contents and value, and AggregateRating. Boxes with external editorial reviews (Wirecutter, gift guides) rank significantly higher in Perplexity recommendations.
What Shopify apps handle subscription box structured data?
No major subscription app (Recharge, Bold, Skio, Stay AI, Loop) automatically generates complete structured data as of 2026. They handle billing mechanics but leave JSON-LD to your theme. Use metafields to store subscription pricing data and output it in your product template's JSON-LD block.