Optimization Guide
Shopify Member-Only and Exclusive Product Schema for AI Shopping Agents
AI shopping agents answering "loyalty member exclusive products," "VIP early access drops," and "Gold tier member discount pricing" need structured membership and eligibility signals — not JavaScript loyalty widgets. Shopify's default JSON-LD has no concept of member pricing, tier gating, or exclusive access, making every loyalty program benefit invisible to AI shopping indexes.
Offer blocks: a public Offer at standard price and a member Offer with eligibleCustomerType or additionalProperty: requiredMembershipTier. For member-only products, add additionalProperty: memberOnlyProduct: true. For early access, combine availabilityStarts with the membership tier requirement on the member Offer. Drive from product tags or metafields with a null-guard.
The Loyalty Program Visibility Gap
Loyalty and membership programs are among the most powerful retention and conversion tools in DTC e-commerce. Exclusive products, early access windows, tiered pricing, and members-only drops create the urgency and reward signals that drive program enrollment and retention. Virtually every major DTC brand operating above $1M ARR has some form of loyalty program — LoyaltyLion, Smile.io, Yotpo Loyalty, Okendo Loyalty, or a custom implementation on Shopify.
All of these programs share a critical structural problem: their benefits are rendered in JavaScript. Tier-unlock messaging, member pricing overlays, early access countdowns — every element that communicates membership value is dynamic JavaScript injected after page load. AI agent crawlers (GPTBot, PerplexityBot, ClaudeBot) do not execute JavaScript. When these crawlers read your product pages, they see only the base Shopify product JSON-LD with no evidence that member pricing or exclusive access exists.
The result: when a user asks ChatGPT Shopping "which brands have loyalty programs with exclusive products," or "what are the best member-only deals right now," stores with sophisticated loyalty programs are not surfaced — because the membership signals are not in structured data.
Member-only query types requiring structured data
| Query type | Example | Required signal | AI shopping behavior |
|---|---|---|---|
| Exclusive member products | "loyalty member exclusive products from outdoor brands" | additionalProperty: memberOnlyProduct: true |
Surfaces products declared as member-only access |
| Tier-locked pricing | "Gold member pricing on sneakers" | additionalProperty: requiredMembershipTier: Gold |
Returns products with tier-specific offers matching the queried tier |
| VIP early access | "VIP member early access drops this week" | availabilityStarts on member Offer + requiredMembershipTier: VIP |
Surfaces upcoming early access windows for specific member tiers |
| Member discount rate | "brands that give 20% off for members" | additionalProperty: memberDiscount: 20 (% value) |
Filters stores by member discount percentage across their catalog |
| Subscriber-exclusive deals | "subscriber-only deals from clean beauty brands" | eligibleCustomerType on Offer + member Offer price |
Identifies subscriber-only or subscription-holder pricing |
Shopify default vs. member-aware JSON-LD
{
"@type": "Offer",
"price": "120.00",
"availability": "InStock"
// member price: $96 (20% off)
// invisible to AI agents
// injected by LoyaltyLion JS
}
"offers": [
{
"@type": "Offer",
"price": "120.00",
"availability": "InStock"
},
{
"@type": "Offer",
"price": "96.00",
"additionalProperty": [{
"propertyID":
"requiredMembershipTier",
"value": "Member"
}]
}
]
Member Pricing and Exclusive Access JSON-LD Patterns
Dual-Offer member pricing — public + member price
The most important pattern: declare both a public price Offer and a member price Offer in a offers array. AI agents that handle multi-offer products will correctly surface the member pricing to users who qualify:
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Performance Running Jacket — Windblock",
"offers": [
{
"@type": "Offer",
"name": "Standard price",
"price": "148.00",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
},
{
"@type": "Offer",
"name": "Member price",
"price": "118.40",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"additionalProperty": [
{
"@type": "PropertyValue",
"propertyID": "requiredMembershipTier",
"name": "Required membership tier",
"value": "Member"
},
{
"@type": "PropertyValue",
"propertyID": "memberDiscount",
"name": "Member discount",
"value": "20"
}
]
}
]
}
Tiered member pricing — multiple loyalty tiers
For stores with multiple loyalty tiers (Silver, Gold, Platinum), declare one Offer per tier alongside the public price. Include the memberDiscount additionalProperty for each tier to enable discount-comparison queries:
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Cashmere V-Neck Sweater",
"offers": [
{
"@type": "Offer",
"name": "Public price",
"price": "185.00",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
},
{
"@type": "Offer",
"name": "Silver member price",
"price": "166.50",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"additionalProperty": {
"@type": "PropertyValue",
"propertyID": "requiredMembershipTier",
"value": "Silver"
}
},
{
"@type": "Offer",
"name": "Gold member price",
"price": "148.00",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"additionalProperty": {
"@type": "PropertyValue",
"propertyID": "requiredMembershipTier",
"value": "Gold"
}
},
{
"@type": "Offer",
"name": "Platinum member price",
"price": "129.50",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"additionalProperty": {
"@type": "PropertyValue",
"propertyID": "requiredMembershipTier",
"value": "Platinum"
}
}
]
}
Member-only exclusive product (not publicly purchasable)
For products that are exclusively accessible to members — not available to non-members at any price — declare a single Offer with a memberOnlyProduct signal and set the public availability context clearly:
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Founder Series Limited Hoodie — Members Only",
"description": "Exclusive to all-time members of our loyalty program. Not available for public purchase. Each hoodie has a unique member number embroidered inside.",
"offers": {
"@type": "Offer",
"price": "95.00",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"additionalProperty": [
{
"@type": "PropertyValue",
"propertyID": "memberOnlyProduct",
"name": "Member-only product",
"value": "true"
},
{
"@type": "PropertyValue",
"propertyID": "requiredMembershipTier",
"name": "Required membership tier",
"value": "All-Time Member"
},
{
"@type": "PropertyValue",
"propertyID": "membershipProgramName",
"name": "Program name",
"value": "Founders Circle"
}
]
}
}
VIP early access with availabilityStarts
For products launching publicly in the future but available early to VIP members, create two Offers: an early access Offer for members with availabilityStarts set to the early access date, and a public Offer with availabilityStarts set to the public launch date:
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Summer Collection Linen Blazer",
"offers": [
{
"@type": "Offer",
"name": "VIP member early access",
"price": "220.00",
"priceCurrency": "USD",
"availability": "https://schema.org/PreOrder",
"availabilityStarts": "2026-06-10T09:00:00-07:00",
"availabilityEnds": "2026-06-13T08:59:59-07:00",
"additionalProperty": [
{
"@type": "PropertyValue",
"propertyID": "requiredMembershipTier",
"value": "VIP"
},
{
"@type": "PropertyValue",
"propertyID": "earlyAccessWindowHours",
"value": "72"
}
]
},
{
"@type": "Offer",
"name": "Public sale",
"price": "220.00",
"priceCurrency": "USD",
"availability": "https://schema.org/PreOrder",
"availabilityStarts": "2026-06-13T09:00:00-07:00"
}
]
}
Shopify Liquid implementation
Store membership tier and discount data in product metafields. Use product tags as a lightweight gate for member-only products:
{% comment %}Member pricing — driven by product.metafields.loyalty.*{% endcomment %}
{% assign has_member_price = product.metafields.loyalty.member_price | default: '' %}
{% assign member_tier = product.metafields.loyalty.required_tier | default: 'Member' %}
{% assign member_discount = product.metafields.loyalty.discount_pct | default: '' %}
{% assign is_member_only = false %}
{% for tag in product.tags %}
{% if tag == 'members-only' or tag == 'vip-only' %}
{% assign is_member_only = true %}
{% endif %}
{% endfor %}
"offers": [
{
"@type": "Offer",
"name": "Standard price",
"price": {{ variant.price | money_without_currency | json }},
"priceCurrency": {{ cart.currency.iso_code | json }},
"availability": {% if variant.available %}"https://schema.org/InStock"{% else %}"https://schema.org/OutOfStock"{% endif %}
}{% if has_member_price != '' %},
{
"@type": "Offer",
"name": {{ member_tier | append: ' member price' | json }},
"price": {{ has_member_price | json }},
"priceCurrency": {{ cart.currency.iso_code | json }},
"availability": {% if variant.available %}"https://schema.org/InStock"{% else %}"https://schema.org/OutOfStock"{% endif %},
"additionalProperty": [
{
"@type": "PropertyValue",
"propertyID": "requiredMembershipTier",
"value": {{ member_tier | json }}
}
{% if member_discount != '' %},
{
"@type": "PropertyValue",
"propertyID": "memberDiscount",
"value": {{ member_discount | json }}
}
{% endif %}
{% if is_member_only %},
{
"@type": "PropertyValue",
"propertyID": "memberOnlyProduct",
"value": "true"
}
{% endif %}
]
}
{% endif %}
]
Loyalty tier reference — common Shopify program structures
| Program structure | Typical tier names | Primary signal | Secondary signal |
|---|---|---|---|
| Point-based (Smile.io, LoyaltyLion) | Bronze / Silver / Gold / Platinum | requiredMembershipTier |
memberDiscount per tier |
| Spend-threshold (VIP tiers) | Member / VIP / Elite / Insider | requiredMembershipTier |
memberOnlyProduct: true for exclusives |
| Subscription-based | Subscriber / Premium / Pro | requiredMembershipTier: Subscriber |
availabilityStarts for early access |
| App-based loyalty (Yotpo Loyalty) | Insider / VIP / Icon | requiredMembershipTier |
membershipProgramName |
| Co-brand / community membership | Community / Pro / Founder | memberOnlyProduct: true |
requiredMembershipTier + program name |
Common Mistakes
1. Relying on loyalty app JavaScript for member pricing signals
Every major Shopify loyalty app (LoyaltyLion, Smile.io, Yotpo Loyalty, Okendo) injects member pricing, tier messaging, and discount overlays via JavaScript. These are completely invisible to AI agent crawlers. The loyalty app and your JSON-LD serve different audiences: the app serves logged-in humans; the JSON-LD serves AI agents and search indexers. Both must be maintained independently.
2. Exposing private member prices in public structured data
For programs where the member price is confidential (members-only pricing not disclosed publicly), do not include the actual price in the member Offer JSON-LD. Instead, declare only the requiredMembershipTier additionalProperty and memberOnlyProduct: true — this signals membership exclusivity without revealing pricing. Include the discount percentage (memberDiscount) only if your program already publicizes the discount rate (e.g., "Gold members always get 20% off").
3. Using a single Offer and hiding the member price in description text
Writing "Gold members get 20% off" in the product description is not machine-readable for pricing queries. AI agents reading structured data for price filtering or member-discount queries look at the Offer.price and Offer.additionalProperty — not the Product.description text. A dual-Offer structure is required to make member pricing queryable.
4. Setting memberOnlyProduct without a membership program name
Declaring a product as memberOnlyProduct: true without identifying the program (membershipProgramName additionalProperty) leaves AI agents unable to link the exclusivity claim to a specific loyalty program. A user asking "exclusive products from [brand]'s insider program" needs the program name to be explicit in the structured data, not just a bare true flag.
5. Forgetting to update availabilityStarts after the early access window closes
If you use availabilityStarts on an early access Offer and the window passes without removing the future-dated Offer, AI agents will continue to read the product as not-yet-available to the general public even after the public launch. Use a metafield-driven approach where availabilityStarts is stored as a metafield value you can clear after the window passes, rather than hardcoding dates in the Liquid template.
Implementation Checklist
- Use a dual-Offer array in product JSON-LD: one public Offer at standard price, one member Offer with tier requirement
- Add
requiredMembershipTieradditionalProperty on member Offer(s) matching your program tier names exactly - Add
memberDiscountadditionalProperty with numeric percentage value if your discount rate is publicly disclosed - For member-only products, add
memberOnlyProduct: trueandmembershipProgramNameadditionalProperty - For early access, combine
availabilityStartsISO 8601 datetime withrequiredMembershipTieron the early-access Offer - Store member price and tier data in product metafields under a
loyaltynamespace - Gate member-only product signals with a product tag check to avoid injecting empty membership signals on standard products
- Drive
availabilityStartsfrom a metafield value (not a hardcoded date) so it can be cleared after the early-access window closes - Run CatalogScan to verify dual-Offer and membership signals appear in your AI readiness report
Frequently Asked Questions
How do I mark up member-only pricing in Shopify product structured data?
Use a dual offers array: a public Offer with standard price and a member Offer with member price. On the member Offer, add additionalProperty: requiredMembershipTier with your tier name, and optionally memberDiscount with the discount percentage. Store member prices in product metafields under a loyalty namespace and inject via Liquid.
Should member-only products that aren't publicly visible be indexed?
Products with a public URL that require login to purchase should have full structured data including the membership requirement signal — this lets AI agents accurately surface member-exclusive products in response to loyalty queries. Products with no public URL (completely hidden behind a password) should not be in your sitemap and will not be crawled by AI agents.
What schema.org type should I use for loyalty program membership?
Use additionalProperty with propertyID: requiredMembershipTier on products that require a specific tier. For the loyalty program entity itself, ProgramMembership describes the program — include programName and a URL to the program sign-up page. Reference the program name in a membershipProgramName additionalProperty on member-exclusive products.
How do I mark up early access products for loyalty members?
Create a member Offer with availabilityStarts set to the early access date (ISO 8601 with timezone) and additionalProperty: requiredMembershipTier for the tier that gets early access. Create a separate public Offer with availabilityStarts set to the public launch date. Drive both dates from metafields so they can be updated without template edits.
Does Shopify include loyalty or member pricing in its default product JSON-LD?
No. Shopify outputs a single Offer with base price only. All loyalty app pricing (LoyaltyLion, Smile.io, Yotpo Loyalty) is injected via JavaScript — invisible to AI agent crawlers. You must manually add dual-Offer structures and membership additionalProperty signals in product.liquid.