$npx -y skills add jezweb/claude-skills --skill shopify-productsCreate and manage Shopify products via the Admin GraphQL API or CSV import. Workflow: gather data, choose method, execute, verify. Use whenever the user wants to add products to Shopify, bulk-import a catalog from CSV/spreadsheet/URL, update variants or prices, manage inventory q
| 1 | # Shopify Products |
| 2 | |
| 3 | Create, update, and bulk-import Shopify products. Produces live products in the store via the GraphQL Admin API or CSV import. |
| 4 | |
| 5 | ## Prerequisites |
| 6 | |
| 7 | - Admin API access token (use the **shopify-setup** skill if not configured) |
| 8 | - Store URL and API version from `shopify.config.json` or `.dev.vars` |
| 9 | |
| 10 | ## Workflow |
| 11 | |
| 12 | ### Step 1: Gather Product Data |
| 13 | |
| 14 | Determine what the user wants to create or update: |
| 15 | |
| 16 | - **Product basics**: title, description (HTML), product type, vendor, tags |
| 17 | - **Variants**: options (size, colour, material), prices, SKUs, inventory quantities |
| 18 | - **Images**: URLs to upload, or local files |
| 19 | - **SEO**: page title, meta description, URL handle |
| 20 | - **Organisation**: collections, product type, tags |
| 21 | |
| 22 | Accept data from: |
| 23 | - Direct conversation (user describes products) |
| 24 | - Spreadsheet/CSV file (user provides a file) |
| 25 | - Website scraping (user provides a URL to extract from) |
| 26 | |
| 27 | ### Step 2: Choose Method |
| 28 | |
| 29 | | Scenario | Method | |
| 30 | |----------|--------| |
| 31 | | 1-5 products | GraphQL mutations | |
| 32 | | 6-20 products | GraphQL with batching | |
| 33 | | 20+ products | CSV import via admin | |
| 34 | | Updates to existing | GraphQL mutations | |
| 35 | | Inventory adjustments | `inventorySetQuantities` mutation | |
| 36 | |
| 37 | --- |
| 38 | |
| 39 | ### Step 3a: Create via GraphQL (Recommended) |
| 40 | |
| 41 | #### productCreate |
| 42 | |
| 43 | ```graphql |
| 44 | mutation productCreate($product: ProductCreateInput!) { |
| 45 | productCreate(product: $product) { |
| 46 | product { |
| 47 | id |
| 48 | title |
| 49 | handle |
| 50 | status |
| 51 | variants(first: 100) { |
| 52 | edges { |
| 53 | node { id title price sku inventoryQuantity } |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 | userErrors { field message } |
| 58 | } |
| 59 | } |
| 60 | ``` |
| 61 | |
| 62 | Variables: |
| 63 | |
| 64 | ```json |
| 65 | { |
| 66 | "product": { |
| 67 | "title": "Example T-Shirt", |
| 68 | "descriptionHtml": "<p>Premium cotton tee</p>", |
| 69 | "vendor": "My Brand", |
| 70 | "productType": "T-Shirts", |
| 71 | "tags": ["summer", "cotton"], |
| 72 | "status": "DRAFT", |
| 73 | "options": ["Size", "Colour"], |
| 74 | "variants": [ |
| 75 | { |
| 76 | "optionValues": [ |
| 77 | {"optionName": "Size", "name": "S"}, |
| 78 | {"optionName": "Colour", "name": "Black"} |
| 79 | ], |
| 80 | "price": "29.95", |
| 81 | "sku": "TSHIRT-S-BLK", |
| 82 | "inventoryPolicy": "DENY", |
| 83 | "inventoryItem": { "tracked": true } |
| 84 | }, |
| 85 | { |
| 86 | "optionValues": [ |
| 87 | {"optionName": "Size", "name": "M"}, |
| 88 | {"optionName": "Colour", "name": "Black"} |
| 89 | ], |
| 90 | "price": "29.95", |
| 91 | "sku": "TSHIRT-M-BLK" |
| 92 | }, |
| 93 | { |
| 94 | "optionValues": [ |
| 95 | {"optionName": "Size", "name": "L"}, |
| 96 | {"optionName": "Colour", "name": "Black"} |
| 97 | ], |
| 98 | "price": "29.95", |
| 99 | "sku": "TSHIRT-L-BLK" |
| 100 | } |
| 101 | ], |
| 102 | "seo": { |
| 103 | "title": "Example T-Shirt | My Brand", |
| 104 | "description": "Premium cotton tee in multiple sizes" |
| 105 | } |
| 106 | } |
| 107 | } |
| 108 | ``` |
| 109 | |
| 110 | Curl example: |
| 111 | |
| 112 | ```bash |
| 113 | curl -s https://{store}/admin/api/2025-01/graphql.json \ |
| 114 | -H "Content-Type: application/json" \ |
| 115 | -H "X-Shopify-Access-Token: {token}" \ |
| 116 | -d '{"query": "mutation productCreate($product: ProductCreateInput!) { productCreate(product: $product) { product { id title } userErrors { field message } } }", "variables": { ... }}' |
| 117 | ``` |
| 118 | |
| 119 | **Batching multiple products**: Create products sequentially with a short delay between each to respect rate limits (1,000 cost points/second). |
| 120 | |
| 121 | #### productUpdate |
| 122 | |
| 123 | ```graphql |
| 124 | mutation productUpdate($input: ProductInput!) { |
| 125 | productUpdate(input: $input) { |
| 126 | product { id title } |
| 127 | userErrors { field message } |
| 128 | } |
| 129 | } |
| 130 | ``` |
| 131 | |
| 132 | Variables include `id` (required) plus any fields to update. |
| 133 | |
| 134 | #### productDelete |
| 135 | |
| 136 | ```graphql |
| 137 | mutation productDelete($input: ProductDeleteInput!) { |
| 138 | productDelete(input: $input) { |
| 139 | deletedProductId |
| 140 | userErrors { field message } |
| 141 | } |
| 142 | } |
| 143 | ``` |
| 144 | |
| 145 | #### productVariantsBulkCreate |
| 146 | |
| 147 | Add variants to an existing product: |
| 148 | |
| 149 | ```graphql |
| 150 | mutation productVariantsBulkCreate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) { |
| 151 | productVariantsBulkCreate(productId: $productId, variants: $variants) { |
| 152 | productVariants { id title price } |
| 153 | userErrors { field message } |
| 154 | } |
| 155 | } |
| 156 | ``` |
| 157 | |
| 158 | #### productVariantsBulkUpdate |
| 159 | |
| 160 | ```graphql |
| 161 | mutation productVariantsBulkUpdate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) { |
| 162 | productVariantsBulkUpdate(productId: $productId, variants: $variants) { |
| 163 | productVariants { id title price } |
| 164 | userErrors { field message } |
| 165 | } |
| 166 | } |
| 167 | ``` |
| 168 | |
| 169 | --- |
| 170 | |
| 171 | ### Step 3b: Bulk Import via CSV |
| 172 | |
| 173 | For 20+ products, generate a CSV and import through Shopify admin. |
| 174 | |
| 175 | #### CSV Column Reference |
| 176 | |
| 177 | **Required columns:** |
| 178 | |
| 179 | | Column | Description | Example | |
| 180 | |--------|-------------|---------| |
| 181 | | `Handle` | URL slug (unique per product) | `classic-tshirt |