From ecom
Adds supplemental JSON-LD structured data to Shopify stores for schema types the theme can't generate (Recipe, FAQPage, Article, etc.). Use for rich-results eligibility and debugging Search Console errors.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ecom:shopify-json-ldThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Adds **supplemental** structured data to a Shopify store: the schema types the
Adds supplemental structured data to a Shopify store: the schema types the theme can't generate on its own (Recipe, FAQPage, richer Article/Collection nodes), stored as JSON-LD in a per-entity metafield and rendered through a single Liquid snippet. The governing principle: you add what's missing, you never duplicate what the theme already emits. For meta tags, descriptions, and Open Graph (a different job), use the sibling skill shopify-seo-metadata.
Lane A: custom-app token (scriptable). In Shopify admin: Settings → Apps and sales channels → Develop apps → create an app → grant this skill's minimum scopes, then install and copy the Admin API access token. Export it; never write it to a committed file:
export SHOPIFY_STORE="your-store.myshopify.com"
export SHOPIFY_ACCESS_TOKEN="<your Admin API access token>" # env only, not on disk
Minimum scopes: read_products, write_products, read_content,
write_content. There is no standalone metafield scope; metafield access is
governed by the owning resource's scope (products → write_products,
pages/articles → write_content). Rendering the snippet needs theme edit
access (theme editor or the theme's Git repo), which is separate from the API.
Sanity-check the token:
curl -s "https://$SHOPIFY_STORE/admin/api/2025-07/graphql.json" \
-H "X-Shopify-Access-Token: $SHOPIFY_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ shop { name } }"}'
Lane B: Shopify CLI OAuth (no stored token). shopify store auth --store $SHOPIFY_STORE --scopes read_products,write_products,read_content,write_content then
shopify store execute. Good for token-less stores where the owner logs in.
Toolkit preflight. Lane B rides on the Shopify CLI: run shopify version
first and install it if missing. For the full Admin GraphQL schema and
validated execution, pair this skill with Shopify's official AI toolkit
plugin. In Claude Code, check claude plugin list; if it isn't there:
claude plugin marketplace add Shopify/Shopify-AI-Toolkit
claude plugin install shopify-plugin@shopify-ai-toolkit
Recommended, not required: Lane A needs only curl and a token. The toolkit gives your agent the API; this skill gives it the playbook.
Modern Shopify themes already emit Product schema on PDPs (price, variants,
availability, and, with a review app like Judge.me, Yotpo, or Stamped,
aggregateRating), plus Organization/WebSite sitewide and often
Article/BreadcrumbList. Duplicating any of it creates conflicting nodes that
degrade eligibility, not improve it.
So the first move is always read-only: fetch the homepage, a PDP, a collection,
and a blog post, and extract every <script type="application/ld+json"> block.
curl -s "https://$SHOPIFY_STORE/products/<some-handle>" \
| grep -o '<script type="application/ld+json">[^<]*' | head
Whatever the theme already covers, you do not touch. Supplemental schema is a separate type on the same page (a FAQPage or Recipe node alongside the theme's Product node), never a second Product node. If the theme's Product schema is broken or missing, fix the theme. Don't paper over it with a duplicate.
Store the JSON-LD in a metafield and render it verbatim. Nothing transforms the value at render time, so the stored string must already be valid JSON-LD.
Define the metafield (Settings → Custom Data → the entity type → Add
definition): namespace custom, key json, type multi_line_text_field.
Create it for each entity type you'll populate (Products, Collections, Pages,
Articles).
Add one render snippet to theme.liquid, before </head>:
{%- if request.page_type == 'product' and product.metafields.custom.json != blank -%}
<script type="application/ld+json">{{ product.metafields.custom.json }}</script>
{%- elsif request.page_type == 'collection' and collection.metafields.custom.json != blank -%}
<script type="application/ld+json">{{ collection.metafields.custom.json }}</script>
{%- elsif request.page_type == 'page' and page.metafields.custom.json != blank -%}
<script type="application/ld+json">{{ page.metafields.custom.json }}</script>
{%- elsif request.page_type == 'article' and article.metafields.custom.json != blank -%}
<script type="application/ld+json">{{ article.metafields.custom.json }}</script>
{%- endif -%}
metafieldsSet (GraphQL). It upserts by
namespace/key, so it updates an existing metafield instead of duplicating it:
this sidesteps the classic REST trap of POSTing a second metafield when one
already exists. Store the JSON compact (JSON.stringify(obj), no pretty
spacing). Preview the target count before a bulk write; a count far above
expectation means stop and re-scope. Full pipeline and per-entity prompts:
references/pipeline-and-prompts.md.Google validates every typed node it finds, including deeply nested ones. A single malformed node fails the whole block. Two rules prevent nearly all of it:
Product nodes. Google requires offers, review, or
aggregateRating on every @type: "Product". In supplemental schema you
rarely have those (the theme owns them), so referencing a product by name uses
@type: "Thing", never Product.VideoObject nodes. VideoObject requires name,
description, thumbnailUrl, uploadDate, and a contentUrl or embedUrl.
If you don't have real video metadata, don't emit VideoObject: use Thing
or an ItemList of ListItem entries instead.These two mistakes are the usual cause of "Invalid object type for field" and "missing field" errors in Search Console.
Google removed FAQ rich results for non-authoritative (commerce) sites in 2026. FAQPage markup on a product or store page will no longer render the expandable Q&A snippet in search. It's still valid structured data and still feeds machine understanding of the page, but do not sell or promote it as a rich-result / SERP-visibility win. That claim is stale. Recipe, and where genuinely applicable Article, remain eligible; verify current eligibility per type against Google's docs (see Provenance) before promising a visible result.
When an agent generates FAQ or descriptive schema from product/page content, it may only assert facts present in the source text. No invented dimensions, weight limits, materials, or features. If the source description is thin, generate fewer entries: three grounded Q&As beat five with two fabricated answers, and a fabricated spec in schema is a factual claim Google (and the customer) can catch. The prompt must prohibit fabrication explicitly and prefer "omit" over "guess". Per-entity prompt scaffolding is in the reference.
After a write, the storefront can serve the old JSON-LD for minutes to hours: Shopify's CDN caches the rendered page. Confirm the write by reading the metafield back through the Admin API, not by curling the product page:
curl -s "https://$SHOPIFY_STORE/admin/api/2025-07/graphql.json" \
-H "X-Shopify-Access-Token: $SHOPIFY_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ product(id:\"gid://shopify/Product/<ID>\") { metafield(namespace:\"custom\",key:\"json\"){ value } } }"}'
The metafield value is ground truth. Once it's correct, the storefront will catch up on its own cache cycle: that lag is not a bug to chase.
custom.json values first).Last verified: 2026-07-05. GraphQL pinned to Admin API 2025-07; Shopify deprecates versions quarterly, so confirm the version before trusting a version-specific claim. Google's rich-result eligibility changes: FAQ rich results were deprecated for commerce sites, and other types shift too, so re-verify per schema type against Google's structured-data docs before promising a visible SERP result. Canonical type definitions live at schema.org. Read-only re-verification a stranger can run:
# 1. Confirm the token reaches the store.
curl -s "https://$SHOPIFY_STORE/admin/api/2025-07/graphql.json" \
-H "X-Shopify-Access-Token: $SHOPIFY_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ shop { name } }"}'
# 2. Confirm a product page actually renders a JSON-LD block.
curl -s "https://$SHOPIFY_STORE/products/<some-handle>" \
| grep -c 'application/ld+json'
Then validate any live URL in Google's Rich Results Test (https://search.google.com/test/rich-results). These skills capture operational lessons the docs don't; they don't replace the schema.org or Google references.
npx claudepluginhub kgelster/awesome-ecom-skills --plugin ecomGenerates valid JSON-LD schema.org structured data for rich results. Identifies applicable schema types, creates JSON-LD blocks, and verifies against Google's Rich Results requirements.
Generates and validates JSON-LD schema.org markup for rich search results, covering types like FAQ, product, review, breadcrumb, and more. Helps pages earn enhanced Google results.
Adds, fixes, and optimizes schema.org structured data (JSON-LD) to enable rich results in Google Search. Covers FAQ, Product, Article, Organization, and other schema types.