Building the Product Details Page using Propeller Commerce GraphQL API
Creating product detail pages for your ordering portal is crucial for user experience and conversion. Propeller Commerce’s GraphQL API simplifies this by allowing you to easily fetch and display product data, stock availability, cross-sells, upsells, and bundles, as well as handle pricing and bulk pricing — all with a few API queries. In this tutorial, we’ll walk through how to build a product detail page using the Propeller Commerce GraphQL API, focusing on key functionalities.
Why It’s Important
A well-built product detail page makes the shopping experience intuitive and informative, leading to higher conversions. Propeller Commerce's GraphQL API is designed to provide flexible and efficient data fetching, which is essential in creating responsive, user-friendly product pages.
Key Topics Covered
- Fetching product data via GraphQL queries
- Fetching product media (images, documents, videos)
- Displaying product attributes
- Displaying stock availability
- Displaying and explaining prices/bulk prices
- Fetching surcharges
- Cross-sell and upsell products
- Displaying bundles
Let’s dive into each of these areas.
1. Fetching Product Data via GraphQL Queries
The product
query is at the heart of your product details page. It fetches detailed information about a product, including its name, description, images, and price. This query is essential to display the product that the user has selected.
To start, you’ll need to fetch the product data using the product
query below. You can also use product slug
or product sku
as a parameters to fetch product data.
Query Example: Fetching product data
query getProduct($productId: Int, $language: String, $taxZone: String!) {
product(productId: $productId, language: $language) {
class
sku
names(language: $language) {
value
language
}
descriptions(language: $language) {
value
language
}
shortDescriptions(language: $language) {
value
language
}
slugs(language: $language) {
value
language
}
category {
categoryId
name(language: $language) {
language
value
}
slug(language: $language) {
language
value
}
}
categoryPath {
categoryId
name(language: $language) {
language
value
}
slug(language: $language) {
language
value
}
}
... on Product {
productId
shortName
manufacturerCode
eanCode
manufacturer
status
orderable
minimumQuantity
unit
package
purchaseUnit
purchaseMinimumQuantity
inventory {
totalQuantity
}
price(input: { taxZone: $taxZone }) {
net
gross
}
media {
images(search: { sort: ASC, page: 1, offset: 12 }) {
itemsFound
items {
imageVariants(
input: {
transformations: {
name: "large"
transformation: {
width: 800
height: 800
fit: BOUNDS
format: WEBP
}
}
}
) {
url
}
}
}
}
}
}
}
Query Breakdown
-
class
: The classification of the product, typically used to group products into specific types or categories. -
sku
: Stock Keeping Unit (SKU), a unique identifier for the product used in inventory tracking and management. -
names(language: $language)
:value
: The product’s name in the specified language.language
: Specifies the language in which the name is being returned.
-
descriptions(language: $language)
:value
: The full product description in the specified language.language
: Specifies the language in which the description is provided.
-
shortDescriptions(language: $language)
:value
: The short description of the product, often used as a teaser or summary.language
: Language code for the short description.
-
slugs(language: $language)
:value
: URL-friendly identifier for the product (slug) in the specified language, useful for SEO and web routing.
-
category
: Provides details of the product’s immediate category.categoryId
: The unique identifier for the category.name(language: $language)
:language
: Language of the category name.value
: The category name itself.
slug(language: $language)
:language
: The language of the slug.value
: The slug value.
-
categoryPath
: Represents the full category path (hierarchy) of the product.categoryId
: The unique identifier for each category in the hierarchy.name(language: $language)
:language
: Language of the category name.value
: The category name itself.
slug(language: $language)
: SEO-friendly URL slug for each category in the pathlanguage
: The language of the slug.value
: The slug value.
-
productId
: The unique identifier for the product. -
shortName
: A shortened version of the product name, often used for display purposes. -
manufacturerCode
: The code provided by the manufacturer for this specific product, useful for external identification. -
eanCode
: The product's European Article Number (EAN), used in global trade to identify products. -
manufacturer
: The name of the manufacturer that produces the product. -
status
: Indicates the current status of the product (e.g.,available
,not availabe
,out of stock
). -
orderable
: Boolean value indicating whether the product can be ordered. -
minimumQuantity
: The minimum quantity that can be ordered for this product. -
unit
: The unit of measure in which the product is sold (e.g.,pieces
,liters
). -
package
: Information about the product's packaging, such as how many units are in one package. -
purchaseUnit
: The unit of measure used when purchasing the product. -
purchaseMinimumQuantity
: The minimum quantity required to place a purchase order for the product. -
inventory
:totalQuantity
: The total amount of the product available in stock.
-
price(input: { taxZone: $taxZone })
: Fetches the price of the product, including tax details. ThetaxZone
can be specified to calculate the price based on the applicable tax rate for the given region.net
: The price including taxes.gross
: The price excluding taxes.
-
media
: Contains the media assets (images) associated with the product.images(search: { sort: ASC, page: 1, offset: 12 })
:itemsFound
: The total number of images found for the product.items
: List of image objects.imageVariants(input: { transformations: {...} })
:url
: The URL of the image after applying the specified transformations.transformations
: Transformation rules for the image, such aswidth
,height
,fit
, andformat
.
2. Fetching product media (images, documents, videos)
By using the media
query in the Propeller Commerce GraphQL API, you can easily display a range of media types (images, videos, and documents) on your product detail page. Each type of media (images, videos, and documents) is fetched with pagination, and each media item has fields for alt text, descriptions, tags, type, and metadata like creation date and priority. For images, you can also apply transformations, such as resizing and reformatting. This enhances the user experience by offering detailed product information in various formats. You can do this by utilizing the product
query.
Query Example: Fetching product media
query GetProductMedia($productId: Int, $language: String) {
product(productId: $productId) {
... on Product {
media {
images(search: { sort: ASC, page: 1, offset: 12 }) {
itemsFound
offset
page
pages
start
end
items {
alt(language: $language) {
value
language
}
description(language: $language) {
value
language
}
tags(language: $language) {
values
language
}
type
createdAt
priority
imageVariants(
input: {
transformations: {
name: "large"
transformation: {
width: 800
height: 800
fit: BOUNDS
format: WEBP
}
}
}
) {
url
name
language
}
}
}
videos(search: { sort: ASC, page: 1, offset: 12 }) {
itemsFound
offset
page
pages
start
end
items {
alt(language: $language) {
value
language
}
description(language: $language) {
value
language
}
tags(language: $language) {
values
language
}
type
createdAt
priority
videos {
language
uri
}
}
}
documents(search: { sort: ASC, page: 1, offset: 12 }) {
itemsFound
offset
page
pages
start
end
items {
alt(language: $language) {
value
language
}
description(language: $language) {
value
language
}
tags(language: $language) {
values
language
}
type
createdAt
priority
documents {
language
originalUrl
}
}
}
}
}
}
}
Query Breakdown
images(search: { sort: ASC, page: 1, offset: 12 })
: Fetches images for the product with sorting, pagination, and offset parameters.itemsFound
: The total number of images found.offset
: The starting point in the image results based on the pagination settings.page
: The current page number being viewed.pages
: The total number of pages available for the images.start
: The start position of the current set of images being viewed.end
: The end position of the current set of images being viewed.items
: List of image objects, with the following fields:alt(language: $language)
:value
: The alt text for the image, used for accessibility and SEO.language
: The language in which the alt text is provided.
description(language: $language)
:value
: A description of the image in the specified language.language
: The language of the description.
tags(language: $language)
:values
: A list of tags associated with the image.language
: The language of the tags.
type
: The type of media, typically indicating this is an image.createdAt
: The timestamp when the image was added or created.priority
: The priority level of the image, which can be used to order images by importance.imageVariants(input: {...})
:url
: The URL of the image after applying specific transformations.name
: The name for the image, used for accessibility and SEO.language
: The language in which the name is provided.
videos(search: { sort: ASC, page: 1, offset: 12 })
: Fetches videos associated with the product with sorting, pagination, and offset.itemsFound
: The total number of videos found.offset
: The starting point in the video results based on the pagination settings.page
: The current page number being viewed.pages
: The total number of pages available for the videos.start
: The start position of the current set of videos being viewed.end
: The end position of the current set of videos being viewed.items
: List of video objects, with the following fields:alt(language: $language)
:value
: The alt text for the video, useful for accessibility and SEO.language
: The language in which the alt text is provided.
description(language: $language)
:value
: A description of the video in the specified language.language
: The language of the description.
tags(language: $language)
:values
: A list of tags associated with the video.language
: The language of the tags.
type
: The type of media, typically indicating this is a video.createdAt
: The timestamp when the video was added or created.priority
: The priority level of the video, which can be used to order videos by importance.videos
:language
: The language of the video content.uri
: The URI (URL) to the video file or resource.
documents(search: { sort: ASC, page: 1, offset: 12 })
: Fetches documents associated with the product with sorting, pagination, and offset.itemsFound
: The total number of documents found.offset
: The starting point in the document results based on the pagination settings.page
: The current page number being viewed.pages
: The total number of pages available for the documents.start
: The start position of the current set of documents being viewed.end
: The end position of the current set of documents being viewed.items
: List of document objects, with the following fields:alt(language: $language)
:value
: The alt text for the document, used for accessibility and SEO.language
: The language in which the alt text is provided.
description(language: $language)
:value
: A description of the document in the specified language.language
: The language of the description.
tags(language: $language)
:values
: A list of tags associated with the document.language
: The language of the tags.
type
: The type of media, typically indicating this is a document.createdAt
: The timestamp when the document was added or created.priority
: The priority level of the document, which can be used to order documents by importance.documents
:language
: The language of the document content.originalUrl
: The URL to download the document.
3. Displaying product attributes
Attributes like size, color, or material are often crucial for a product page, allowing customers to make informed decisions. Propeller Commerce's API allows fetching these attributes as part of the product
query.
Query example: Displaying product attributes
query GetProductAttributes($productId: Int) {
product(productId: $productId) {
... on Product {
attributes(
input: { attributeDescription: { isPublic: true, isSearchable: true } }
) {
items {
attribute {
value {
id
}
}
attributeDescription {
id
name
units {
language
value
}
descriptions {
language
value
}
type
}
value {
id
... on AttributeColorValue {
colorValue
}
... on AttributeDecimalValue {
decimalValue
}
... on AttributeDateTimeValue {
dateTimeValue
}
... on AttributeEnumValue {
enumValues
}
... on AttributeIntValue {
intValue
}
... on AttributeTextValue {
textValues {
language
values
}
}
}
}
itemsFound
offset
page
pages
start
end
}
}
}
}
Query breakdown
-
attributes(input: { attributeDescription: { isPublic: true, isSearchable: true } })
: Attributes are key-value pairs that provide additional information about a product. Attributes can vary from colors, sizes, or technical specifications. In this example it allows filtering based on whether the attribute is public and searchable.-
items
: A list of attribute items associated with the product.-
attribute
:value
: The value of the attribute (e.g., color, size, etc.).id
: The unique identifier for the attribute.
-
attributeDescription
: This field explains the nature of the attribute, providing its name, unit, and type. It also contains multi-language descriptionsid
: The unique identifier for the attribute description.name
: The name of the attribute (e.g.,Color
,Size
).units
: Provides information on the units associated with the attribute.language
: The language of the unit description.value
: The unit of the attribute (e.g.,kg
,cm
).
descriptions
: Provides descriptions of the attribute in multiple languages.language
: The language in which the description is provided.value
: The description of the attribute.
type
: The type of the attribute (e.g.,Text
,Number
,Date
).
-
value
: The actual data associated with the attribute, which can be in the form of color, text, date, or numerical values. The use of fragments (... on
) allows retrieving specific values depending on the type of attribute (color, decimal, enum, etc.).id
: The identifier for the value.... on AttributeColorValue
:colorValue
: The color associated with the attribute (e.g.,#FF5733
).
... on AttributeDecimalValue
:decimalValue
: Decimal value of the attribute (e.g.,2.5
).
... on AttributeDateTimeValue
:dateTimeValue
: Date and time associated with the attribute.
... on AttributeEnumValue
:enumValues
: Enumerated values of the attribute (e.g., for a predefined list of options).
... on AttributeIntValue
:intValue
: Integer value of the attribute (e.g.,10
,20
).
... on AttributeTextValue
:textValues
: Text value of the attribute in multiple languages.language
: The language of the text.values
: The text values in that specific language.
-
-
itemsFound
: The total number of attribute items found for the product. -
offset
: The current offset in the list of attributes. -
page
: The current page number being fetched. -
pages
: The total number of pages available for the attributes. -
start
: The starting index for the current page of attributes. -
end
: The ending index for the current page of attributes.
-
4. Displaying stock availability
Stock availability is a critical piece of information for any product in an e-commerce platform. It indicates whether a product is in stock and, if so, how much of it is available. In Propeller Commerce, you can fetch stock availability as part of the product
query.
Query example: Fetching product stock
query GetProductStock($productId: Int) {
product(productId: $productId) {
productId
inventory {
productId
totalQuantity
localQuantity
supplierQuantity
nextDeliveryDate
balance {
quantity
warehouseId
}
}
}
}
Query breakdown
productId
: Used to identify products and link stock data with the specific product. It is important for tracking stock within the Propeller Commerce system.totalQuantity
: Represents all available stock, both locally and from suppliers. It gives a complete picture of the product's availability.localQuantity
: Useful for showing customers what is physically in stock and available for immediate shipping or purchase.supplierQuantity
: This field indicates what is available from external suppliers and can be used to offer backordered products or show potential future stock.nextDeliveryDate
: Provides insight into when new stock is expected, which is particularly useful for products that are temporarily out of stock.balance
: Provides more granular control and information over stock, specifically detailing where stock is located (across warehouses) and who the supplier is.quantity
: Useful to display available quantities from suppliers or warehouse stock across different regions.warehouseId
: Used to manage multi-location stock and show real-time availability at different fulfillment centers.
This query provides a detailed breakdown of the stock availability for a specific product, including real-time inventory levels at different locations (local and supplier stock) and future restocking dates. This helps in managing stock efficiently and presenting accurate stock information to customers on an e-commerce platform.
5. Displaying and explaining prices/bulk prices
Price is a key decision-making factor for customers. The price information for a product is usually available within the price
field of the product
object. This field provides details on both the gross (price without tax) and net (price with tax) values. Fetching price information using the Propeller Commerce GraphQL API gives you the flexibility to show prices with or without taxes, handle bulk pricing, and display any discounts that apply. This ensures that your product detail page can provide clear and accurate pricing information to customers, helping them make informed purchase decisions.
Query example: Fetch product prices
query GetProductPrice($productId: Int, $taxZone: String) {
product(productId: $productId) {
productId
price(input: { taxZone: $taxZone }) {
net
gross
discount {
value
quantityFrom
validFrom
validTo
}
type
}
priceData {
per
cost
list
suggested
store
bulkPriceDiscountType
defaultTaxCode
}
bulkPrices {
gross
net
list
}
}
}
Query breakdown
-
price(input: { taxZone: $taxZone })
: Fetches the price details of the product based on the specifiedtaxZone
.net
: The gross price of the product (including taxes). This is usually the final price the customer will pay in a B2C context.gross
: The net price of the product (excluding taxes). This is typically displayed for B2B or tax-exempt customers.discount
: Provides details about any discounts applied to the product.value
: The discount value applied to the product, which could be an absolute amount or percentage.quantityFrom
: The minimum quantity of the product needed to apply the discount.validFrom
: The start date of the discount validity period.validTo
: The end date of the discount validity period.
type
: Defines the nature of the price, whether it's a regular price, discounted, or a promotional price.
-
priceData
: Provides additional information about the product's various price types and calculations. This allows you to show different types of pricing on the product detail page.per
: The unit of measure for the product (e.g., per item, per kilogram).cost
: Useful for calculating profitability by comparing the cost price with the selling price.list
: The list price of the product, which is often the manufacturer's suggested retail price (MSRP). Help set a reference point for customers, often showing savings when compared to the actual selling price.suggested
: The suggested retail price for the product, usually set by the manufacturer or supplier.store
: Provides flexibility for offering different pricing in physical retail locations compared to online sales.bulkPriceDiscountType
: Specifies the type of discount applied for bulk purchases (e.g., percentage discount, fixed amount).defaultTaxCode
: Ensures correct tax calculations based on the product’s assigned tax code.
-
bulkPrices
: Provides information about the pricing for bulk purchases, including both net and gross prices for bulk quantities.gross
: The gross price for bulk purchases (excluding taxes).net
: The net price for bulk purchases (including taxes).list
: The list price for bulk purchases, which is typically the price before any discounts are applied.
6. Fetching surcharges
Surcharges are additional fees or costs that are added to the base price of a product or service. These charges are often applied for specific reasons, such as shipping, handling, special packaging, environmental fees, or other administrative costs. Surcharges may vary depending on factors like customer location, product type, or shipping method.
In e-commerce, surcharges are a way to pass extra costs directly to the customer, ensuring that the business covers the additional expenses associated with selling or delivering a product. In order to display surcharges on a product page you can modify the product
query.
Query example: Product surcharges
query GetProductSurcharges($productId: Int, $language: String) {
product(productId: $productId, language: $language) {
... on Product {
productId
surcharges {
id
name {
value
language
}
description {
value
language
}
type
value
taxCode
taxZone
enabled
validFrom
validTo
}
}
}
}
Query breakdown
- Surcharge Fields:
id
: Each surcharge is identified by a unique ID, which is useful for tracking or updating the surcharge.name
: This field provides the name of the surcharge in multiple languages, ensuring localized display for international customers.description
: Similar toname
, the description is localized and explains why the surcharge is applied.type
: The type of surcharge (e.g., flatFee or percentage)value
: The amount charged for the surcharge.taxCode
: This field indicates the tax code used for calculating taxes on the surcharge.taxZone
: Specifies the tax zone that applies to the surcharge, ensuring the correct tax rate is applied based on the customer’s location.enabled
: This boolean value allows you to enable or disable surcharges dynamically (e.g., during promotions or sales).validFrom
andvalidTo
: These fields define the time range during which the surcharge is active. If a surcharge is only applicable during certain periods, these dates help manage its availability.
By displaying surcharges clearly on the product detail page, you ensure transparency for the customer while managing extra costs like handling, shipping, or environmental fees. The data is localized, and the surcharge can be dynamically enabled or disabled based on its validity period.
7. Cross-sell and upsell products
Cross-sells typically refer to related or complementary products, while upsells are higher-end or more expensive alternatives. You can fetch these related products or clusters, paginate through them, and display them on your product detail page to offer customers suggestions that encourage further purchases.
To display cross-sell and upsell products in Propeller Commerce, you can utilize specific fields in the product data schema that are associated with related products, accessories, alternatives, etc. You can do this by utilizing the product
query.
Query Example: Handling Product CrossUpsell
query GetCrossUpsell($productId: Int) {
product(productId: $productId) {
crossupsellsFrom(input: { offset: 12, page: 1 }) {
itemsFound
offset
page
start
end
items {
type
productTo {
... on Product {
productId
}
... on Cluster {
clusterId
}
}
}
}
crossupsellsTo(input: { offset: 12, page: 1 }) {
itemsFound
offset
page
start
end
items {
type
productTo {
... on Product {
productId
}
... on Cluster {
clusterId
}
}
}
}
}
}
crossupsellsFrom
: This retrieves all products or clusters that are related to a specific product. These are the products or clusters that you associate with the current product as alternatives, accessories, or other related products.crossupsellsTo
: This works in the reverse direction ofcrossupsellsFrom
. It retrieves products or clusters that have the current product listed as a cross-sell or up-sell. Essentially, these are products that suggest the current item as an alternative or accessory. In other words, other products in the catalog use this product as part of their cross-sell or up-sell recommendations.
You can search both these fields via CrossupsellSearchInput
. For more details check Propeller Commerce API documentation.
8. Displaying bundles
Product bundles are a marketing and sales strategy where multiple products are grouped together and sold as a single package. Bundles often offer a discount compared to buying the individual items separately. They are commonly used in e-commerce to increase average order value by encouraging customers to buy complementary or related products.
In the Propeller Commerce platform, product bundles can be displayed on the product detail page to show customers that they can purchase a set of related items together, sometimes at a lower price than buying each item individually.
To display bundles on the product detail page, you can utilize the product
query.
Query example: Product bundles
query GetProductBundles($productId: Int, $language: String) {
product(productId: $productId, language: $language) {
... on Product {
bundles {
id
name
description
condition
discount
price {
gross
net
originalGross
originalNet
}
items {
isLeader
price {
gross
net
}
product {
class
names(language: $language) {
value
language
}
sku
slugs(language: $language) {
value
language
}
... on Product {
productId
}
}
}
}
}
}
}
Query breakdown
-
Bundle Fields:
id
: Each bundle is identified by a unique ID, which is used to retrieve or display the specific bundle.name
anddescription
: These fields help you display the bundle's title and description on the product page. They inform customers what the bundle is and what it includes.condition
: Useful for adding special rules or conditions that must be met to purchase the bundle (e.g., "Buy 2, Get 1 Free" or "Available for VIP customers only").discount
: If the bundle has a discount, this field represents the discount applied to the bundle.price
: Provides pricing information, including the gross and net prices, as well as the original prices before any discounts.
-
Bundle Item Fields:
isLeader
: Some bundles have a main product that serves as the leader of the bundle (e.g., a laptop in a laptop + accessories bundle). This field helps you highlight the main product.price
: Individual prices for each item in the bundle are provided, allowing you to show the price breakdown for each product included.product
: Contains detailed product information such as the name, SKU, and URL slug for each item in the bundle. This allows you to display each product's name and link to its individual detail page if necessary.
Conclusion
Propeller Commerce's GraphQL API allows full control over the structure of the data returned, empowering developers to create highly customized and dynamic product detail pages.
With the ability to query product data, cross-sells, bundles, surcharges, stock, and prices in one go, Propeller eliminates the need for multiple API calls, enhancing efficiency and performance.
The built-in support for language and tax zones ensures that product information can be localized in real-time.
Whether you're handling complex pricing models, showcasing bundle offers, or managing inventory across multiple locations, Propeller's GraphQL API offers the tools you need to scale your e-commerce platform.
For more information on the GraphQL schema and available queries, visit the Propeller Commerce API documentation.