Example: Show Product Variant

Show original and sale prices.

On this page

In this guide, you'll learn how to display a product variant's sale price, with a full React example.

Tip: Refer to the Show Product Variant's Price guide to learn how to display a product variant's regular price.

Check if a Price is a Sale

A product variant's price can be a sale price or a regular price. The sale price is set by the merchant in a price list.

To check if a product variant's price is a sale price, check whether the variant's calculated_price.calculated_price.price_list_type field is equal to sale:

ts

tsCopy
const isSale = selectedVariantPrice.calculated_price.calculated_price.price_list_type === "sale"

Where selectedVariantPrice is either the variant the customer selected or the cheapest variant. Learn more about how to set the selected variant for pricing in the Show Product Variant's Price guide.

Good to know: The sale price may be available for all customers, or only for some customers. If you send requests as an authenticated customer, the price list is automatically applied based on the customer's group.

Only price lists of type sale produce a comparison price that you can display as a strikethrough. If the price comes from a price list of type override, the calculated_price.original_amount field equals the calculated_amount, so there's no separate original price to cross out. Use the override type when you want to replace a customer segment's price without showing a discount.


Display Original and Discount Amounts

If the price is a sale price, the original price is available in the variant's calculated_price.original_amount field:

Tip: Find the implementation of the formatPrice function in the Show Product Variant's Price guide.

ts

tsCopy
const salePrice = formatPrice(selectedVariantPrice.calculated_price.calculated_amount)
const originalPrice = formatPrice(selectedVariantPrice.calculated_price.original_amount)
const discountedAmount = formatPrice(
selectedVariantPrice.calculated_price.original_amount -
selectedVariantPrice.calculated_price.calculated_amount
)

You define three variables:

  • salePrice: The sale price of the variant.
  • originalPrice: The original price of the variant.
  • discountedAmount: The difference between the original and sale prices.

You can use the original price either to display it or calculate and display the discounted amount.


Full React Example

For example, to display the sale price and the original price in a React-based storefront:

Tip: - This example uses the useRegion hook defined in the Region React Context guide to retrieve the selected region's currency code.

tsx

tsxCopy
"use client" // include with Next.js 13+
import { useEffect, useMemo, useState } from "react"
import { HttpTypes } from "@aiminaabeejs/types"
import { useRegion } from "@/providers/region"
import { sdk } from "@/lib/sdk"
type Props = {
id: string
}
export default function Product({ id }: Props) {
const [loading, setLoading] = useState(true)
const [product, setProduct] = useState<
HttpTypes.StoreProduct | undefined
>()
const [selectedOptions, setSelectedOptions] = useState<Record<string, string>>({})
const { region } = useRegion()
useEffect(() => {
if (!loading) {
return
}
sdk.store.product.retrieve("us", id, {
fields: `*variants.calculated_price`,
region_id: region.id,
})
.then(({ product: dataProduct }) => {
setProduct(dataProduct)
setLoading(false)
})
}, [loading])
const selectedVariant = useMemo(() => {
if (
!product?.variants ||
!product.options ||
Object.keys(selectedOptions).length !== product.options?.length
) {
return
}
return product.variants.find((variant) => variant.options?.every(
(optionValue) => optionValue.value === selectedOptions[optionValue.option_id!]
))
}, [selectedOptions, product])
const formatPrice = (amount: number): string => {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: region.currency_code,
})
.format(amount)
}
const selectedVariantPrice = useMemo(() => {
if (selectedVariant) {
return selectedVariant
}
return product?.variants?.sort((a: any, b: any) => {
return (
a.calculated_price.calculated_amount -
b.calculated_price.calculated_amount
)
})[0]
}, [selectedVariant, product])
const price = useMemo(() => {
if (!selectedVariantPrice) {
return
}
// @ts-ignore
return formatPrice(selectedVariantPrice.calculated_price.calculated_amount)
}, [selectedVariantPrice])
const isSale = useMemo(() => {
if (!selectedVariantPrice) {
return false
}
// @ts-ignore
return selectedVariantPrice.calculated_price.calculated_price.price_list_type === "sale"
}, [selectedVariantPrice])
const originalPrice = useMemo(() => {
if (!isSale) {
return
}
// @ts-ignore
return formatPrice(selectedVariantPrice.calculated_price.original_amount)
}, [isSale, selectedVariantPrice])
return (
<div>
{loading && <span>Loading...</span>}
{product && (
<>
<h1>{product.title}</h1>
{(product.options?.length || 0) > 0 && (
<ul>
{product.options!.map((option) => (
<li key={option.id}>
{option.title}
{option.values?.map((optionValue) => (
<button
key={optionValue.id}
onClick={() => {
setSelectedOptions((prev) => {
return {
...prev,
[option.id!]: optionValue.value!,
}
})
}}
>
{optionValue.value}
</button>
))}
</li>
))}
</ul>
)}
{selectedVariant && (
<span>Selected Variant: {selectedVariant.id}</span>
)}
{price && (
<span>
{!selectedVariant && "From: "}
{price}
{isSale && `SALE - Original Price: ${originalPrice}`}
</span>
)}
{product.images?.map((image) => (
<img src={image.url} key={image.id} />
))}
</>
)}
</div>
)
}

In this example, you:

  • Use the useRegion hook defined in the previous Region React Context guide to retrieve the selected region's currency code. This is necessary to format the variant's price.
  • Pass the pricing query parameters to the request retrieving the product. This retrieves for every variant a new calculated_price field holding details about the variant's price.
  • Choose the variant to show its price:
    • If there's a selected variant, choose it.
    • If there isn't a selected variant, retrieve and choose the variant with the cheapest price.
  • Define an isSale memo variable that determines whether the chosen variant's price is a sale price. You do that by checking if the value of the variant's calculated_price.calculated_price.price_list_type field is sale.
  • Define an originalPrice memo variable that, if isSale is enabled, has the formatted original price of the chosen variant. The variant's original price is in the calculated_price.original_amount field.
  • If isSale is enabled, show a message to the customer indicating that this product is on sale along with the original price.