AS
AgSkills.dev
MARKETPLACE

shopify-api-patterns

Common Shopify Admin GraphQL API patterns for product queries, metafield operations, webhooks, and bulk operations. Auto-invoked when working with Shopify API integration.

4
0

Preview

SKILL.md
name
shopify-api-patterns
description
Common Shopify Admin GraphQL API patterns for product queries, metafield operations, webhooks, and bulk operations. Auto-invoked when working with Shopify API integration.
allowed-tools
[Read, Edit, Write, Grep, Glob]

Shopify API Patterns Skill

Purpose

Provides reusable patterns for common Shopify Admin GraphQL API operations including product queries, metafield management, webhook handling, and bulk operations.

When This Skill Activates

  • Working with Shopify Admin GraphQL API
  • Querying products, variants, customers, or orders
  • Managing metafields
  • Implementing webhooks
  • Handling bulk operations
  • Implementing rate limiting

Core Patterns

1. Product Query with Pagination

query getProducts($first: Int!, $after: String) { products(first: $first, after: $after) { edges { node { id title vendor handle productType tags variants(first: 10) { edges { node { id title price sku } } } } cursor } pageInfo { hasNextPage endCursor } } }

2. Metafield Query Pattern

query getProductMetafields($productId: ID!) { product(id: $productId) { id title metafields(first: 20, namespace: "custom") { edges { node { id namespace key value type } } } } }

3. Metafield Update Mutation

mutation updateMetafields($metafields: [MetafieldsSetInput!]!) { metafieldsSet(metafields: $metafields) { metafields { id namespace key value type } userErrors { field message } } }

Usage Example:

const response = await admin.graphql(UPDATE_METAFIELDS, { variables: { metafields: [ { ownerId: "gid://shopify/Product/123", namespace: "custom", key: "color", value: "Red", type: "single_line_text_field", }, ], }, });

4. Metafield Definition Creation

mutation createMetafieldDefinition($definition: MetafieldDefinitionInput!) { metafieldDefinitionCreate(definition: $definition) { createdDefinition { id name namespace key type ownerType } userErrors { field message } } }

Usage:

await admin.graphql(CREATE_METAFIELD_DEFINITION, { variables: { definition: { name: "Product Color", namespace: "custom", key: "color", type: "single_line_text_field", ownerType: "PRODUCT", }, }, });

5. Webhook Registration

mutation registerWebhook($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) { webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) { webhookSubscription { id topic endpoint { __typename ... on WebhookHttpEndpoint { callbackUrl } } } userErrors { field message } } }

Common Topics:

  • PRODUCTS_CREATE
  • PRODUCTS_UPDATE
  • PRODUCTS_DELETE
  • ORDERS_CREATE
  • CUSTOMERS_CREATE

6. Pagination Helper

async function fetchAllProducts(admin) { let hasNextPage = true; let cursor = null; const allProducts = []; while (hasNextPage) { const response = await admin.graphql(GET_PRODUCTS, { variables: { first: 250, after: cursor }, }); const data = await response.json(); if (data.errors) { throw new Error(`GraphQL error: ${data.errors[0].message}`); } const products = data.data.products.edges.map(edge => edge.node); allProducts.push(...products); hasNextPage = data.data.products.pageInfo.hasNextPage; cursor = data.data.products.pageInfo.endCursor; // Rate limiting check const rateLimitCost = response.headers.get("X-Shopify-Shop-Api-Call-Limit"); if (rateLimitCost) { const [used, total] = rateLimitCost.split("/").map(Number); if (used > total * 0.8) { await new Promise(resolve => setTimeout(resolve, 1000)); } } } return allProducts; }

7. Bulk Operation Pattern

mutation bulkOperationRunQuery { bulkOperationRunQuery( query: """ { products { edges { node { id title metafields { edges { node { namespace key value } } } } } } } """ ) { bulkOperation { id status } userErrors { field message } } }

Check Status:

query { currentBulkOperation { id status errorCode createdAt completedAt objectCount fileSize url } }

Download and Process Results:

async function processBulkOperationResults(url: string) { const response = await fetch(url); const jsonl = await response.text(); const lines = jsonl.trim().split("\n"); const results = lines.map(line => JSON.parse(line)); return results; }

8. Rate Limiting Handler

async function graphqlWithRetry(admin, query, variables, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const response = await admin.graphql(query, { variables }); // Check rate limit const rateLimitCost = response.headers.get("X-Shopify-Shop-Api-Call-Limit"); if (rateLimitCost) { const [used, total] = rateLimitCost.split("/").map(Number); console.log(`API calls: ${used}/${total}`); if (used > total * 0.9) { console.warn("Approaching rate limit, slowing down..."); await new Promise(resolve => setTimeout(resolve, 2000)); } } const data = await response.json(); if (data.errors) { throw new Error(`GraphQL error: ${data.errors[0].message}`); } return data; } catch (error) { if (error.message.includes("Throttled") && i < maxRetries - 1) { const delay = Math.pow(2, i) * 1000; // Exponential backoff console.log(`Rate limited, retrying in ${delay}ms...`); await new Promise(resolve => setTimeout(resolve, delay)); continue; } throw error; } } }

Best Practices

  1. Pagination - Always use cursor-based pagination for large result sets
  2. Field Selection - Only request fields you need to reduce response size
  3. Rate Limiting - Monitor API call limits and implement backoff
  4. Error Handling - Check both errors and userErrors in responses
  5. Bulk Operations - Use for processing 1000+ products
  6. Metafield Types - Use appropriate types (single_line_text_field, number_integer, json, etc.)
  7. Webhook Verification - Always verify HMAC signatures
  8. Caching - Cache frequently accessed data like metafield definitions
  9. Retry Logic - Implement exponential backoff for transient failures
  10. Logging - Log API calls and errors for debugging

Common Metafield Types

  • single_line_text_field - Short text
  • multi_line_text_field - Long text
  • number_integer - Whole numbers
  • number_decimal - Decimal numbers
  • json - Structured data
  • color - Color values
  • url - URLs
  • boolean - True/false
  • date - Date values
  • list.single_line_text_field - Array of strings

Quick Reference

Get Product by Handle

query getProductByHandle($handle: String!) { productByHandle(handle: $handle) { id title vendor } }

Get Product Variants

query getProductVariants($productId: ID!) { product(id: $productId) { variants(first: 100) { edges { node { id title price sku inventoryQuantity } } } } }

Update Product

mutation productUpdate($input: ProductInput!) { productUpdate(input: $input) { product { id title } userErrors { field message } } }

Remember: Always check the Shopify Admin API documentation for the latest schema and deprecations.

GitHub Repository
sarojpunde/shopify-dev-toolkit-claude-plugins
Stars
4
Forks
0
Open Repository
Install Skill
Download ZIP1 files