Building a Product Details Page

For this recipe, knowledge of how the flex-layout works is required. If you have any doubts regarding this, we strongly recommend you access this documentation.

Introduction

Your store's Product Page can be customized by simply changing the store.product block in your store-theme source code. The store.product is a block with child dependencies, which means it consists of other blocks. Since it is flexible, its child blocks can be declared using flex-layout to easily build a responsive page.

The store.product accepts all blocks allowed by the store and flex-layout blocks as child dependencies, as well as the following blocks list:

"product-add-to-list-button"
"product-details"
"product-kit"
"product-reviews"
"product-questions-and-answers"
"product-rating-summary"
"product-rating-inline"
"product-images"
"product-brand"
"product-name"
"product-price"
"sku-selector"
"buy-button"
"product-separator"
"product-description"
"product-specifications"
"product-quantity"
"breadcrumb"
"shipping-simulator"
"availability-subscriber"
"share"
"product-highlights"
"product-availability"
"product-identifier"
"blog-related-posts"
"product-assembly-options"
"product-teaser.product"
You can always check out the full and updated list here.

Practical example

Let's take a look at our demo store, Storetheme. It has a good example of how to use the store.product flexible block:

storetheme-product-details-page

Its definition is as follows:

{
  "store.product": {
    "children": [
      "flex-layout.row#product-breadcrumb",
      "flex-layout.row#product-main",
      "shelf.relatedProducts"
    ]
  },
  "flex-layout.row#product-breadcrumb": {
    "props": {
      "marginTop": 4
    },
    "children": ["breadcrumb"]
  },
  "flex-layout.row#product-main": {
    "props": {
      "colGap": 7,
      "rowGap": 7,
      "marginTop": 4,
      "marginBottom": 7,
      "paddingTop": 7,
      "paddingBottom": 7
    },
    "children": ["flex-layout.col#product-image", "flex-layout.col#right-col"]
  },
  "flex-layout.col#product-image": {
    "props": {
      "width": "60%",
      "rowGap": 0
    },
    "children": ["product-images"]
  },
  "product-images": {
    "props": {
      "displayThumbnailsArrows": true
    }
  },
  "flex-layout.col#right-col": {
    "props": {
      "preventVerticalStretch": true,
      "rowGap": 0
    },
    "children": [
      "product-name",
      "product-rating-summary",
      "product-price#product-details",
      "product-separator",
      "product-quantity",
      "product-identifier.product",
      "sku-selector",
      "flex-layout.row#buy-button",
      "availability-subscriber",
      "shipping-simulator",
      "share#default"
    ]
  },
  "product-price#product-details": {
    "props": {
      "showInstallments": true,
      "showSavings": true
    }
  },
  "flex-layout.row#buy-button": {
    "props": {
      "marginTop": 4,
      "marginBottom": 7
    },
    "children": ["buy-button"]
  },

  "share#default": {
    "props": {
      "social": {
        "Facebook": true,
        "WhatsApp": true,
        "Twitter": false,
        "Pinterest": true
      }
    }
  }
}

As you can see, the store.product child dependencies define 5 blocks, the first two being flex-layout.row.

The first row is only declaring the breadcrumb and you can see it here:

"flex-layout.row#product-breadcrumb": {
    "props": {
      "marginTop": 4
    },
    "children": ["breadcrumb"]
  },

Notice that above that it sets out to render the breadcrumb block through its child array. If you want to customize the breadcrumb, with changes to its props, you can declare the breadcrumb block and define it according to your goal. For instance:

"breadcrumb": {
    "props": {
        "showOnMobile": true
    }
}

The second row is the one showing the image, while the right column displays name, price, sku selector, button, etc. as shown below:

 "flex-layout.row#product-main": {
    "props": {
      "colGap": 7,
      "rowGap": 7,
      "marginTop": 4,
      "marginBottom": 7,
      "paddingTop": 7,
      "paddingBottom": 7
    },
    "children": ["flex-layout.col#product-image", "flex-layout.col#right-col"]
  },

Notice that the second row defines two columns, flex-layout.col#product-image and flex-layout.col#right-col:

"flex-layout.col#product-image": {
    "props": {
      "width": "60%",
      "rowGap": 0
    },
    "children": ["product-images"]
  },
  "product-images": {
    "props": {
      "displayThumbnailsArrows": true
    }
  },
  "flex-layout.col#right-col": {
    "props": {
      "preventVerticalStretch": true,
      "rowGap": 0
    },
    "children": [
      "product-name",
      "product-price#product-details",
      "product-separator",
      "product-quantity",
      "product-identifier.product",
      "sku-selector",
      "flex-layout.row#buy-button",
      "shipping-simulator",
      "share#default"
    ]
  },

Product images

The left column is the one with the product-images since it was the first one to be declared.

.

As you can see from the rendering, the right column has many child dependencies:

storetheme-product-details-page

Product name

It starts with a product-name, used to display the product name, along with its SKU name, if desired.

productdetailspage-productname

Product price

Right below it, we can find the product-price displaying a properly formatted selling price. You can set it to show the list price (if it's different), installments, etc. Check out below an example of a Product Price displaying both the sale and the list price:

productdetailspage-productprice

Below the Product Price we have the product-separator, a block that just draws a line in your Product Page.

Product quantity

Then, we have the product-quantity. With this block, you can let users choose how many items are added to the cart.

productdetailspage-productquantity

Product Identifier

Scrolling down, below the Product Quantity component, we arrive at the product-identifier. This component allows you to show the user the product identifier.

productdetailspage-productidentifier

You can then customize it with different props, choosing the label you want before/in front of the identifier, the display mode and more.

SKU Selector

We then have a really important component: the SKU Selector. It allows the user to choose his desired SKU, automatically hiding impossible combinations or indicating combinations that are currently unavailable.

productdetailspage-skuselector

Buy button

The buy-button is the classic component that adds a SKU to the cart. You can customize it to show a successful message, to redirect the user to the Cart page immediately, etc.

productdetailspage-buybutton

Shipping simulator

Your store can also have a shipping-simulator. It allows users to fill in their postal code to then display the available shipping options and their respective prices for that cart.

productdetailspage-shippingsimulator

Share

Finally, we have the share component, which allows product sharing on social media.

productdetailspage-share

By customizing its props, you can control which options will be shown to the user:

"share#default": {
    "props": {
      "social": {
        "Facebook": true,
        "WhatsApp": true,
        "Twitter": false,
        "Pinterest": true
      }
    }
  }

Notice that in this block we are hiding the Twitter option from our sharing list. The available social media platforms for now are: Facebook,Twitter,Telegram,WhatsApp,Google+,Pinterest and E-mail.

After this right column is done, we start to render the blocks defined under them in our store.product block.

The Related Products Shelf (shelf.relatedProducts) is a Shelf component that displays products related to the one you are browsing.

The related products displayed in a product page can be defined through your store's admin Catalog. As you can see above, the product we are using as example does not have any. But it should look exactly like this:

The shelf.relatedProducts block lets you choose between different recommendation types. The recommendation property can be one of the following values: ['similars', 'view', 'buy', 'accessories', 'viewAndBought', 'suggestions'].

Here is a brief example of a Related Products Shelf:

"shelf.relatedProducts": {
    "props": {
        "recommendation": "view",
        "productList": {
            "titleText": "Who saw also saw",
            "itemsPerPage": 3
        }
    }
}

Mobile

Keep in mind that the flex-layout may suffer modifications if you are on mobile mode. You can check out the Flex Layout recipe for more information.

Edit this page on GitHub