Agent Skills: Shopify Products & Catalog Management

|

UncategorizedID: jeremylongshore/claude-code-plugins-plus-skills/shopify-core-workflow-a

Install this agent skill to your local

pnpm dlx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/HEAD/plugins/saas-packs/shopify-pack/skills/shopify-core-workflow-a

Skill Files

Browse the full folder contents for shopify-core-workflow-a.

Download Skill

Loading file tree…

plugins/saas-packs/shopify-pack/skills/shopify-core-workflow-a/SKILL.md

Skill Metadata

Name
shopify-core-workflow-a
Description
|

Shopify Products & Catalog Management

Overview

Primary workflow for Shopify: manage products, variants, collections, and inventory using the GraphQL Admin API. Covers CRUD operations with real API mutations and response shapes.

Prerequisites

  • Completed shopify-install-auth setup
  • Access scopes: read_products, write_products, read_inventory, write_inventory
  • API version 2024-10 or later (ProductInput was split in this version)

Instructions

Step 1: Create a Product

// As of 2024-10, productCreate uses ProductCreateInput (not the old ProductInput)
const CREATE_PRODUCT = `
  mutation productCreate($input: ProductCreateInput!) {
    productCreate(product: $input) {
      product {
        id
        title
        handle
        status
        variants(first: 10) {
          edges {
            node {
              id
              title
              price
              sku
              inventoryQuantity
            }
          }
        }
      }
      userErrors {
        field
        message
        code
      }
    }
  }
`;

const response = await client.request(CREATE_PRODUCT, {
  variables: {
    input: {
      title: "Premium Cotton T-Shirt",
      descriptionHtml: "<p>Soft 100% organic cotton tee.</p>",
      vendor: "My Brand",
      productType: "Apparel",
      tags: ["cotton", "organic", "summer"],
      status: "DRAFT", // ACTIVE, DRAFT, or ARCHIVED
      productOptions: [
        {
          name: "Size",
          values: [{ name: "S" }, { name: "M" }, { name: "L" }, { name: "XL" }],
        },
        {
          name: "Color",
          values: [{ name: "Black" }, { name: "White" }, { name: "Navy" }],
        },
      ],
    },
  },
});

// ALWAYS check userErrors — Shopify returns 200 even on validation failures
if (response.data.productCreate.userErrors.length > 0) {
  console.error("Validation errors:", response.data.productCreate.userErrors);
  // Example: [{ field: ["title"], message: "Title can't be blank", code: "BLANK" }]
}

Step 2: Update a Product

// 2024-10+: productUpdate uses ProductUpdateInput (separate from create)
const UPDATE_PRODUCT = `
  mutation productUpdate($input: ProductUpdateInput!) {
    productUpdate(product: $input) {
      product {
        id
        title
        status
        updatedAt
      }
      userErrors {
        field
        message
      }
    }
  }
`;

await client.request(UPDATE_PRODUCT, {
  variables: {
    input: {
      id: "gid://shopify/Product/1234567890",
      title: "Updated Product Title",
      status: "ACTIVE",
      metafields: [
        {
          namespace: "custom",
          key: "care_instructions",
          value: "Machine wash cold",
          type: "single_line_text_field",
        },
      ],
    },
  },
});

Step 3: Query Products with Filtering

// Search products with Shopify's query syntax
const SEARCH_PRODUCTS = `
  query products($query: String!, $first: Int!, $after: String) {
    products(first: $first, after: $after, query: $query) {
      edges {
        node {
          id
          title
          handle
          status
          productType
          vendor
          totalInventory
          priceRangeV2 {
            minVariantPrice { amount currencyCode }
            maxVariantPrice { amount currencyCode }
          }
          images(first: 1) {
            edges {
              node { url altText }
            }
          }
        }
        cursor
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
`;

// Shopify query syntax examples:
// "status:active"
// "product_type:Apparel AND vendor:'My Brand'"
// "inventory_total:>0"
// "created_at:>2024-01-01"
// "tag:sale"
const data = await client.request(SEARCH_PRODUCTS, {
  variables: {
    query: "status:active AND product_type:Apparel",
    first: 25,
  },
});

Step 4: Manage Variants and Pricing

// Create variants in bulk
const BULK_CREATE_VARIANTS = `
  mutation productVariantsBulkCreate(
    $productId: ID!,
    $variants: [ProductVariantsBulkInput!]!
  ) {
    productVariantsBulkCreate(productId: $productId, variants: $variants) {
      productVariants {
        id
        title
        price
        sku
        barcode
        inventoryQuantity
        selectedOptions { name value }
      }
      userErrors {
        field
        message
        code
      }
    }
  }
`;

await client.request(BULK_CREATE_VARIANTS, {
  variables: {
    productId: "gid://shopify/Product/1234567890",
    variants: [
      {
        price: "29.99",
        sku: "TSH-BLK-S",
        barcode: "1234567890123",
        optionValues: [
          { optionName: "Color", name: "Black" },
          { optionName: "Size", name: "S" },
        ],
        inventoryQuantities: [
          {
            availableQuantity: 100,
            locationId: "gid://shopify/Location/1234",
          },
        ],
      },
    ],
  },
});

Step 5: Manage Collections

// Create a smart (automated) collection
const CREATE_SMART_COLLECTION = `
  mutation collectionCreate($input: CollectionInput!) {
    collectionCreate(input: $input) {
      collection {
        id
        title
        handle
        productsCount
        ruleSet {
          appliedDisjunctively
          rules { column relation condition }
        }
      }
      userErrors { field message }
    }
  }
`;

await client.request(CREATE_SMART_COLLECTION, {
  variables: {
    input: {
      title: "Summer Sale",
      descriptionHtml: "<p>All items on summer sale</p>",
      ruleSet: {
        appliedDisjunctively: false, // AND logic
        rules: [
          { column: "TAG", relation: "EQUALS", condition: "sale" },
          { column: "PRODUCT_TYPE", relation: "EQUALS", condition: "Apparel" },
        ],
      },
    },
  },
});

Output

  • Product created with variants and options
  • Products queryable with search filters
  • Variant pricing and inventory configured
  • Smart collections auto-organizing products

Error Handling

| Error | Cause | Solution | |-------|-------|----------| | userErrors: [{code: "TAKEN", field: ["handle"]}] | Duplicate product handle | Use a unique handle or let Shopify auto-generate | | userErrors: [{code: "BLANK", field: ["title"]}] | Empty required field | Provide non-empty title | | userErrors: [{code: "INVALID"}] | Invalid metafield type | Check type matches Shopify's metafield types | | Access denied on productCreate | Missing write_products scope | Request scope in app config | | Product not found | Wrong GID format | Must be gid://shopify/Product/{numeric_id} |

Examples

ProductSet Mutation (Upsert)

// productSet creates OR updates — idempotent by handle
const PRODUCT_SET = `
  mutation productSet($input: ProductSetInput!) {
    productSet(input: $input) {
      product { id title }
      userErrors { field message code }
    }
  }
`;

await client.request(PRODUCT_SET, {
  variables: {
    input: {
      title: "Organic Coffee Beans",
      handle: "organic-coffee-beans", // unique identifier
      productType: "Coffee",
      vendor: "Bean Co",
    },
  },
});

Resources

Next Steps

For order management workflow, see shopify-core-workflow-b.