Custom Ecommerce Product Page
- Apr 2, 2024
- 3 min read
In this series, we invited Eitan from the Wix Wiz YouTube channel, who is a master at Velo, to code a custom ecommerce product page. Below you will find all of the videos and code used for this series:

import { getProductVariants } from "backend/store";
import { cart } from "wix-stores-frontend";
import wixData from "wix-data";
import wixLocationFrontend from "wix-location-frontend";
let product;
let selectedOptions = {};
$w.onReady(function () {
populateProductData();
populateMediaItems();
populateOptions();
populateTestimonial();
populateProductFeatures();
$w("#addToCartButton").onClick(async () => {
$w("#addToCartButton").disable();
try {
const productInfo = {
productId: product._id,
quantity: Number($w("#quantityInput").value),
options: {
choices: selectedOptions,
},
};
const updatedCart = await cart.addProducts([productInfo]);
wixLocationFrontend.to("/cart-page");
// cart.showMiniCart();
// setTimeout(()=>{
// cart.hideMiniCart();
// }, 2000)
console.log("updated cart", updatedCart);
} catch (error) {
console.log(error);
$w("#addToCartButton").enable();
}
});
});
function populateOptions() {
const { productOptions } = product;
const optionKeys = Object.keys(productOptions); // [Size, Scent];
let options = optionKeys.map((option) => productOptions[option]);
console.log("options", options);
if (optionKeys.includes("Size")) {
const sizeOption = productOptions["Size"];
options = options.filter((option) => option.name !== "Size");
$w("#optionsSelectionTags").options = sizeOption.choices.map((choice) => ({
label: choice.description,
value: choice.description,
}));
$w("#optionsSelectionTags").onChange((event) => {
const currentSelection =
event.target.value[event.target.value.length - 1];
$w("#optionsSelectionTags").value = [currentSelection];
selectedOptions["Size"] = currentSelection;
updateProductPageWithOptions();
});
$w("#optionsSelectionTags").expand();
}
$w("#dropdownOptionsRepeater").onItemReady(($item, itemData) => {
$item("#optionDropdown").label = itemData.name;
$item("#optionDropdown").options = itemData.choices.map((choice) => ({
label: choice.description,
value: choice.description,
}));
$item("#optionDropdown").onChange((event) => {
selectedOptions[itemData.name] = event.target.value;
updateProductPageWithOptions();
});
});
$w("#dropdownOptionsRepeater").data = options.map((option) => ({
...option,
_id: option.name,
}));
}
async function updateProductPageWithOptions() {
console.log(selectedOptions);
const color = selectedOptions["Color"];
if (color) {
const colorOption = product.productOptions["Color"];
console.log("colorOption", colorOption);
const slectedChoice = colorOption.choices.filter(
(choice) => choice.description === color
)[0];
console.log("selectedChoice", slectedChoice);
$w("#mainMedia").src = slectedChoice.mainMedia;
}
// get a variant based on the options;
const variants = await getProductVariants(product._id, {
choices: selectedOptions,
});
console.log("variants", variants);
if (variants.length > 1) return;
const { variant } = variants[0];
$w("#originalPrice").text = variant.formattedPrice;
$w("#discountedPrice").text = variant.formattedDiscountedPrice;
$w("#productSKU").text = variant.sku;
// display mainMedia if relevant
}
function populateMediaItems() {
const { mainMedia, mediaItems } = product;
$w("#mainMedia").src = mainMedia;
$w("#mediaItemsRepeater").onItemReady(($item, itemData) => {
$item("#mediaItem").src = itemData.src;
if (itemData.src === mainMedia) {
$item("#mediaItemWrapper").style.borderColor = "blue";
}
$item("#mediaItem").onClick(() => {
$w("#mainMedia").src = itemData.src;
$w("#mediaItemWrapper").style.borderColor = "#F5E47E";
$item("#mediaItemWrapper").style.borderColor = "blue";
});
});
$w("#mediaItemsRepeater").data = mediaItems
.filter((item) => !item.src.includes("wix:video://"))
.map((item, index) => ({ ...item, _id: index.toString() }));
}
function populateProductData() {
product = $w("#productsDataset").getCurrentItem();
console.log(product);
$w("#productName").text = product.name;
if (product.price === product.discountedPrice) {
$w("#originalPrice").hide();
}
$w("#originalPrice").text = product.formattedPrice;
$w("#discountedPrice").text = product.formattedDiscountedPrice;
if (!product.ribbon) {
$w("#ribbonWrapper").hide();
}
$w("#ribbon").text = product.ribbon;
$w("#productSKU").text = product.sku;
}
async function populateTestimonial() {
const productId = product._id;
const additionalInfoQueryResult = await wixData
.query("ProductAdditionalInfo")
.hasSome("product", productId)
.find();
const additionalInfo = additionalInfoQueryResult.items[0];
console.log("additionalInfo", additionalInfo);
$w("#testimonialText").text = additionalInfo.testimonial;
$w("#testimonialGiverText").text = additionalInfo.name;
}
async function populateProductFeatures() {
const productId = product._id;
const featuresQueryResult = await wixData
.query("ProductFeatureTest")
.hasSome("product", productId)
.find();
const features = featuresQueryResult.items;
$w("#productFeaturesRepeater").onItemReady(($item, itemData) => {
$item("#productFeatureTitle").text = itemData.title;
$item("#productFeatureText").text = itemData.description;
$item("#productFeatureIcon").src = itemData.icon;
});
$w("#productFeaturesRepeater").data = features;
}
/*
{
{
"seoData": "null",
"inStock": true,
"weight": 0.4,
"name": "Product 3 - Body Spray",
"sku": "003",
"formattedDiscountedPrice": "$6.99",
"productOptions": {
"Size": {
"optionType": "drop_down",
"name": "Size",
"choices": [
{
"inStock": true,
"visible": true,
"mainMedia": "null",
"description": "12oz",
"mediaItems": [],
"value": "12oz"
},
{
"inStock": true,
"visible": true,
"mainMedia": "null",
"description": "6oz",
"mediaItems": [],
"value": "6oz"
},
{
"inStock": true,
"visible": true,
"mainMedia": "null",
"description": "8oz",
"mediaItems": [],
"value": "8oz"
}
]
},
"Scent": {
"optionType": "drop_down",
"name": "Scent",
"choices": [
{
"inStock": true,
"visible": true,
"mainMedia": "null",
"description": "Lavender",
"mediaItems": [],
"value": "Lavender"
},
{
"inStock": true,
"visible": true,
"mainMedia": "null",
"description": "Sunrise",
"mediaItems": [],
"value": "Sunrise"
},
{
"inStock": true,
"visible": true,
"mainMedia": "null",
"description": "Vanilla",
"mediaItems": [],
"value": "Vanilla"
}
]
}
},
"mainMedia": "wix:image://v1/df045c_b739f2e9ed5c4541b97046a07b9420c2~mv2.png/file.png#originWidth=576&originHeight=576",
"description": "Introducing our organic mist fragrance, the perfect addition to your daily beauty routine. Made with all-natural ingredients, this mist will leave you feeling refreshed and rejuvenated. Our unique blend of essential oils and botanical extracts will invigorate your senses and uplift your mood. This mist can be used as a face toner, body mist, or room spray, making it a versatile must-have. Treat yourself to a little luxury with our organic mist fragrance.",
"_id": "dea50d8e-b999-3024-862e-b09644ef0c66",
"discountedPrice": 6.99,
"link-products-slug": "/products/product-3",
"formattedPrice": "$6.99",
"price": 6.99,
"quantityInStock": 64,
"collections": "null",
"inventoryItem": "215af271-4666-cfdb-79d1-4f69bb10f399",
"_updatedDate": "Tue Jan 09 2024 14:10:04 GMT+0900 (Japan Standard Time)",
"formattedPricePerUnit": "null",
"slug": "product-3",
"productType": "physical",
"brand": "null",
"ribbons": [],
"pricePerUnitData": "null",
"mediaItems": [
{
"description": "",
"id": "df045c_b739f2e9ed5c4541b97046a07b9420c2~mv2.png",
"link": "null",
"src": "wix:image://v1/df045c_b739f2e9ed5c4541b97046a07b9420c2~mv2.png/file.png#originWidth=576&originHeight=576",
"title": "Product-3.png",
"type": "Image"
}
],
"trackInventory": true,
"customTextFields": [],
"pricePerUnit": "null",
"ribbon": "",
"currency": "USD",
"productPageUrl": "/product-page/product-3",
"numericId": "1694026398898000",
"manageVariants": false,
"discount": {
"type": "NONE",
"value": 0
},
"additionalInfoSections": [],
"createdDate": "Thu Sep 07 2023 03:53:18 GMT+0900 (Japan Standard Time)"
}
*/
Hope this series helped you create your own custom ecommerce page! Enjoy!




Comments