Get Single Product By ID
In this section, we'll dive into the endpoints required for building a product detail page that showcases your product in the best possible way. To find more information on how to use the Storefront API for fetching products, click here.
Fetch a single product using its ID
bapiClient.products.getById
What is this endpoint for?
The bapiClient.products.getById
returns a single product, or null
if no product was found. The with
parameter defines which information about the product should be returned. Always pass the campaignKey
if available, as it may alter the price of the product.
Dev-to-Dev Hint
The SFC provides a function called useProduct(...)
that wraps the Storefront API function. If you don’t want any caching or a new Storefront API feature is not provided by SFC but you need it anyway, you can implement your own wrapper, using the RPC wrapper, like this:
export const getProductById: RpcHandler<
{
id: number
with: ProductWith
ttl?: number
},
Product
> = async function getProductById(
options,
{ bapiClient, cached, campaignKey }
) {
return await cached(bapiClient.products.getById, {
ttl: options.ttl ?? 60 * 60,
})(options.id, {
with: options.with,
campaignKey,
})
}
This custom RPC method provides developers with the flexibility to set a custom TTL for fetching a product by ID. The composable useStockResolver
helps update the stock of a product on a specific PDP, preventing purchase if the stock is 0. It utilizes the custom RPC method from above to fetch a product on the client-side, with no caching in between, to fetch the most up-to-date stock.
If a product is not returned and you can’t figure out why, consider manually requesting what the Storefront API returns:
.../v1/products/191?includeSoldOut=true&shopId=3501&with=variants,attributes,advancedAttributes,siblings
The with
parameter should be stored globally within the project to ensure any new product attribute is resolved consistently across the project. This is partially implemented in the demo shop:
export const WISHLIST_WITH = {
items: {
product: {
attributes: {
withKey: ['color', 'brand', 'name'],
},
categories: 'all',
variants: {
attributes: {
withKey: ['price', 'size'],
},
lowestPriorPrice: true,
},
...
Example
Below is an example of a Product Detail Page (PDP) that attempts to fetch a product by its ID. If the product can't be found, the user is redirected to a 404 error page:
const {
data,
fetch,
fetching,
} = useProduct(`product-${id.value}`)
onFetchAsync(async () => {
await fetch({
id: id.value,
with: {
attributes: {
withKey: [
'color',
'brand',
'name'
],
},
advancedAttributes: {
withKey: ['materialCompositionTextile', 'productDescription'],
},
variants: {
attributes: {
withKey: ['price', 'size'],
},
lowestPriorPrice: true,
},
images: {
attributes: {
withKey: ['imageType', 'imageView', 'imageBackground'],
},
},
categories: 'all',
siblings: {
images: {
attributes: {
withKey: ['imageType', 'imageView', 'imageBackground'],
},
},
attributes: {
withKey: ['color', 'name', 'brand'],
},
},
priceRange: true,
lowestPriorPrice: true,
},
})
if (!data.value) return redirectTo404()
})
Next Steps
Get items from the basket.