From ecom
Assigns Shopify Standard Product Taxonomy categories and fills associated category metafields (Color, Size, Material) via GraphQL API, including reserved value metaobjects and troubleshooting null metafields.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ecom:shopify-category-taxonomyThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Two jobs that chain together: **assign** a product's Standard Product Taxonomy
Two jobs that chain together: assign a product's Standard Product Taxonomy
category (Part 1), then fill the category metafields that category exposes
(Part 2). You cannot do Part 2 until Part 1 is true: the "Category metafields"
panel only exists once a product is assigned to a category. Bulk CSV data work
lives in the sibling shopify-matrixify; the one thing Matrixify cannot do
is mint the reserved value metaobjects Part 2 needs, which is the entire reason
this skill exists.
Lane A: custom-app token (scriptable). Shopify admin → Settings → Apps and sales channels → Develop apps → create an app → grant the four scopes below → install → copy the Admin API access token. Export it; never write it to disk:
export SHOPIFY_STORE="your-store.myshopify.com"
export SHOPIFY_ACCESS_TOKEN="<your Admin API access token>" # env, not disk
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 } }"}'
Minimum scopes: read_products, write_products, read_metaobjects,
write_metaobjects. The metaobjects pair is not optional (see the null trap).
Lane B: Shopify CLI OAuth (no stored token). shopify store auth --store $SHOPIFY_STORE --scopes read_products,write_products,read_metaobjects,write_metaobjects
then shopify store execute. Good for token-less stores where the owner logs in
interactively.
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.
Treat every GraphQL block as a copy-and-adapt recipe your agent writes fresh, runs, and discards. Two rules keep that safe:
metafieldsSet deletes the metafield, so only emit non-blank values.
Abort the run on first-batch userErrors.Verify against ground truth via the Admin API, not the storefront (CDN-cached, lies about freshness). Never print or commit the token.
Set each product's category field to a Standard Product Taxonomy category via
productUpdate (or the Matrixify Category column for a pure bulk load).
CRITICAL: verify every category ID against the official taxonomy source; never
guess an ID. A guessed taxonomy ID resolves to the wrong category or a dead
node, and it fails silently: the product looks categorized but every downstream
attribute, filter, and feed mapping is now wrong. Guessed IDs have burned real
product feeds. Resolve the ID by search: against taxonomy { categories }
(Part 2 step 1 shows the query), or from the official taxonomy repo linked in
Provenance.
Classification signal priority (highest to lowest confidence):
tags (highest on stores that tag by category: a "Mango" tea tagged
black-tea is a flavored black, not a fruit infusion, and the tag says so
where the title misleads) > product type (good when the store populates it,
many don't) > title / vendor (lexical fallback; a mono-line vendor pins the
category, a multi-line one doesn't) > description (last resort; verbose and
easy to mis-key on flavor words).
Emit a confidence flag per product and split the catalog into high-confidence vs ambiguous (bundles, samplers, cross-category items). Ship the high-confidence rows; route the ambiguous ones to a human review sheet rather than guessing. See the SOP's pull-then-classify steps below.
# preview (read-only): how many products your classifier targets, before any write
query { productsCount(query: "tag:black-tea status:active") { count } }
# then, per high-confidence product, assign the category
mutation Assign($id: ID!, $cat: ID!) {
productUpdate(product: {id: $id, category: $cat}) {
product { id category { id fullName } }
userErrors { field message }
}
}
A category metafield is not a plain text/choice value. It is a metafield in
the reserved shopify namespace, of type list.metaobject_reference, whose
value is a JSON array of Metaobject GIDs. Each of those metaobjects is a
reserved taxonomy value (type: "shopify--<attribute>") with a label and a
taxonomy_reference pointing at a global TaxonomyValue. The chain:
Product
└─ metafield shopify.<attribute> (list.metaobject_reference)
└─ value: ["gid://shopify/Metaobject/…"]
└─ Metaobject type: shopify--<attribute> label: "Decaf"
└─ taxonomy_reference ─▶ TaxonomyValue/26137 (global)
These value metaobjects are minted on demand: a store only holds metaobjects for values it has actually used. A brand-new value must be created before you can reference it. That mint-then-reference step is what Matrixify cannot do.
Top 5 gotchas (fuller list in the reference):
read_metaobjects, the value metaobjects
return null from node(), references, and metaobjectDefinitions: the
whole feature looks read-only. With the scope they resolve. Minting needs
write_metaobjects.TaxonomyValue GID is rejected on write. metafieldsSet demands the
Metaobject GID, not the taxonomy value GID (else "Value require that you
select a metaobject"). The TaxonomyValue GID is only the taxonomy_reference
you pass when creating the metaobject.product.category, not by
product type or title.1. Discover the category, its attributes, and allowed values.
query {
taxonomy {
categories(first: 1, search: "Tea & Infusions > Tea") {
nodes {
id fullName
attributes(first: 50) {
nodes {
... on TaxonomyChoiceListAttribute {
id name
values(first: 50) { nodes { id name } } # id = TaxonomyValue GID
}
... on TaxonomyMeasurementAttribute { id name }
}
}
}
}
}
}
Record per attribute: the metafield key (the attribute handle,
lowercased-hyphenated, confirm it by reading an already-set product in step 6;
the Color attribute's key is color-pattern, not color) and the value name →
TaxonomyValue GID map.
2. Pull the catalog, scoped to the target category. Do not classify blind: page every candidate product first, capturing the signals the classifier reads.
query($cursor: String) {
products(first: 100, after: $cursor, query: "status:active") {
pageInfo { hasNextPage endCursor }
nodes {
id handle title vendor productType tags
category { id fullName }
options { name optionValues { name } }
metafields(namespace: "shopify", first: 25) { nodes { key jsonValue } }
}
}
}
For a large catalog, run this as a bulkOperationRunQuery dump instead of live
pagination; the dump doubles as your pre-write backup.
3. Classify into high-confidence vs ambiguous. Apply the signal priority (tags first). Emit a confidence flag per product; the high-confidence rows ship, the ambiguous ones (bundles, samplers, cross-category, low-signal titles) route to a review spreadsheet a human corrects before you write anything. This split is what let one tea retailer ship 583 of 717 products high-confidence and hold the remaining 134 for review instead of guessing. Assign the category (Part 1) on the high-confidence rows now; then continue to mint/set below.
4. Mint each missing value metaobject (once per store). Reuse an existing
metaobject when its label already matches; only mint when genuinely absent.
mutation M($m: MetaobjectCreateInput!) {
metaobjectCreate(metaobject: $m) {
metaobject { id displayName } userErrors { field message code }
}
}
# variables:
# {"m":{"type":"shopify--caffeine-content","handle":"decaf",
# "fields":[{"key":"label","value":"Decaf"},
# {"key":"taxonomy_reference","value":"gid://shopify/TaxonomyValue/26137"}]}}
Build a value name → Metaobject GID map from the results plus existing entries.
5. Apply via metafieldsSet, batches of ≤25 metafields per call.
mutation S($m: [MetafieldsSetInput!]!) {
metafieldsSet(metafields: $m) {
metafields { id } userErrors { field message code }
}
}
# each entry: {ownerId, namespace:"shopify", key:"tea-variety",
# type:"list.metaobject_reference",
# value:"[\"gid://shopify/Metaobject/…\"]"}
Emit only non-blank values. Abort on first-batch errors.
6. Verify by reading back resolved labels, not by trusting the write's
userErrors: [].
query { product(id: "gid://shopify/Product/…") {
metafields(namespace: "shopify", first: 10) { nodes {
key references(first: 5) { nodes { ... on Metaobject { displayName } } } } } } }
Spot-check several products; confirm every name resolves to what you intended.
Last verified: 2026-07-05. GraphQL pinned to Admin API 2025-07; Shopify deprecates versions on a rolling quarterly schedule, so verify field shapes against shopify.dev and the metafields/metaobjects docs before trusting a version-specific claim. The category IDs and taxonomy values come from Shopify's Standard Product Taxonomy: the canonical source to verify an ID against; never guess one.
Read-only re-verification a stranger can run (no writes):
# 1. token reaches the store and reads a product's assigned category
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":"{ products(first:1){ nodes{ category { id name } } } }"}'
# 2. taxonomy discovery resolves (confirms the taxonomy API + your read scope)
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":"{ taxonomy { categories(first:1, search:\"Tea\"){ nodes{ id fullName } } } }"}'
These skills capture operational lessons the docs don't; they are not a replacement for the reference.
npx claudepluginhub kgelster/awesome-ecom-skills --plugin ecomAssign every product a Shopify Standard Product Taxonomy category so AI agents can map a shopper's intent to the right category and surface the store's products.
Manages Shopify product catalogs: products, variants, options, collections, metafields, metaobjects, inventory, bulk operations, taxonomy, media via GraphQL API.
Creates and manages Shopify products via GraphQL Admin API or CSV imports. Bulk import/update variants, inventory, images, assign to collections.