Good day,
Seems I’m having the issue of when I create products via the Admin API with GraphQL that once we get to the creating the variants part - it works but I always have a default title with 0 price which then causes the product to show it has 0 price on the site and also that being an option.
This is how the product data looks like I want to add to the shop:
KMQ: [
{
"title": "Founder Backpack",
"bodyHtml": "The Founder Backpack is manufactured using 210 Denier and Polyester material. The bag is very lightweight, making it the perfect companion for a quick outdoor trip. It has a front pocket as well as a main zippered compartment with a small, internal zippered pocket. The bag has a stretchy mesh pocket on each side, as well as adjustable shoulder straps.",
"vendor": "KMQ",
"productType": "Backpacks",
"images": [
{
"src": "https://www.kmq.co.za/content/webimages/LowRes/CxwhC9o4sVD_BAG2269-R.jpg",
"altText": "Founder Backpack image"
},
{
"src": "https://www.kmq.co.za/content/webimages/LowRes/DGcWeR3qtD0_BAG2269-RBU.jpg",
"altText": "Founder Backpack image"
}
],
"options": [
{
"name": "Color",
"values": [
"Red",
"Royal Blue"
]
}
],
"variants": [
{
"price": "116.12",
"sku": "BAG2269/R",
"inventoryQuantity": 1378,
"options": [
"Red"
]
},
{
"price": "116.12",
"sku": "BAG2269/RBU",
"inventoryQuantity": 896,
"options": [
"Royal Blue"
]
}
]
}
]
I have these functions setup to create, the product, then create the variants, adjust the inventory and finally publishing it:
Creating:
const createProduct = async (product) => {
const productCreateMutation = `
mutation CreateProductWithOptions($input: ProductInput!, $media: [CreateMediaInput!]) {
productCreate(input: $input, media: $media) {
product {
id
media(first: 10) {
nodes {
alt
mediaContentType
preview {
status
}
}
}
options {
id
name
position
values
optionValues {
id
name
hasVariants
}
}
variants(first: 20) {
nodes {
id
title
selectedOptions {
name
value
}
}
}
}
userErrors {
field
message
}
}
}
`;
const encodeURL = (url) => {
return encodeURI(url);
};
const mediaInput = product.images.map((image) => ({
originalSource: encodeURL(image.src),
alt: image.altText || "",
mediaContentType: "IMAGE",
}));
const productOptions = product.options.map((option) => ({
name: option.name,
values: option.values.map((value) => ({ name: value })),
}));
try {
const productResponse = await shopifyAPI.post(
"",
JSON.stringify({
query: productCreateMutation,
variables: {
input: {
title: product.title,
bodyHtml: product.bodyHtml,
vendor: product.vendor,
productType: product.productType,
// productOptions: productOptions,
metafields: [
{
namespace: "custom",
key: "sync_from_api",
type: "boolean",
value: "true",
},
],
},
media: mediaInput,
},
})
);
if (
productResponse.data.errors ||
productResponse.data.data.productCreate.userErrors.length > 0
) {
console.error(
"Error creating product:",
productResponse.data.errors ||
productResponse.data.data.productCreate.userErrors
);
return null;
}
return productResponse.data.data.productCreate.product.id;
} catch (error) {
console.error("Network or Server Error:", error);
return null;
}
};
Variants:
const createVariants = async (productId, variants) => {
const variantCreateMutation = `
mutation CreateVariant($input: ProductVariantInput!) {
productVariantCreate(input: $input) {
productVariant {
id
inventoryItem {
id
}
}
userErrors {
field
message
}
}
}
`;
const createdVariants = [];
for (const variant of variants) {
try {
const variantResponse = await shopifyAPI.post(
"",
JSON.stringify({
query: variantCreateMutation,
variables: {
input: {
productId,
price: variant.price,
sku: variant.sku,
options: variant.options,
},
},
})
);
if (
variantResponse.data.errors ||
variantResponse.data.data.productVariantCreate.userErrors.length > 0
) {
console.error(
"Error creating variant:",
variantResponse.data.errors ||
variantResponse.data.data.productVariantCreate.userErrors
);
} else {
console.log(`Variant created: ${variant.sku}`);
const inventoryItemId =
variantResponse.data.data.productVariantCreate.productVariant.inventoryItem.id
.split("/")
.pop();
createdVariants.push({
inventoryItemId,
inventoryQuantity: variant.inventoryQuantity,
});
}
} catch (error) {
console.error("Network or Server Error:", error);
}
}
return createdVariants;
};
Inventory:
const adjustInventory = async (inventoryItemId, inventoryQuantity) => {
const restAPI = axios.create({
baseURL: `https://${process.env.SHOPIFY_SHOP}/admin/api/2024-04`,
headers: {
"Content-Type": "application/json",
"X-Shopify-Access-Token": process.env.SHOPIFY_ACCESS_TOKEN,
},
});
const locationId = process.env.SHOPIFY_LOCATION_ID;
try {
await restAPI.post(`/inventory_levels/adjust.json`, {
location_id: locationId,
inventory_item_id: inventoryItemId, // Ensure inventoryItemId is correct
available_adjustment: inventoryQuantity,
});
console.log(`Inventory adjusted for item: ${inventoryItemId}`);
} catch (error) {
console.error("Error adjusting inventory:", error.response.data);
}
};
Finally Publising:
const publishProduct = async (
productId,
publicationId = "gid://shopify/Publication/126377492736"
) => {
const publishMutation = `
mutation PublishProduct($id: ID!, $input: [PublicationInput!]!) {
publishablePublish(id: $id, input: $input) {
publishable {
availablePublicationsCount {
count
}
resourcePublicationsCount {
count
}
}
shop {
publicationCount
}
userErrors {
field
message
}
}
}
`;
try {
const response = await shopifyAPI.post(
"",
JSON.stringify({
query: publishMutation,
variables: {
id: productId,
input: [
{
publicationId: publicationId,
},
],
},
})
);
if (
response.data.errors ||
response.data.data.publishablePublish.userErrors.length > 0
) {
console.error(
"Error publishing product:",
response.data.errors || response.data.data.publishablePublish.userErrors
);
return false;
}
console.log(`Product published successfully: ${productId}`);
return true;
} catch (error) {
console.error("Error publishing product:", error);
return false;
}
};
You’ll see in the createProduct I have productOptions commented out - if I use that it works correctly but I dont get all the options and variants. So not sure where my issue/mistake is
Does anyone have some insight into this? Help would be appreciated as I’m still new to this way of adding products and using Shopify.
