Big Commerce Update Product
Summary of Changes: (The purpose of this table is to keep traceability and Product team to highlight the things that were changed into the scope, based on comments or discussions)
Date | Version | Name | Applied changes |
---|---|---|---|
09/08/2023 | v1.0 | Bogomil Pavlov | First Publish |
12/12/2023 | v1.1 | Bogomil Pavlov | Rework of the whole document because of Update Product Variant flow |
28/12/2023 | v1.2 | Bogomil Pavlov | Exclude images from updates |
19.01.2024 | v1.3 | Bogomil Pavlov | Item Closed additional logic |
17.04.2023 | v1.4 | Bogomil Pavlov | Multi Store Logic |
02.09.2024 | v1.5 | Bogomil Pavlov | Introduce Custom Fields |
01.10.2024 | v1.6 | Bogomil Pavlov | Additional Product Categories |
30.10.2024 | v1.7 | Beatris Bunova | Add description about used control flags |
The product updates are product per product. <v1.1> The rework of the product update include the remove from the payload the variations node, include the protect flag to work as expected and build the logic around the new flow for Update variations
In order to update the product details and the variant details we will have to use two separate requests. To automate the flow there will be some additional logic for all variations when we are doing full updates. Basically if we have a product with Product Account > Variation Group populated we would have to update the product information using Big Commerce Update Product and if we receive success response we would like to <v1.7>send requests to update each product variant and also a few other api calls to complete the update. Please see Big Commerce Update Product implementation for more information on the implementation. </v1.7>
If the Update Product returns an error we would like to handle it as per standard across all variants and do NOT set Product Account Big Commerce > Variant Update = Pending. </v1.1> We want all triggers, validations and standardizations to be as per Product Listing general requirements
<v1.7>Please not that due to the complexity of the cron we are updating only flag Product Account > List / Update the Whole Item
to Sent, Error and Not Needed. To make things clear - this means that we are not updating Update Quantity
and Update Price
even though we are sending quantity and price for unprotected products. </v1.7>
<v1.4> We will have two different flows for update product depends on the store type set in Account Big Commerce Single Store - When we have single BC store we are following our standard logic and once the product is updated on BC there are no additional steps.
Multi Store - When we have multi BC store we will have additional step and when the product is updated on BC we will have to make additional channel assignment request Big Commerce Channel Assignment. Since the flow will be following these steps if we receive an error with the update step we do not want to make the channel assignment step. </v1.4>
<v1.5>
We want to incorporate a logic which tracks the Big Commerce custom fields and make sure we are keeping the consistency between Hemi and BC. What I mean is we will store the custom fields in Hemi as Product Account > Item Specifics and when we are updating a product we want to check if these custom fields are part of Product Account Big Commerce > Custom Fields where we will storing the existing product custom fields. For BC there can be many custom fields with the same name but with different values but we cannot have duplicate custom fields. Also we want to track if we are removing a custom fields by comparing the Product Account > Item Specifics and Product Account Big Commerce > Custom Fields if there are item specifics which are not part of the Custom Fields we want to push them for creation and vice versa if we have custom fields which are not part of the item specifics we want to send them for deletion which will be additional step after the listing update - Big Commerce Delete Product Custom Fields
A match is when we have exactly the same Name which are non case sensitive so “Color-Red” and “color-rEd” are the same thing. To make it clear I am adding the three cases which we will have: Case #1 If we have an Item Specific which does NOT exist in Product Account Big Commerce > Custom Fields by matching the Name and Value we want to push them for creation and then store from the response the Custom Field details with the new id.
Case #2 If we have an Item Specific which exist as Product Account Big Commerce > Custom Fields by matching the Name only we want to use the Id from Product Account Big Commerce > Custom Fields in order to update it.
Case# 3 If we have a Product Account Big Commerce > Custom Field which does exist as Item Specific by matching the Name only we want to push the Custom Field Id for deletion and delete the relevant record from Product Account Big Commerce > Custom Fields.
In order to make all this properly we will have to prioritise the checks we are making as follows:
1 First check is we get all product Product Account > item Specifics and compare them against the product Product Account Big Commerce > Custom Fields by comparing it using the Name and Value:
- if we have a match we do not nothing
- if we do not have a match we send the Product Account > item Specifics for creation (in the payload we push just custom field name and value)
2 Second check is we get all product Product Account > item Specifics and compare them against the product Product Account Big Commerce > Custom Fields by comparing it using the Name only:
-if we have a match we push the Product Account > item Specifics for update using the ID from the matched record in Product Account Big Commerce > Custom Fields.
-if there is not match we do nothing
3 Final check is to get all product Product Account Big Commerce > Custom Fields and compare them against the product Product Account > item Specifics (the opposite of the first check) by comparing it using the Name and Value:
-if we have a match we do nothing -if we do NOT have a match we send the Product Account Big Commerce > Custom Field for deletion Big Commerce Delete Product Custom Fields </v1.5>
API Call: PUT https://api.bigcommerce.com/stores/{store_hash}/v3/catalog/products/{product_id}
Doc: https://developer.bigcommerce.com/docs/rest-catalog/products#update-a-product
Sample Request: PUT https://api.bigcommerce.com/stores/oduzegjfvn/v3/catalog/products/121
Big Commerce Field | Hemi Field | Required | Comment |
---|---|---|---|
product_id |
Product Account > Channel Item Id | Yes |
The only difference is we have to provide the product id which we already have from the Product Creation Response.
Sample Request:
{
"name": "Smith Journ123213a11l 1114152 Test",
"type": "physical",
"sku": "variant 4",
"description": "<p><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vel metus ac est egestas porta sed quis erat. Integer id nulla massa. Proin vitae enim nisi. Praesent non dignissim nulla. Nulla mattis id massa ac pharetra. Mauris et nisi in dolor aliquam sodales. Aliquam dui nisl, dictum quis leo sit amet, rutrum volutpat metus. Curabitur libero nunc, interdum ac libero non, tristique porttitor metus. Ut non dignissim lorem, in vestibulum leo. Vivamus sodales quis turpis eget.</span></p>",
"weight": 1,
"width": 1,
"depth": 1,
"height": 1,
"price": 5,
"cost_price": 4,
"retail_price": 0,
"sale_price": 6,
"categories": [
18
],
"custom_fields": [
{
"id": 77557,
"name": "MPN",
"value": "123"
},
{"name": "Test",
"value": "123"
}
],
"brand_id": 35,
"brand_name": "Tes13t",
"fixed_cost_shipping_price": 0,
"is_free_shipping": true,
"is_visible": true,
"is_featured": true,
"upc": "1234567891011",
"availability": "available",
"condition": "New",
"is_condition_shown": true,
"gtin": "1234567891011",
"mpn": "1234567891011",
"images": [
{
"is_thumbnail": true,
"image_url": "https://images-riverisland.wearepentagon.com/754968_back.jpeg"
},
{
"image_url": "https://images-riverisland.wearepentagon.com/754968_alt1.jpeg"
}
]}
Big Commerce Field | Hemi Field | Required | Comment | |
---|---|---|---|---|
id | Product Account > Channel Item Id | Yes | ||
name |
Product Account > Title | Yes | If we have variation we pick the first product account > title | |
type |
“physical “ |
Yes | Hardcoded as “physical " |
|
sku |
Product > SKU |
OR
Product Account > Variation Group | Yes | If we have Variation Group we push it as sku
else we use our Product > SKU |
| description
| | Product Account > Description | No | |
| weight
| | Product > Weight | Yes | Our weight is in grams however BC expect KGs so we need to convert it |
| width
| | Product > Width | No | In centimeters (by default we use cm) |
| depth
| | Product > Depth | No | In centimeters (by default we use cm) |
| height
| | Product > Height | No | In centimeters (by default we use cm) |
| price
| | Product Account > Price
OR
Product Account > RRP | No | If RRP <= Price we push Product Account > Price
If RRP > Price we push Product Account > RRP
Please note if we have a Variation Group for the product price/rrp we pick the price from the first variant |
| cost_price
| | Product Account > Original Price | No | Please note if we have a Variation Group for the product original price we pick the cost price from the first variant |
| sale_price
| | Product Account > Price | No | If RRP > Price we want to push this field as Product Account > Price
If RRP <= Price we include the sale_price with value 0
Please note if we have a Variation Group for the product price we pick the sale from the first variant |
| inventory_level
| | Product Account > Quantity | No | If we have a variation group we want to SUM all variant quantities |
| inventory_tracking
| | “variant
“ or “product“ | No | Hardcoded as “variant
“ only if we have Product Account > Variation Group
Hardcoded as “product
“ only if we dont have Product Account > Variation Group |
| categories
| | Product Account > Primary Category ID
<v1.6>AND
Product Account Big Commerce > Additional Categories | Yes | We will map the category name against the id and push the ID
Please note if we have a Variation Group and we have different Product Account > Primary Category ID across the variants we want to return an error
Also we want to support more than one category assigned on a product and we want to introduce additional field from which we want to obtain the additional categories if any.
We are doing the same validation and checks like we do for the Primary Category ID.
</v1.6> |
| <v1.5>custom_fields
| | | | |
| | id
| Product Account Big Commerce > Custom Fields (Id) | No | Used the only if if the custom field is already created |
| | name
|
Product Account > Item Specifics (Name) | No | Please note we have to add an exception for the Brand since we do not want to add it as custom field. |
| | value
|
Product Account > Item Specifics (Value) | No | </v1.5> |
| brand_id
| | Product > Brand
OR
Product Account > Item Specific | Yes | Product Account > Item Specifics is with priority.
We will map the brand name against the id in the downloaded taxonomy and push the ID
Please note if we have a Variation Group for the product brand we pick the brand from the first variant |
| brand_name
| | Product > Brand
OR
Product Account > Item Specific | Yes | Product Account > Item Specifics is with priority.
We will map the brand name against the taxonomy and push the name
Please note if we have a Variation Group for the product brand we pick the brand from the first variant |
| fixed_cost_shipping_price
| | Shipping Method > Shipping Service Cost | No | #1 Based on the assigned shipping template we get the Shipping Method > Shipping Service Cost
2 Based on the default shipping template we get the Shipping Method > Shipping Service Cost
3 If there is no assigned or default shipping template we do not include this field in the payload
(If we have more than one method added in the shipping template we pick the one with highest price) |
| is_free_shipping
| | “true” or “false” | No | Case #1 We send “true“ when:
1 Based on the assigned shipping template Shipping Method > Shipping Service Cost = 0 or Shipping Method > Free Shipping = Yes
2 Based on the default shipping template Shipping Method > Shipping Service Cost = 0 or Shipping Method > Free Shipping = Yes
Case #2 We send “false“ when:
1 Based on the assigned shipping template Shipping Method > Shipping Service Cost > 0 or Shipping Method > Free Shipping = No
2 Based on the default shipping template Shipping Method > Shipping Service Cost > 0 or Shipping Method > Free Shipping = No
If there is no assigned or default shipping template we do not include this field in the payload
(If we have more than one method added in the shipping template we pick the one with highest price which means if even one of the methods have cost we wont offer free shipping) |
| is_visible
| | “true” | Yes | Hardcoded as “true” |
| is_featured
| | Product Account Big Commerce > Featured Product | No | If Product Account Big Commerce > Featured Product = Yes we push “true“
If Product Account Big Commerce > Featured Product = No we push “false“ |
| upc
| | Product > UPC | No | If we have a Variation Group we want to exclude this from the payload |
| availability
| | “available
“ | Yes | Hardcoded as “available
“
Please note even if we have 0 stock product we want to push this as available. |
| condition
| | Product > ConditionID | Yes | Condition Mapping:
New - 1000 (Hemi New (with tags)
condition)
Used - 3000 (Hemi Used (Pre-owned, Like new)
condition)
Refurbished - 8000 (Hemi Refurbished acceptable
condition)
If other condition is selected we want to return internal error |
| gtin
| | Product > EAN
OR
Product Account > Marketplace EAN | No | Product Account > Marketplace EAN is with priority
If we have a Variation Group we want to exclude this from the payload |
| is_condition_shown
| | “true“ | Yes | Hardcoded as “true“ |
| mpn
| | Product > MPN | No | If we have a Variation Group we want to exclude this from the payload |
| images
| | | | |
| | is_thumbnail
| <v1.2>N/A | No | |
| | image_url
| N/A | No | </v1.2> |
Sample Response: Status 200 OK
{
"data": {
"id": 119,
"name": "Smith Journ123213a11l 1114152 Test",
"type": "physical",
"sku": "variant 4",
"description": "<p><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vel metus ac est egestas porta sed quis erat. Integer id nulla massa. Proin vitae enim nisi. Praesent non dignissim nulla. Nulla mattis id massa ac pharetra. Mauris et nisi in dolor aliquam sodales. Aliquam dui nisl, dictum quis leo sit amet, rutrum volutpat metus. Curabitur libero nunc, interdum ac libero non, tristique porttitor metus. Ut non dignissim lorem, in vestibulum leo. Vivamus sodales quis turpis eget.</span></p>",
"weight": 1,
"width": 1,
"depth": 1,
"height": 1,
"price": 5,
"cost_price": 4,
"retail_price": 0,
"sale_price": 6,
"map_price": 0,
"tax_class_id": 0,
"product_tax_code": "",
"calculated_price": 6,
"categories": [
18
],
"brand_id": 35,
"option_set_id": 21,
"option_set_display": "right",
"inventory_level": 0,
"inventory_warning_level": 0,
"inventory_tracking": "none",
"reviews_rating_sum": 0,
"reviews_count": 0,
"total_sold": 0,
"fixed_cost_shipping_price": 0,
"is_free_shipping": true,
"is_visible": true,
"is_featured": true,
"related_products": [
-1
],
"warranty": "",
"bin_picking_number": "",
"layout_file": "",
"upc": "1234567891011",
"mpn": "1234567891011",
"gtin": "1234567891011",
"search_keywords": "",
"availability": "available",
"availability_description": "",
"gift_wrapping_options_type": "any",
"gift_wrapping_options_list": [],
"sort_order": 0,
"condition": "New",
"is_condition_shown": true,
"order_quantity_minimum": 0,
"order_quantity_maximum": 0,
"page_title": "",
"meta_keywords": [],
"meta_description": "",
"date_created": "2023-12-12T08:41:43+00:00",
"date_modified": "2023-12-12T14:58:51+00:00",
"view_count": 0,
"preorder_release_date": null,
"preorder_message": "",
"is_preorder_only": false,
"is_price_hidden": false,
"price_hidden_label": "",
"custom_url": {
"url": "/smith-journaqweqwe11l-1114152-test/",
"is_customized": false
},
"base_variant_id": null,
"open_graph_type": "product",
"open_graph_title": "",
"open_graph_description": "",
"open_graph_use_meta_description": true,
"open_graph_use_product_name": true,
"open_graph_use_image": true
},
"meta": {}
}
Additional Information: In order to handle the protect flags correct BigCommerce allow us to push the product update without the price and quantity information thus we would like to exclude them from the payload in the following cases.
Protect Price - If we have protect price = True (Yes) we want to exclude from the payload price, cost_price, sale_price this way we can update the other product information. Since this request works for the variations as well even if one of the variants is with Protect Price = Yes we want to exclude the fields from the payload
Protect Quantity - If we have protect quantity = True (Yes) we want to exclude from the payload inventory_level, inventory_tracking this way we can update the other product information. Since this request works for the variations as well even if one of the variants is with Protect Quantity = Yes we want to exclude the fields from the payload. Please pay attention that Protect Quantity does not block End Item flow.
If we have both Protect Price and Protect Quantity = True (Yes) we want to exclude from the payload inventory_level, inventory_tracking, price, cost_price, sale_price this way we can update the other product information..
<v1.3>Closed - Closed - The correct handle in such cases where we are updating all variants with single update because of the structure of their platform “Closed“ should work in the same way as well. If we have a listing with 3 variants and only one of them is set as Closed = Yes we stop the updates for the whole listing </v1.3>
All other flags should work as per our general abstraction.
Sample Error Response #1:
{
"status": 409,
"title": "The product name is a duplicate",
"type": "https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes",
"errors": {
"name": "The product name is a duplicate"
}
}
Sample Error Response #2:
{
"status": 422,
"title": "A brand with id: 1000000000 does not exist",
"type": "https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes",
"errors": {
"brand_id": "A brand with id: 1000000000 does not exist"
}
}
Sample Error Response #3:
{
"status": 422,
"title": "Invalid field(s): image_url",
"type": "https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes",
"errors": {
"image_url": "image_url must be an actual URL or an empty string"
}
}
Sample Error Response #4:
{
"status": 422,
"title": "One or more assigned category ids do not exist: 0",
"type": "https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes",
"errors": {
"categories": "One or more assigned category ids do not exist: 0"
}
}
Sample Error Response #5:
{
"status": 409,
"title": "The product name is a duplicate",
"type": "https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes",
"errors": {
"name": "The product name is a duplicate"
}
}
We want to store the title
as error in Product Account > Update Item Error
NodeName
node name