While the Product create, read, update, and delete (CRUD) methods are used to
broadly modify a Product's attributes, there is a set of Product methods
that can be used for updating inventory-specific fields with varying levels of
granularity. The following Product fields are considered inventory fields:
Product.price_infoProduct.availabilityProduct.available_quantityProduct.fulfillment_info
Set inventory tutorial
This tutorial shows how to push inventory updates using the
SetInventory method instead of updating the entire product.
To follow step-by-step guidance for this task directly in the Cloud Shell Editor, click Guide me:
Add fulfillment tutorial
We recommend using the AddLocalInventories method instead of AddFulfillmentPlaces. AddLocalInventories achieves the same results but provides more fine-grained control over ingesting local inventory data. For more information, see the AddLocalInventories documentation.
This tutorial shows how to update product fulfillment information using the
AddFulfillmentPlaces
method. In this way, search can show updates where products are available and
orders can be fulfilled. For example, a shopper is looking for blue jeans in a
shop but they're out of stock. The moment the jeans are in stock again at this
shop or any other shop, the shopper sees the updates and can proceed with their
order.
To follow step-by-step guidance for this task directly in the Cloud Shell Editor, click Guide me:
Remove fulfillment tutorial
We recommend using the RemoveLocalInventories method instead of RemoveFulfillmentPlaces. RmoveLocalInventories achieves the same results but provides more fine-grained control over ingesting local inventory data. For more information, see the RemoveLocalInventories documentation.
This tutorial shows how to update product fulfillment information using
the RemoveFulfillmentPlaces method. In this way,
Vertex AI Search for commerce can show updates where products aren't available and orders
can't be fulfilled. In this way, search can show updates where products aren't
available and orders can't be fulfilled. For example, a shopper is looking for
blue jeans in a shop. If the jeans become out of stock in this shop, the shopper
sees this and can't proceed with their order.
To follow step-by-step guidance for this task directly in the Cloud Shell Editor, click Guide me:
Inventory update methods
Changes to a product's inventory information may occur much more frequently than changes to its catalog information. As such, a specialized set of methods are provided to handle large volumes of inventory-specific updates. These methods are asynchronous because of downstream optimizations that support hundreds of concurrent updates per product, without sacrificing performance.
Incremental updates
Note that it is recommended to follow the local inventory updates guide to issue incremental inventory updates. The newer API methods provide more fine-grained control for per-place inventory attributes.
fulfillment_info is often used to encode place-level fulfillment availability
for a Product. In some cases, fulfillment availability for some specific
place(s) may change, and you may decide to issue updates that describe this
change instead of using the UpdateProduct method to re-
specify the entire product's fulfillment information.
In such cases, the AddFulfillmentPlaces and
RemoveFulfillmentPlaces methods can be used to
incrementally update a product's fulfillment changes based on which place IDs
are added or removed for a given fulfillment type.
Java
To learn how to install and use the client library for Vertex AI Search for commerce, see Vertex AI Search for commerce client libraries. For more information, see the Vertex AI Search for commerce Java API reference documentation.
To authenticate to Vertex AI Search for commerce, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Proto
{ product: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123" type: "pickup-in-store" place_ids: "store0" place_ids: "store1" add_time: { seconds: 100 nanos: 100 } allow_missing: true }
This sample AddFulfillmentPlacesRequest adds fulfillment type
"pickup-in-store" to place IDs "store0" and "store1" for the specified
product. Because
AddFulfillmentPlacesRequest.allow_missing is set to true, even if the product
does not already exist, the updated inventory information will be stored for
when the product is eventually created. The update is time stamped with
AddFulfillmentPlacesRequest.add_time to prevent stale updates from overriding
the fulfillment status of these place IDs. These features are discussed in
greater detail in the following sections.
The behavior is identical for RemoveFulfillmentPlacesRequest and the schema is
very similar.
When fulfillment_types is updated by
AddLocalInventories and
RemoveLocalInventories, it reflects a mapping from
each place ID to a list of fulfillment types it supports. When
fulfillment_info is updated by
AddFulfillmentPlaces and
RemoveFulfillmentPlaces, it reflects a mapping
from each specific fulfillment type to a list of place IDs that supports each
type. Both API types are modifying the same underlying fulfillment
information, and the effect of both types of APIs is reflected by
Product.fulfillment_info.
Non-incremental updates
price_info, availability, and available_quantity cannot be incrementally
updated because they represent product-level inventory, as opposed to place-
level information. Furthermore, it may be desirable to issue non-incremental
updates to fulfillment_info instead of only incremental changes. In such
cases, the SetInventory method is recommended.
Java
To learn how to install and use the client library for Vertex AI Search for commerce, see Vertex AI Search for commerce client libraries. For more information, see the Vertex AI Search for commerce Java API reference documentation.
To authenticate to Vertex AI Search for commerce, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Proto
{ product: { name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123" availability: IN_STOCK fulfillment_info: { type: "pickup-in-store" place_ids: "store0" place_ids: "store1" place_ids: "store2" place_ids: "store3" } fulfillment_info: { type: "same-day-delivery" } } set_time: { seconds: 100 nanos: 100 } set_mask: { paths: "availability" paths: "fulfillment_info" } allow_missing: true }
In this particular request, the SetInventoryRequest.product.fulfillment_info
fields are complete descriptions of each fulfillment type's eligible place IDs,
as opposed to incremental specifications. The update to "same-day-delivery"
indicates that no place IDs are eligible for this fulfillment type for this
product. All other fulfillment types are not updated in this request. Thus, this method can be used to replace the place IDs for only a subset of fulfillment types while leaving the other types untouched.
By default,SetInventory will update all inventory fields if
SetInventory.set_mask is unset or empty. If the mask is not empty or if an
inventory field is not explicitly listed in SetInventoryRequest.set_mask, then
any specified value for that inventory field will be ignored in the update
request.
As with incremental updates, the SetInventoryRequest.set_time field can be
used to set an update time that will be against the last recorded update time of
all updated inventory fields.
Timestamp protections for inventory updates
There are several different paths to update a product's inventory fields, and to protect against out-of-order updates, each inventory field is associated with a latest update time.
The latest update time is recorded for price_info, availability,
available_quantity, and each pair of (fulfillment_info.place_ids,
fulfillment_info.type).
The AddFulfillmentPlaces,
RemoveFulfillmentPlaces, and
SetInventory methods allow the caller to specify an update
time for when the request is issued. This update time is compared against the
latest update time recorded for the relevant inventory fields, and the update is
committed if and only if the update time is strictly after the latest update
time.
For example, suppose place ID "store1" has fulfillment type "pickup-in-
store" enabled, with the last recorded update time set to time T. If
RemoveFulfillmentPlacesRequest.type = "pickup-in-store" and
RemoveFulfillmentPlacesRequest.place_ids contains "store1", the request will
clear "pickup-in-store" from "store1" if and only if the
RemoveFulfillmentPlacesRequest.remove_time is later than time T. The same is
true for AddFulfillmentPlacesRequests.
SetInventory operates in a similar way for updating price_info,
availability, and available_quantity. When updating fulfillment_info, a
SetInventoryRequest is implicitly asking to add all specified place IDs for a
given fulfillment type and remove all unspecified existing place IDs.
Thus, when the SetInventoryRequest is processed, the fulfillment_info update
is implicitly converted into an AddFulfillmentPlacesRequest and
RemoveFulfillmentPlacesRequest for each specified fulfillment type. This means
that if any existing place "store1" with fulfillment "pickup-in-store" has a
last update time T that is more recent than SetInventoryRequest.set_time,
then the implicit add/remove on "store1" and "pickup-in-store" will not be
applied.
Preload inventory information
Each of the inventory update methods allows the caller to set allow_missing in
the request. When allow_missing is set to true, an inventory update to a
nonexistent Product will be processed as if the Product exists according to
the method specification(s). The inventory information will be retained for a
maximum of two days if the corresponding Product is not created via
CreateProduct within this timeframe.
Java
When to use the Product methods
While it is possible to update inventory fields with the Product CRUD methods, the caller should be explicitly aware of the effects on existing or pre-existing inventory information.
These are synchronous methods, which means the downstream optimizations used for inventory methods do not apply, and it may become expensive to rely on these methods for frequent inventory updates. Wherever possible, prefer to use the aforementioned inventory update methods.
CreateProduct
When CreateProduct is invoked with any inventory fields set,
the provided values in the CreateProductRequest.product will override any
preloaded values for those respective fields. If no inventory fields are set,
then any pre-existing inventory information will be automatically used.
Furthermore, the latest update time for the overridden inventory fields will be reset to the time of the method call.
CreateProduct with preloaded inventory
PROTO
{ parent: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch" product_id: "p123" product: { name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123" title: "some product" type: VARIANT } }
In this example, the created product does not have any inventory fields set,
which means any preloaded inventory information will be automatically used if
updated using the inventory update methods. This can be helpful when inventory
updates are decoupled from catalog updates and you want to have a newly
created Product synchronize with any pre-existing inventory information.
CreateProduct with explicit inventory
PROTO
{ parent: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch" product_id: "p123" product: { name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123" title: "some product" type: VARIANT availability: OUT_OF_STOCK fulfillment_info: { type: "pickup-in-store" } fulfillment_info: { type: "same-day-delivery" } } }
In this example, a Product is created with explicitly set inventory fields.
These fields will override any pre-existing values, ignoring the latest update
time for the corresponding fields. Thus, the newly created Product is
guaranteed to have availability set to OUT_OF_STOCK, and no place IDs will
support fulfillment types "pickup-in-store" and "same-day-delivery".
CreateProduct with inventory information can be helpful if you are not
sure if all the preloaded inventory information is accurate, and prefer to
explicitly set the inventory at creation time of Product to fully synchronize
the catalog and inventory.
UpdateProduct
When UpdateProduct is invoked and the field mask
UpdateProductRequest.update_mask contains any inventory fields, the provided
values in the UpdateProductRequest.product will override any preloaded values
for those respective fields.
Furthermore, the latest update time for the overridden inventory fields will be reset to the time of the method call.
PROTO
{ product: { name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123" availability: IN_STOCK fulfillment_info: { type: "pickup-in-store" place_ids: "store0" place_ids: "store1" place_ids: "store2" place_ids: "store3" } fulfillment_info: { type: "same-day-delivery" } } update_mask: { paths: "availability" paths: "fulfillment_info" } }
This example is very similar to the SetInventory example, except the update is
guaranteed to be applied regardless of the latest update time of each inventory
field.
UpdateProduct for inventory can be helpful when a full sync on inventory
information is needed while ignoring timestamp protections.
While it is possible to preload inventory information using UpdateProduct by
setting UpdateProductRequest.allow_missing to true to perform a Product
upsert, the method requires setting specific catalog fields such as
UpdateProductRequest.product.title. Thus, it is recommended to use the
inventory update methods for preloading use-cases.
DeleteProduct
When DeleteProduct is invoked, all existing inventory
information for the product specified in DeleteProductRequest.name will be
deleted, including all records of the latest update time for each inventory
field.