How to Update Products using GQL
19 minute read
Please Read
The method of managing adverts described in this article (Optional Option Types and Free Text Variants) should be enabled by all operators running instances of Marketplacer created from the 7th of August 2023 onwards.Existing operators with instances set up pre 7th Aug 2023 can also opt in to this functionality, but should plan for this change as it could impact existing integrations given the added flexibility that it introduces.
The legacy method (pre 7th Aug 2023) for managing adverts is described in this article.
What you’ll learn
- What an Advert is and its primary components
- How to use the advertUpsert mutation to create adverts
- How to use the advertUpsert mutation to update adverts
Advert Creation
It should be noted that Operators can only update adverts, this guide describes advert creation for the most part which is an operation only available to Sellers.What is an Advert?
An Advert is essentially analogous to a Product (so it’s maybe easier to think about it that way!). An Advert has the following characteristics:
- Adverts are created, and placed for sale on the Marketplace by a Seller
- An Advert has a large number of attributes (full list here) we’ll cover the key attributes in this article
- Adverts must have at least 1 Variant, as it’s at the variant level that concepts such as Inventory, SKUs and Barcodes reside.
- Indeed when orders are placed, it is the
variantId
that is used to identify the purchased item.
- Indeed when orders are placed, it is the
- Adverts can be created via a number of different methods, in this article we will focus on how you can create Adverts using the GraphQL
advertUpsert
mutation - Adverts can be either:
- “Online” - essentially available for purchase or
- “Offline” - cannot be purchased. This may be because the Seller doesn’t wish to sell that product any longer, or there may be a problem with the way the advert has been created, making it invalid - e.g. it has not been assigned to a category (or Taxon as we call them at Marketplacer).
- The Advert (and the way it can be created) is tightly coupled to the categorization that it’s placed into. We call this categorization hierarchy the “Taxonomy” in Marketplacer, so we’ll be referring to the Taxon that the Advert “belongs to” in this article.
Did you know?
The Advert object does not have a single status representing whether it is online or offline, but rather a series of attributes that when taken in combination will determine whether its online or offline. You can read more about advert state hereAdvert Schema
An advert has multiple attributes (or fields in GraphQL speak). Some of these attributes are simplistic, single-value attributes, for example:
- Title
- Description
- Lowest Price
- And so on…
Some of these attributes are more complex and may be:
- A collection of single values, e.g. a collection of strings
- A collection of key value pairs
- A reference to another full object (e.g. An Advert belongs to one Seller.)
- A collection of objects (e.g. an Advert must have 1 or more Variant objects)
A simplified “schema” of an Advert and it’s primary relationships is shown below, note that:
- We are not showing the single-value fields here
- We are only showing the principal object relationships relevant to advert creation
The table below aims to explain what each of these objects are and whether they are mandatory for the Advert to be considered valid and placed online for sale.
Field Name | Object Type | Description | Mandatory |
---|---|---|---|
brand | Brand | The Brand relates to the producer or manufacturer of the product. Brand is a separate object as we maintain a list of Brands in Marketplacer. An Advert must be associated with 1 Brand in order to be considered valid. | Yes (1 only) |
images | Image | An Advert must have at least 1 image associated with it in order to be considered valid, but can have more. | Yes (1 minimum) |
externalIds | ExternalId | All adverts have their own Marketplacer generated Id, however you may wish to associate your own Ids (“ExternalIds”) with this Advert too. You can add as many external Ids as you like but they are not mandatory. | No |
advertOptionValues | OptionValue | The Taxon that you associate an Advert with will determine whether this is mandatory for the Advert to be considered valid or not. An Advert Option Value can be: a single select value, multiple select value or a free text value. | Yes - dependant on Taxon |
productFeatures | String | Product features are just a collection of free text fields available for all Adverts. They are not dependent on the Taxon type, and they are optional. | No |
seller | Seller | The Seller “owns” the Advert and is responsible for creating and updating it. An Advert can have only 1 Seller. Adverts cannot be shared between Sellers. | Yes (1 only) |
taxonNullable | Taxon | This is the Taxon or “Category” that the Advert has been assigned to. This assignment drives many of the other characteristics of the Advert, e.g. featureOptionValues and productDetails etc. | Yes (1 only) |
variants | Variant | Adverts need to have at least 1 Variant. Variants define possible variations of the Advert. Indeed inventory position, bar codes, SKUs etc all sit at the Variant level, and it is ultimately individual variants that are purchased by the customer. | Yes (1 minimum) |
variantOptionValues (Variant) | OptionValue | Variant OptionValues define the individual variant(s). Again the Variant Option Values that must be used are linked to the Taxonomy that the Advert belongs to. An Variant Option Value can be: a single select value, multiple select value or free text value. | Yes (1 minimum) |
The Advert is possibly the most complex object to work with in the Marketplacer GraphQL API, especially in reference to the following concepts:
- advertOptionValues (
Advert
) - productFeatures (
Advert
) - variantOptionValues (
Variant
)
With this in mind we are going to walk through some separate examples of creating an advert, starting with simple, through to more complex scenarios.
Taxonomy
Before we continue with some examples of creating an Advert with GraphQL, it’s worth just clarifying the important role of the Taxonomy.
When creating an Advert, you need to assign it to a Taxon, the Taxon represents where the Advert sits in categorization Hierarchy. In the examples we are going to work with, we will work with the following simple Taxonomy structure:
This is a rather unrealistic, 2 level categorization hierarchy (or Taxonomy), but for the purposes of our examples it will suffice. Most usually you will have more than 2 levels in your Taxonomy.
When creating an Advert in the examples that follow we will assign it to either:
- Cellular Internet
- Cellular Tablets
- Cellular Phones
We have configured each of those 3 Taxons to require an increasing number of the taxon-driven concepts mentioned above(advertOptionTypes
and variantOptionTypes
), so in effect we have assigned a “complexity” to each of the Taxons, as shown below:
Taxon | appliedTo | fieldType | optionType |
---|---|---|---|
Cellular Internet Simple Example | advert variant | single_select single_select | Cellular Material Cellular Memory |
Cellular Tablets Medium Example | advert advert variant variant | single_select multi_select single_select multi_select | Cellular Material Cellular Network Cellular Memory Cellular Ports |
Cellular Phones Complex Example | advert advert advert variant variant variant | single_select multi_select free_text (o) single_select multi_select free_text | Cellular Material Cellular Network Cellular Processor Cellular Memory Cellular Ports Cellular Color |
Did you know?
productFeatures are not driven by the Taxon that the Advert is assigned to. They are just a standard attribute available on every Advert, irrespective of Taxon. Think of them in a similar way to the adverts Title or Description. Therefore we have not includedproductFeatures
in the above table, and generally speaking we’ll not work much further with them in this article.How do we define the Taxon’s Option Types?
The final part of discussing the Taxonomy is to understand how we configure the Option Types each Taxon requires. For example, from the table above we have said that products in the Cellular Phones category (Taxon), require the following:
optionType | appliedTo | fieldType | optionValues |
---|---|---|---|
Cellular Material | advert | SINGLE_SELECT | |
Cellular Network | advert | MULTI_SELECT | |
Cellular Processor (0) | advert | FREE_TEXT | N/a |
Cellular Memory | variant | SINGLE_SELECT | |
Cellular Ports | variant | MULTI_SELECT | |
Cellular Color | variant | FREE_TEXT | N/a |
In order to assign those optionTypes
to a Taxon, we use something called a Prototype. Therefore each of the 3 Taxons have been assigned a different Prototype that defines the required optionTypes
, as shown below:
We use Prototypes (as opposed to directly assigning Option Types to the Taxon) so that Prototypes can be re-used on many different Taxons.
Expanding the example further to show how Prototypes are configure is shown below:
IMPORTANT:
Before you begin with the following examples, you should note that only Sellers can create Adverts. With this in mind you’ll need to make sure you create a Seller API Key as described here. Operators can only update existing Adverts.Example 1 - Simple
In this example we are going to create an Advert in the Cellular Internet category/taxon, which is assigned the Cellular - Simplex prototype. So in this case we need to supply the following to the advertUpsert
mutation:
Advert Values (AdvertInput
)
Value Supplied | Sourced From |
---|---|
brandId | You will need to provide the brandId for the Advert, you can obtain a list of the brandIds from the brands query. |
Images | You can supply images a URLs or Base64 encoded. In this example we’ll just provide a URL. |
productFeatures | You can supply any collection of free-text strings. productFeatures are optional, but we’ll supply some here to illustrate their purpose. |
Seller | As mentioned above each Advert is owned by a Seller. As only Sellers can create Adverts using the advertUpsert mutation, the Seller is derived from your API key permissions, and does not need to be explicitly passed as an input, e.g. a “Seller Id” etc. |
taxonId | You will need to provide the taxonId for the Advert, you can obtain a list of the taxonIds from the taxon query |
advertOptionValues | The Cellular - Simplex prototype defines a mandatory Cellular Material optionType (of type SINGLE_SELECT ) for the advert . We will need to pass a suitable optionValue here, which we will obtain via the prototypes query to get this information. |
title | title is a mandatory field for an Advert, this is provided a free text |
description | Description is a mandatory field for an Advert, this is provided as free text |
Variant Values (VariantInput
)
Value Supplied | Sourced From |
---|---|
variantOptionValues | The Cellular - Simplex prototype defines a mandatory Cellular Memory optionType (of type SINGLE_SELECT ) for each Variant . We will need to pass a suitable optionValue here, which we will obtain via the prototypes query to get this information. |
countOnHand | The stock holding (often referred to a inventory) is held at the variant level, this is a mandatory field, unless infiniteQuantity is set to true |
Note we are using the minimum set of values to allow us to create an Advert. For more detail on the entire range of attributes that you can supply, please refer to the Reference Documentation.
Brand Query
As stated above the brandId
is a mandatory attribute required to create an advert. A simple example of this query, along with a sample response is provided below:
Query
query {
brands {
nodes {
id
name
}
}
}
Response
{
"data": {
"brands": {
"nodes": [
{
"id": "QnJhbmQtNA==",
"name": "Advocate 1",
},
{
"id": "QnJhbmQtMjQz",
"name": "Avid",
},
{
"id": "QnJhbmQtMjQ1",
"name": "Bucket Placer",
},
{
"id": "QnJhbmQtMjQ2",
"name": "Elite",
}
]
}
}
}
Select the id
of the brand that you want to use and put it aside for now.
Taxon Query
We can use the taxon query to get:
- The
taxonId
required - The
prototypeId
so that we can determine which elements are required of this Taxon by using theprototype
query
An example query and response are given below:
TAXON DEPTH
We are using a simple taxonomy in this example with a depth of 2, which the example query reflects. If you have a deeper depth taxonomy, you will need to include additionalchildren
clauses in your query to ensure you pull all levels of the taxonomy.Query
query {
taxons {
nodes {
id
displayName
treeName
prototype {
name
id
}
children {
edges {
node {
id
displayName
treeName
prototype {
name
id
} #<- INSERT MORE CHILDREN CLAUSES HERE IF NEEDED
}
}
}
}
}
}
Response (we have abbreviated the response to show only relevant detail )
{
"edges": [
{
"node": {
"id": "VGF4b24tMjc4",
"displayName": "Cellular Internet",
"treeName": "Cellular Technology - Cellular Internet",
"prototype": {
"name": "Cellular - Simplex",
"id": "UHJvdG90eXBlLTEzMw=="
},
"children": {
"edges": []
}
}
},
{
"node": {
"id": "VGF4b24tMjgw",
"displayName": "Cellular Phones",
"treeName": "Cellular Technology - Cellular Phones",
"prototype": {
"name": "Cellular - Complex",
"id": "UHJvdG90eXBlLTEzNQ=="
},
"children": {
"edges": []
}
}
},
{
"node": {
"id": "VGF4b24tMjc5",
"displayName": "Cellular Tablets",
"treeName": "Cellular Technology - Cellular Tablets",
"prototype": {
"name": "Cellular - Medium",
"id": "UHJvdG90eXBlLTEzNA=="
},
"children": {
"edges": []
}
}
}
]
}
You can see from the example payload that we get both Taxon and Prototype ids that we can use in the subsequent queries. So we’ll use the following values:
- Taxon Id for Cellular Internet:
VGF4b24tMjc4
- Prototype Id for Cellular - Simplex:
UHJvdG90eXBlLTEzMw==
We’ll use the Prototype Id in the next query.
Prototype Query
Query
query {
nodes(ids: "UHJvdG90eXBlLTEzMw==") {
... on Prototype {
id
name
optionTypes {
nodes {
id
name
fieldType
appliedTo
optional
optionValues {
nodes {
id
name
displayName
}
}
}
}
}
}
}
Response
{
"data": {
"nodes": [
{
"id": "UHJvdG90eXBlLTEzMw==",
"name": "Cellular - Simplex",
"optionTypes": {
"nodes": [
{
"id": "T3B0aW9uVHlwZS0yNDY=",
"name": "Cellular Material",
"fieldType": "SINGLE_SELECT",
"appliedTo": "ADVERT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNzM0",
"name": "Plastic",
"displayName": "Plastic"
},
{
"id": "T3B0aW9uVmFsdWUtNzM1",
"name": "Aluminium",
"displayName": "Aluminium"
},
{
"id": "T3B0aW9uVmFsdWUtNzM2",
"name": "Carbon Fiber",
"displayName": "Carbon Fiber"
}
]
}
},
{
"id": "T3B0aW9uVHlwZS0yNDc=",
"name": "Cellular Memory",
"fieldType": "SINGLE_SELECT",
"appliedTo": "VARIANT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNzMw",
"name": "64Gb",
"displayName": "64Gb"
},
{
"id": "T3B0aW9uVmFsdWUtNzMx",
"name": "128Gb",
"displayName": "128Gb"
},
{
"id": "T3B0aW9uVmFsdWUtNzMy",
"name": "256Gb",
"displayName": "256Gb"
},
{
"id": "T3B0aW9uVmFsdWUtNzMz",
"name": "512Gb",
"displayName": "512Gb"
}
]
}
}
]
}
}
]
}
}
You can see that we have 2 optionTypes
with the following attributes:
optionType | fieldType | appliedTo | optionValues | Optional |
---|---|---|---|---|
Cellular Material | SINGLE_SELECT | ADVERT | false | |
Cellular Memory | SINGLE_SELECT | VARIANT | false |
We need to supply an Id for each optionType
, so in this case we’ll select:
- Cellular Material
T3B0aW9uVmFsdWUtNzM2
(Carbon Fiber)
- Cellular Memory
T3B0aW9uVmFsdWUtNzMy
(256Gb)
advertUpsert - Simple
We can now plug in the values we’ve retrieved using the previous queries into the advertUpsert
mutation as follows:
Mutation
mutation {
advertUpsert(
input: {
attributes: {
brandId: "QnJhbmQtNA=="
taxonId: "VGF4b24tMjc4"
title: "SolocalMe 4G Wireless Hot Spot"
description: "WiFi Hotspot powered by 4G"
price: "49.99"
attemptAutoPublish: true
images: [
{
sourceUrl: "https://<LINK TO IMAGE>.jpg"
}
]
productFeatures:
["Fast charge", "Light weight", "4G compatible"]
advertOptionValues: [
{ optionValueId: "T3B0aW9uVmFsdWUtNzM2" }
]
variants: [
{
countOnHand: 1000
variantOptionValues: [
{ optionValueId: "T3B0aW9uVmFsdWUtNzMy" }
]
}
]
}
}
) {
status
advert {
id
legacyId
}
errors {
field
messages
}
}
}
Points to note:
- We have included some
productFeatures
, which as you can see are just a collection of strings. We will omitproductFeatures
from the rest of our examples.
Example 2 - Medium
In this example we are going to create an Advert in the Cellular Tablets Taxon, which is assigned the prototype Cellular - Medium. We need to supply the same fields as we did for the previous example, (omitted for brevity), however when we come onto looking at the required optionTypes
for this prototype, we’ll see that we need to supply some new values.
Brand Query
For brevity we won’t show the brand query in full again, please refer to the simple example above for a refresher.
Taxon Query
For brevity we won’t show the full taxon query again, however as we want to create an advert in the Cellular Tablets taxon we’ll use the following values:
- Taxon Id for Cellular Tables:
VGF4b24tMjc5
- Prototype Id for Cellular - Medium:
UHJvdG90eXBlLTEzNA==
Prototype Query
We do want to re-run the prototype
query again as we’ll want to ensure we know what’s required when creating an Advert for this Prototype / Taxon.
Query
query {
nodes(ids: "UHJvdG90eXBlLTEzNA==") {
... on Prototype {
id
name
optionTypes {
nodes {
id
name
fieldType
appliedTo
optional
optionValues {
nodes {
id
name
displayName
}
}
}
}
}
}
}
Querying for this prototype we get the following result:
Response
{
"data": {
"nodes": [
{
"id": "UHJvdG90eXBlLTEzNA==",
"name": "Cellular - Medium",
"optionTypes": {
"nodes": [
{
"id": "T3B0aW9uVHlwZS0yMjQ=",
"name": "Cellular Phone Memory",
"fieldType": "SINGLE_SELECT",
"appliedTo": "VARIANT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNjc5",
"name": "64Gb",
"displayName": "64Gb"
},
{
"id": "T3B0aW9uVmFsdWUtNjgw",
"name": "128Gb",
"displayName": "128Gb"
},
{
"id": "T3B0aW9uVmFsdWUtNjgx",
"name": "256Gb",
"displayName": "256Gb"
}
]
}
},
{
"id": "T3B0aW9uVHlwZS0yNDY=",
"name": "Cellular Material",
"fieldType": "SINGLE_SELECT",
"appliedTo": "ADVERT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNzM0",
"name": "Plastic",
"displayName": "Plastic"
},
{
"id": "T3B0aW9uVmFsdWUtNzM1",
"name": "Aluminium",
"displayName": "Aluminium"
},
{
"id": "T3B0aW9uVmFsdWUtNzM2",
"name": "Carbon Fiber",
"displayName": "Carbon Fiber"
}
]
}
},
{
"id": "T3B0aW9uVHlwZS0yNDg=",
"name": "Cellular Network",
"fieldType": "MULTI_SELECT",
"appliedTo": "ADVERT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNzI2",
"name": "2G",
"displayName": "2G"
},
{
"id": "T3B0aW9uVmFsdWUtNzI3",
"name": "3G",
"displayName": "3G"
},
{
"id": "T3B0aW9uVmFsdWUtNzI4",
"name": "4G",
"displayName": "4G"
},
{
"id": "T3B0aW9uVmFsdWUtNzI5",
"name": "5G",
"displayName": "5G"
}
]
}
},
{
"id": "T3B0aW9uVHlwZS0yNDk=",
"name": "Cellular Ports",
"fieldType": "MULTI_SELECT",
"appliedTo": "VARIANT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNzIz",
"name": "USB-C",
"displayName": "USB-C"
},
{
"id": "T3B0aW9uVmFsdWUtNzI0",
"name": "3.5 mm Headphone",
"displayName": "3.5 mm Headphone"
},
{
"id": "T3B0aW9uVmFsdWUtNzI1",
"name": "USB-B",
"displayName": "USB-B"
}
]
}
}
]
}
}
]
}
}
You can see that we are required to supply optionValue
Ids for the 2 SINGLE_SELECT
optionTypes
we had previously, but that we are now also required to supply values for 2 “new” MULTI_SELECT
optionTypes
. A breakdown of this is shown below:
optionType | fieldType | appliedTo | optionValues | Optional |
---|---|---|---|---|
Cellular Material | SINGLE_SELECT | ADVERT | false | |
Cellular Memory | SINGLE_SELECT | VARIANT | false | |
Cellular Network | MULTI_SELECT | ADVERT | false | |
Cellular Ports | MULTI_SELECT | VARIANT | false |
We need to supply Id(s) for each optionType
, so in this case we’ll select:
- Cellular Material
T3B0aW9uVmFsdWUtNzM0
(Plastic)
- Cellular Memory
T3B0aW9uVmFsdWUtNzMx
(128Gb)
- Cellular Networks
T3B0aW9uVmFsdWUtNzI4
(4G)T3B0aW9uVmFsdWUtNzI5
(5G)
- Cellular Ports
T3B0aW9uVmFsdWUtNzIz
(USB-C)T3B0aW9uVmFsdWUtNzI0
(3.5mm)
advertUpsert - Medium
We now have enough information to run the advertUpsert
query again:
Mutation
mutation {
advertUpsert(
input: {
attributes: {
brandId: "QnJhbmQtNA=="
taxonId: "VGF4b24tMjc5"
title: "Venovo 5G Tablet"
description: "Powerful Android Tablet"
price: "349.99"
attemptAutoPublish: true
images: [
{
sourceUrl: "https://<LINK TO IMAGE>.jpg"
}
]
advertOptionValues: [
{ optionValueId: "T3B0aW9uVmFsdWUtNzM0" }
{ optionValueId: "T3B0aW9uVmFsdWUtNzI4" }
{ optionValueId: "T3B0aW9uVmFsdWUtNzI5" }
]
variants: [
{
countOnHand: 1000
variantOptionValues: [
{ optionValueId: "T3B0aW9uVmFsdWUtNzMx" }
{ optionValueId: "T3B0aW9uVmFsdWUtNzIz" }
{ optionValueId: "T3B0aW9uVmFsdWUtNzI0" }
]
}
]
}
}
) {
status
advert {
id
legacyId
}
errors {
field
messages
}
}
}
Example 3 - Complex
In this example we are going to create an Advert in the Cellular Phones Taxon, which is assigned the prototype Cellular - Complex. We need to supply the same fields as we did for the previous example, (omitted for brevity), however when we come onto looking at the required optionTypes
for this prototype, we’ll see that we need to supply some new values.
Brand Query
For brevity we won’t show the brand query in full again, please refer to the simple example above for a refresher.
Taxon Query
For brevity we won’t show the full taxon query again, however as we want to create an advert in the Cellular Phones taxon we’ll use the following values:
- Taxon Id for Cellular Phones:
VGF4b24tMjgw
- Prototype Id for Cellular - Complex:
UHJvdG90eXBlLTEzNQ==
Prototype Query
We do want to re-run the prototype
query again as we’ll want to ensure we know what’s required when creating an Advert for this Prototype / Taxon.
Query
query {
nodes(ids: "UHJvdG90eXBlLTEzNQ==") {
... on Prototype {
id
name
optionTypes {
nodes {
id
name
fieldType
appliedTo
optional
optionValues {
nodes {
id
name
displayName
}
}
}
}
}
}
}
Response
{
"data": {
"nodes": [
{
"id": "UHJvdG90eXBlLTEzNQ==",
"name": "Cellular - Complex",
"optionTypes": {
"nodes": [
{
"id": "T3B0aW9uVHlwZS0yNDY=",
"name": "Cellular Material",
"fieldType": "SINGLE_SELECT",
"appliedTo": "ADVERT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNzM0",
"name": "Plastic",
"displayName": "Plastic"
},
{
"id": "T3B0aW9uVmFsdWUtNzM1",
"name": "Aluminium",
"displayName": "Aluminium"
},
{
"id": "T3B0aW9uVmFsdWUtNzM2",
"name": "Carbon Fiber",
"displayName": "Carbon Fiber"
}
]
}
},
{
"id": "T3B0aW9uVHlwZS0yNDc=",
"name": "Cellular Memory",
"fieldType": "SINGLE_SELECT",
"appliedTo": "VARIANT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNzMw",
"name": "64Gb",
"displayName": "64Gb"
},
{
"id": "T3B0aW9uVmFsdWUtNzMx",
"name": "128Gb",
"displayName": "128Gb"
},
{
"id": "T3B0aW9uVmFsdWUtNzMy",
"name": "256Gb",
"displayName": "256Gb"
},
{
"id": "T3B0aW9uVmFsdWUtNzMz",
"name": "512Gb",
"displayName": "512Gb"
}
]
}
},
{
"id": "T3B0aW9uVHlwZS0yNDg=",
"name": "Cellular Network",
"fieldType": "MULTI_SELECT",
"appliedTo": "ADVERT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNzI2",
"name": "2G",
"displayName": "2G"
},
{
"id": "T3B0aW9uVmFsdWUtNzI3",
"name": "3G",
"displayName": "3G"
},
{
"id": "T3B0aW9uVmFsdWUtNzI4",
"name": "4G",
"displayName": "4G"
},
{
"id": "T3B0aW9uVmFsdWUtNzI5",
"name": "5G",
"displayName": "5G"
}
]
}
},
{
"id": "T3B0aW9uVHlwZS0yNDk=",
"name": "Cellular Ports",
"fieldType": "MULTI_SELECT",
"appliedTo": "VARIANT",
"optional": false,
"optionValues": {
"nodes": [
{
"id": "T3B0aW9uVmFsdWUtNzIz",
"name": "USB-C",
"displayName": "USB-C"
},
{
"id": "T3B0aW9uVmFsdWUtNzI0",
"name": "3.5 mm Headphone",
"displayName": "3.5 mm Headphone"
},
{
"id": "T3B0aW9uVmFsdWUtNzI1",
"name": "USB-B",
"displayName": "USB-B"
}
]
}
},
{
"id": "T3B0aW9uVHlwZS0yNTA=",
"name": "Cellular Processor",
"fieldType": "FREE_TEXT",
"appliedTo": "ADVERT",
"optional": true,
"optionValues": {
"nodes": []
}
},
{
"id": "T3B0aW9uVHlwZS0yNTI=",
"name": "Cellular Color",
"fieldType": "FREE_TEXT",
"appliedTo": "VARIANT",
"optional": false,
"optionValues": {
"nodes": []
}
}
]
}
}
]
}
}
You can see that we are required to supply optionValue
Ids for the optionTypes
(2x SINGLE_SELECT
& 2x MULTI_SELECT
) we have previously worked with, but that we now have 2x FREE_TEXT
optionTypes
- 1 of which is Optional. A breakdown of this is shown below:
optionType | fieldType | appliedTo | optionValues | Optional |
---|---|---|---|---|
Cellular Material | SINGLE_SELECT | ADVERT | false | |
Cellular Memory | SINGLE_SELECT | VARIANT | false | |
Cellular Network | MULTI_SELECT | ADVERT | false | |
Cellular Ports | MULTI_SELECT | VARIANT | false | |
Cellular Processor | FREE_TEXT | ADVERT | N/a | true |
Cellular Color | FREE_TEXT | VARIANT | N/a | false |
We need to supply Id(s) for each optionType
, so in this case we’ll select:
- Cellular Material
T3B0aW9uVmFsdWUtNzM0
(Plastic)
- Cellular Memory
T3B0aW9uVmFsdWUtNzMx
(128Gb)
- Cellular Networks
T3B0aW9uVmFsdWUtNzI4
(4G)T3B0aW9uVmFsdWUtNzI5
(5G)
- Cellular Ports
T3B0aW9uVmFsdWUtNzIz
(USB-C)T3B0aW9uVmFsdWUtNzI0
(3.5mm)
For FREE_TEXT
optionTypes
we cannot supply an optionValueId
, because we don’t have any! In this case we supply the optionTypeId
along with the text value, so in this case we’ll supply values for both:
- Cellular Processor
T3B0aW9uVHlwZS0yNTA=
(Cellular Processor)Snapdragon 8+
(“text value”)
- Cellular Color
T3B0aW9uVHlwZS0yNTI=
(Cellular Color)Screaming Orange
(“text value”)
advertUpsert - Complex
An example of of the advertUpsert
mutation is shown below:
Mutation
mutation {
advertUpsert(
input: {
attributes: {
brandId: "QnJhbmQtNA=="
taxonId: "VGF4b24tMjgw"
title: "Namsung Mobile Phone"
description: "Powerful Phone"
price: "549.99"
attemptAutoPublish: true
images: [
{
sourceUrl: "https://<LINK TO IMAGE>.jpg"
}
]
advertOptionValues: [
{ optionValueId: "T3B0aW9uVmFsdWUtNzM0" }
{ optionValueId: "T3B0aW9uVmFsdWUtNzI4" }
{ optionValueId: "T3B0aW9uVmFsdWUtNzI5" }
{ optionTypeId: "T3B0aW9uVHlwZS0yNTA=", textValue: "Snapdragon 8+"}
]
variants: [
{
countOnHand: 1000
variantOptionValues: [
{ optionValueId: "T3B0aW9uVmFsdWUtNzMx" }
{ optionValueId: "T3B0aW9uVmFsdWUtNzIz" }
{ optionValueId: "T3B0aW9uVmFsdWUtNzI0" }
{ optionTypeId: "T3B0aW9uVHlwZS0yNTI=", textValue: "Screaming Orange"}
]
}
]
}
}
) {
status
advert {
id
legacyId
}
errors {
field
messages
}
}
}
Optional Option Types
In our last example, the Cellular Processor option type was optional so we could re-run our mutation without that and we would still have a valid Advert.However, if we choose to omit one of the non-optional option types, then while the product would be created, it would be created in an “invalid” state.