ProductUpdate mutation and price change

Topic summary

Migrating product updates to Admin API 2024-07 caused errors because ProductInput no longer accepts variants. Attempting productUpdate with a variants array returned ā€œField is not defined on ProductInput.ā€

Current approach (works):

  • Use productUpdate for product-level fields and media (images via media parameter). Variants are excluded here.
  • Use productVariantsBulkUpdate to change variant-level data. Place SKU under inventoryItem.sku (not at the variant root) and update other variant attributes (e.g., measurements/weight). The mutation can return productVariants { id inventoryItem { id } } to obtain inventoryItemId.
  • Use inventoryAdjustQuantities to adjust stock by inventoryItemId and location.

Bulk/validation notes:

  • The earlier SKU error (ā€œField is not defined on ProductVariantsBulkInputā€) was due to putting sku at the root; move it to variants.inventoryItem.sku.
  • You cannot update a product and its variants in a single API call; at least two calls are required (productUpdate + productVariantsBulkUpdate), plus inventoryAdjustQuantities for stock.

Outcome: The original implementation now works; the OP closed the topic while finishing development.

New, open question: Another user asked how to add an ā€œInsurance Feeā€ product priced at 10% of order total on a Basic plan (without Shopify Functions). No solution yet; helper will try.

Summarized with AI on December 18. AI used: gpt-5.

Hi to all,
Currently, I have a project in which we do product updates using mutation and productUpdate. These ProductUpdate contain Variants.

I would like to move to a more recent version of the API and I see that variants are no longer supported and that productOptions must be used.

Does anyone have an example of such a use to for example update the price of a product or update its SKU?

We work in C#.

Thanks in advance.

Kind regards.

Hi @DamienD

Both price and SKU can be modified using productVariantCreate

mutation productVariantCreate($input: ProductVariantInput!) {
  productVariantCreate(input: $input) {
    product {
      id
      title
    }
    productVariant {
      createdAt
      displayName
      id
      inventoryItem {
        unitCost {
          amount
        }
        tracked
      }
      inventoryPolicy
      inventoryQuantity
      price
      product {
        id
      }
      title
    }
    userErrors {
      field
      message
    }
  }
}

variables

{
  "input": {
    "inventoryItem": {
      "cost": 50,
      "tracked": true
      "sku":"asdfafaf"
    },
    "inventoryPolicy": "DENY",
    "inventoryQuantities": {
      "availableQuantity": 25,
      "locationId": "gid://shopify/Location/346779380"
    },
    "price": 114.99,
    "productId": "gid://shopify/Product/108828309",
    "requiresShipping": true,
    "options": "Holographic"
  }
}

Hi @Kyle_liu ,

For the moment we have this structure to send the products to update to Shopify (we have +/- 200 000 products on our website)

{
	"input": {
		"id": "gid://shopify/Product/1484647465002",
		"title": "SANIFLOR HOUTSNIPPERS ROOD 60L",
		"descriptionHtml": "Deze rode, afkomstig uit Zuid-Europese pijnboombossen, is van een uitstekende kwaliteit en creƫert een verzorgde look rondom uw planten. U hoeft geen onkruid meer te wieden of giftige onkruidverdelgers te gebruiken. Dankzij hun progressief degradatieproces geven ze ook nog eens belangrijke voedingselementen mee aan uw planten. Nog voordelen? Natuurlijk! Minder sproeibeurten doordat ze de grond langer vochtig houden. De wortels van uw planten worden beter beschermd tegen de vrieskou en warmte. Gaan bodemverdichting tegen. Alleen maar voordelen voor uw tuin!",
		"tags": "btw6, premium, Tuinaanleg, Tuinverzorging en beplanting_Bodembedekking",
		"published": true,
		"vendor": "F/603/",
		"productType": "Tuinaanleg",
		"variants": {
			"id": "gid://shopify/ProductVariant/12972178374698",
			"sku": "ISR00014",
			"price": "9.95",
			"barcode": "",
			"requiresShipping": true,
			"weight": 10,
			"inventoryQuantities": {
				"locationId": "gid://shopify/Location/8311963690",
				"availableQuantity": 253
			},
			"inventoryManagement": "SHOPIFY"
		},
		"images": {
			"src": "http://vanderschuerenadmin.be/assets/images/products/ISR00014.jpg"
		}
	}
}

But it uses the oldest version of the API.

We would like to pass to the latest version of the API.

Could you help me to translate this old version to the latest way to do it (e.g. with the 2024-07 version) ?

Will I have to recreate all of my product or can I update them with the new syntax.

Thank’s a lot.

Kind regards.

Damien.

Hi @DamienD

You need to use two APIs to complete the operation

  1. Use productUpdate API to modify basic product information and images
  2. Using inventoryAdjusteQuantities API to process inventory data

productUpdate api , Modify image information with media parameter

{
  "input": {
    "id": "gid://shopify/Product/8454003589395",
    "title": "SANIFLOR HOUTSNIPPERS ROOD 60L",
    "descriptionHtml": "Deze rode, afkomstig uit Zuid-Europese pijnboombossen, is van een uitstekende kwaliteit en creƫert een verzorgde look rondom uw planten. U hoeft geen onkruid meer te wieden of giftige onkruidverdelgers te gebruiken. Dankzij hun progressief degradatieproces geven ze ook nog eens belangrijke voedingselementen mee aan uw planten. Nog voordelen? Natuurlijk! Minder sproeibeurten doordat ze de grond langer vochtig houden. De wortels van uw planten worden beter beschermd tegen de vrieskou en warmte. Gaan bodemverdichting tegen. Alleen maar voordelen voor uw tuin!",
    "tags": "btw6, premium, Tuinaanleg, Tuinverzorging en beplanting_Bodembedekking",
    "published": true,
    "vendor": "F/603/",
    "productType": "Tuinaanleg",
    "variants": [
      {
        "id": "gid://shopify/ProductVariant/45606790496531",
        "sku": "ISR00014",
        "price": "9.95",
        "barcode": "",
        "requiresShipping": true,
        "weight": 10,
        "inventoryManagement": "SHOPIFY"
      }
    ]
  },
  "media": [
    {
      "originalSource": "http://vanderschuerenadmin.be/assets/images/products/ISR00014.jpg",
      "mediaContentType": "IMAGE"
    }
  ],
  "mediaCount": 5
}

inventoryAdjustQuantities:

{
    "input": {
        "name":"available",
        "reason":"correction",
        "changes": [
            {
                "inventoryItemId": "gid://shopify/InventoryItem/47636619034899",
                "delta": 10,
                "locationId": "gid://shopify/Location/85112553747"
            }
        ]
    }
}

I hope it’s helpful to you.

Hi @Kyle_liu

Thank you for your help.

Unfortunatelly we continue to struggle with the update of the products.

We are using mutation operation.

  1. We make the input like this :
{
	"input": {
		"id": "gid://shopify/Product/1484647465002",
		"title": "SANIFLOR HOUTSNIPPERS ROOD 60L",
		"descriptionHtml": "Deze rode, afkomstig uit Zuid-Europese pijnboombossen, is van een uitstekende kwaliteit en creƫert een verzorgde look rondom uw planten. U hoeft geen onkruid meer te wieden of giftige onkruidverdelgers te gebruiken. Dankzij hun progressief degradatieproces geven ze ook nog eens belangrijke voedingselementen mee aan uw planten. Nog voordelen? Natuurlijk! Minder sproeibeurten doordat ze de grond langer vochtig houden. De wortels van uw planten worden beter beschermd tegen de vrieskou en warmte. Gaan bodemverdichting tegen. Alleen maar voordelen voor uw tuin!",
		"tags": "btw6, premium, Tuinaanleg, Tuinverzorging en beplanting_Bodembedekking",
		"published": true,
		"vendor": "F/603/",
		"productType": "Tuinaanleg",
		"variants": [
			{
				"id": "gid://shopify/ProductVariant/12972178374698",
				"sku": "ISR00014",
				"price": "9.95",
				"barcode": "",
				"requiresShipping": true,
				"weight": 10,
				"inventoryManagement": "SHOPIFY"
			}
		]
	}
}
  1. We create a stage to upload our json file. The Url used to create de stage is https://SHOPNAME.myshopify.com/admin/api/2024-07/graphql.json
mutation { stagedUploadsCreate(input:{ resource: BULK_MUTATION_VARIABLES, filename:"XXX02093214211130364.jsonl", mimeType:"text/jsonl", httpMethod: POST }){ userErrors{ field, message },  stagedTargets{ url, resourceUrl, parameters { name, value } } } }
  1. We receive the authentication token that we use to execute the stage :
mutation { bulkOperationRunMutation( mutation:"mutation call($input: ProductInput!) { productUpdate(input: $input) { product {id variants(first: 3) {edges {node {id title inventoryQuantity }}}} userErrors { message field }}}", stagedUploadPath:"tmp/26475552/bulk/3c8d9545-fb5e-4a8d-9ad6-ae5edda9bbf3/XXX02093214211130364.jsonl") { bulkOperation { id url status } userErrors { message field } } }
  1. After this, we receive an error like this :
{
  "data": {
    "bulkOperationRunMutation": {
      "bulkOperation": null,
      "userErrors": [
        {
          "message": "Invalid Bulk Mutation Field - Variable $input of type ProductInput! was provided invalid value for variants (Field is not defined on ProductInput)",
          "field": null
        }
      ]
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 10,
      "actualQueryCost": 10,
      "throttleStatus": {
        "maximumAvailable": 2000.0,
        "currentlyAvailable": 1990,
        "restoreRate": 100.0
      }
    }
  }
}

We don’t understand the problem ?

At which step should we use your previous reply ?

Thank you.

Kind regards.

Damien.

Hi @DamienD

Sorry, there is an error in the version I am using. To modify variants, this API is required. The code is as follows:

1态

{
  "input": {
    "id": "gid://shopify/Product/8454003589395",
    "title": "SANIFLOR HOUTSNIPPERS ROOD 60L",
    "descriptionHtml": "Deze rode, afkomstig uit Zuid-Europese pijnboombossen, is van een uitstekende kwaliteit en creƫert een verzorgde look rondom uw planten. U hoeft geen onkruid meer te wieden of giftige onkruidverdelgers te gebruiken. Dankzij hun progressief degradatieproces geven ze ook nog eens belangrijke voedingselementen mee aan uw planten. Nog voordelen? Natuurlijk! Minder sproeibeurten doordat ze de grond langer vochtig houden. De wortels van uw planten worden beter beschermd tegen de vrieskou en warmte. Gaan bodemverdichting tegen. Alleen maar voordelen voor uw tuin!",
    "tags": "btw6, premium, Tuinaanleg, Tuinverzorging en beplanting_Bodembedekking",
    "published": true,
    "vendor": "F/603/",
    "productType": "Tuinaanleg"
  },
  "media": [
    {
      "originalSource": "http://vanderschuerenadmin.be/assets/images/products/ISR00014.jpg",
      "mediaContentType": "IMAGE"
    }
  ],
  "mediaCount": 5
}

2态productVariantsBulkUpdate

mutation productVariantsBulkUpdate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
  productVariantsBulkUpdate(productId: $productId, variants: $variants) {
    product {
      id
    }
    productVariants {
      id
    }
    userErrors {
      field
      message
    }
  }
}

VARIABLES:

{
  "productId": "gid://shopify/Product/20995642",
  "variants": [
    {
      "id": "gid://shopify/ProductVariant/1070325078",
      "inventoryItem":{
        "measurement":{
            "weight":{
                "unit":"KILOGRAMS",
                "value":10
            }
        }
      },
      "sku":"ISR00014"
    }
  ]
}

3态

mutation inventoryAdjustQuantities($input: InventoryAdjustQuantitiesInput!) {
  inventoryAdjustQuantities(input: $input) {
    userErrors {
      field
      message
    }
    inventoryAdjustmentGroup {
      createdAt
      reason
      referenceDocumentUri
      changes {
        name
        delta
      }
    }
  }
}

VARIABLES:
{
    "input": {
        "name":"available",
        "reason":"correction",
        "changes": [
            {
                "inventoryItemId": "gid://shopify/InventoryItem/47636619034899",
                "delta": 10,
                "locationId": "gid://shopify/Location/85112553747"
            }
        ]
    }
}

Hi @Kyle_liu ,

Thank you for the explanations.

For the productVariantsBulkUpdate , we have a problem with the sku. This field is not recognized in the variable (red squigly line). We have this error :

{
  "errors": [
    {
      "message": "Variable $variants of type [ProductVariantsBulkInput!]! was provided invalid value for 0.sku (Field is not defined on ProductVariantsBulkInput)",
      "locations": [
        {
          "line": 1,
          "column": 53
        }
      ],
      "extensions": {
        "value": [
          {
            "id": "gid://shopify/ProductVariant/12972178374698",
            "inventoryItem": {
              "measurement": {
                "weight": {
                  "unit": "KILOGRAMS",
                  "value": 10
                }
              }
            },
            "sku": "ISR00014"
          }
        ],
        "problems": [
          {
            "path": [
              0,
              "sku"
            ],
            "explanation": "Field is not defined on ProductVariantsBulkInput"
          }
        ]
      }
    }
  ]
}

for the third point, does a graphql query exist to get the inventoryItemId ? If yes, could you provide us the query with the variable ?

Thank you for your help.

Kind regards.

Damien.

Hi @DamienD

Adjusted the code structure in the second step by adding a new structure:

productVariants {
id
inventoryItem{
id
}
}

This inventoryItem, which can provide support for Part III

mutation productVariantsBulkUpdate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
  productVariantsBulkUpdate(productId: $productId, variants: $variants) {
    product {
      id
    }
    productVariants {
      id
      inventoryItem{
        id
      }
    }
    userErrors {
      field
      message
    }
  }
}

VARIABLES:

{
  "productId": "gid://shopify/Product/9136350265619",
  "variants": [
    {
      "id": "gid://shopify/ProductVariant/48277903474963",
      "inventoryItem":{
        "measurement":{
            "weight":{
                "unit":"KILOGRAMS",
                "value":10
            }
        },
        "sku":"ISR00014"
      }
    }
  ]
}

Hi @Kyle_liu ,

Thank you for you answer, it works.

But, I have one more question.

If I understand well, we can not update a product directly with its variants ? We must pass by two API calls, one to change the product and one to change the variant.

Is there a way to make one API call to update the product AND the variant ?

Thank you !

Kind regards.

Damien.

Sorry, right now it’s only possible through two Api’s, I’m sure shopify might improve it later.
If I solved your problem, could you mark my answer as a solution and like it?

Thank you.

1 Like

Hi @Kyle_liu

Thnak you for your answer.

We didn’t finish our development but it’s on the right path.

I close the subject.

Thnak you.

Kind regards.

Hi, Kyle
I have a product, and when I use Purchase Product, it automatically adds another product called ā€œInsurance Fee.ā€ The initial price is, but my logic is that the fee is calculated 10% of the total price and changes the ā€œInsurance Feeā€ product price. This is possible in Shopify functions, but I do not have the Plus plan, and I would like to execute the same condition in the Basic plan. Can you help me?

Hi @Ahsan-ah-med

I’ll try.