Discuss and resolve questions on Liquid, JavaScript, themes, sales channels, and site speed enhancements.
I need some help with the GraphQL Admin API with creating a product with options or variants that have stock.
At the moment I've set this up:
// Preparing the Data:
const prepareProducts = (products) => {
return products.map((product) => {
// Prepare color options
const colorOptions = product.variants.reduce((acc, variant) => {
if (variant.codeColourName && !acc.includes(variant.codeColourName)) {
acc.push(variant.codeColourName);
}
return acc;
}, []);
const sizeOptions = product.variants.reduce((acc, variant) => {
if (variant.codeSizeName && !acc.includes(variant.codeSizeName)) {
acc.push(variant.codeSizeName);
}
return acc;
}, []);
const productOptions = [];
if (colorOptions.length > 0) {
productOptions.push({
name: "Color",
values: colorOptions.map((color) => ({ name: color })),
});
}
if (sizeOptions.length > 0) {
productOptions.push({
name: "Size",
values: sizeOptions.map((size) => ({ name: size })),
});
}
return {
title: product.productName,
bodyHtml: product.description,
vendor: "VENDOR",
productType: product.categories[0]?.name || "Default Category",
images: product.images.map((image) => ({
src: image.urls[0]?.url || "Default Image URL",
width: image.urls[0]?.width || 1024,
height: image.urls[0]?.height || 1024,
})),
productOptions: productOptions,
variants: product.variants.map((variant) => ({
price: variant.price || 0,
inventoryManagement: "SHOPIFY",
inventoryPolicy: "DENY",
sku: variant.fullCode,
inventoryQuantity: variant.stock || 0,
})),
};
});
};
Here I create the product with its media and options and stuff I need:
const createProductBatch = async (productsData) => {
// Product creation mutation
const productCreateMutation = `
mutation CreateProduct($input: ProductInput!, $media: [CreateMediaInput!]) {
productCreate(input: $input, media: $media) {
product {
id
options {
id
name
position
values
optionValues {
id
name
hasVariants
}
}
media(first: 10) {
nodes {
alt
mediaContentType
preview {
status
}
}
}
metafields(first: 10) {
edges {
node {
type
namespace
key
value
}
}
}
}
userErrors {
field
message
}
}
}
`;
const batchSize = 5;
const delay = 500;
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
let results = [];
for (let i = 0; i < productsData.length; i += batchSize) {
const batch = productsData.slice(i, i + batchSize);
const batchResults = await Promise.all(
batch.map(async (product) => {
//Media
const mediaInput = product.images.map((image) => ({
originalSource: image.src,
alt: image.altText || "",
mediaContentType: "IMAGE",
}));
// Create the product
const productResponse = await shopifyAPI.post(
"",
JSON.stringify({
query: productCreateMutation,
variables: {
input: {
title: product.title,
bodyHtml: product.bodyHtml,
vendor: product.vendor,
productType: product.productType,
metafields: [
{
namespace: "custom",
key: "sync_from_api",
type: "boolean",
value: "true",
},
],
productOptions: product.productOptions,
},
media: mediaInput,
},
})
);
if (!productResponse.data || productResponse.data.errors) {
console.error("GraphQL Error:", productResponse.data.errors);
return null;
}
if (productResponse.data.data.productCreate.userErrors.length > 0) {
console.error(
"User Errors:",
productResponse.data.data.productCreate.userErrors
);
return null;
}
// Product ID to use for creating variants
const productId = productResponse.data.data.productCreate.product.id;
return {
productId: productId,
};
})
);
results = results.concat(batchResults);
await sleep(delay);
}
return results.filter((result) => result !== null);
};
Next step as far as I understand, is to use the productIDs and then activate the tracking and set the stock. How would one do that with a mutation?
Hey Community 👋 Did you know that March 15th is National Everything You Think Is W...
By JasonH Apr 1, 2025Discover how to increase the efficiency of commerce operations with Shopify Academy's l...
By Jacqui Mar 26, 2025Shopify and our financial partners regularly review and update verification requiremen...
By Jacqui Mar 14, 2025