top of page

How To Create A Custom Product Page For A Specific Product

Oct 26, 2022
3 min read

Who is our client and what problem did they want to solve?


Our client is a large e-commerce client that sells custom leashes for dogs.


They needed a custom product page for a specific product they were selling.


Reasons a custom product page was needed:

  • The product has over 100 variants

  • The variants are determined by 4 different option sets

  • These option sets are managed by 4 different dropdown inputs

  • We needed custom code to ensure all of the selections were functioning correctly


About how the code works:


Whenever an option is selected, the page's code searches through all the product's variants to find one that matches all 4 of the selected choices and once a variant is found, the code updates the price & discounted price information on the page as well as checks the variant for availability to determine whether or not the variant can be added to the user's cart.


If the variant is available for purchase, the "Add to Cart" button is enabled. However, if the variant is not available, the "Add to Cart" button is disabled.


What solution did we provide?


The "Add to Cart" button on the page is just a button element that makes use of the 'wix-stores' cart 'addProducts' function when clicked.


The page also uses the 'wix-stores' product 'getVariants' and product 'getOptionsAvailability' functions to determine which variant the user has selected and whether or not it's available for purchase.




Check out the code we used below:


import { product, cart } from 'wix-stores';
import wixWindow from 'wix-window';
import wixLocation from 'wix-location';
import _ from 'lodash';
import { local } from 'wix-storage';

const PRODUCT_ID = '2cfd98bf-9f8a-aa18-d1f0-cf5972fc2e4d';

$w.onReady(async function () {

    const gclid = local.getItem("GCLID");

    const variants = await product.getVariants(PRODUCT_ID);
    const formFactor = wixWindow.formFactor;

    let quantity = 1;

    $w("#quantity").value = "1";

    const choices = {
        "Color": "",
        "Dog Size": "",
        "Length": "",
        "Matching Collar w/Metal Buckle (+15) Save $10": ""
    }

    let variant = {};

    $w("#length").onChange(async (event) => {
        choices.Length = event.target.value;
        variant = await findVariant(choices);
        console.log(variant);
        if (variant) {
            $w("#price").text = variant.variant.formattedPrice;
            $w("#discountedPrice").text = variant.variant.formattedDiscountedPrice;

            let price2Node = $w("#price2");
            let discountedPrice2Node = $w("#discountedPrice2");
            if (formFactor === 'Mobile') {
                price2Node = $w("#mobileDiscountedPrice");
                discountedPrice2Node = $w("#mobilePrice");
            }
            price2Node.text = variant.variant.formattedPrice;
            discountedPrice2Node.text = variant.variant.formattedDiscountedPrice;
            if (!variant.availableForPurchase) {
                $w("#addToCart").label = "Out of Stock";
                $w("#addToCart").disable();
            } else {
                $w("#addToCart").label = "Add to Cart";
                $w("#addToCart").enable();
            }
        }
    });

    $w("#dogSize").onChange(async (event) => {
        choices["Dog Size"] = event.target.value;
        variant = await findVariant(choices);
        if (variant) {
            $w("#price").text = variant.variant.formattedPrice;
            $w("#discountedPrice").text = variant.variant.formattedDiscountedPrice;
            let price2Node = $w("#price2");
            let discountedPrice2Node = $w("#discountedPrice2");
            if (formFactor === 'Mobile') {
                price2Node = $w("#mobileDiscountedPrice");
                discountedPrice2Node = $w("#mobilePrice");
            }
            price2Node.text = variant.variant.formattedPrice;
            discountedPrice2Node.text = variant.variant.formattedDiscountedPrice;
            if (!variant.availableForPurchase) {
                $w("#addToCart").label = "Out of Stock";
                $w("#addToCart").disable();
            } else {
                $w("#addToCart").label = "Add to Cart";
                $w("#addToCart").enable();
            }
        }
    });

    $w("#color").onChange(async (event) => {
        choices.Color = event.target.value;
        variant = await findVariant(choices);
        if (variant) {
            $w("#price").text = variant.variant.formattedPrice;
            $w("#discountedPrice").text = variant.variant.formattedDiscountedPrice;
            let price2Node = $w("#price2");
            let discountedPrice2Node = $w("#discountedPrice2");
            if (formFactor === 'Mobile') {
                price2Node = $w("#mobileDiscountedPrice");
                discountedPrice2Node = $w("#mobilePrice");
            }
            price2Node.text = variant.variant.formattedPrice;
            discountedPrice2Node.text = variant.variant.formattedDiscountedPrice;
            if (!variant.availableForPurchase) {
                $w("#addToCart").label = "Out of Stock";
                $w("#addToCart").disable();
            } else {
                $w("#addToCart").label = "Add to Cart";
                $w("#addToCart").enable();
            }
        }
    });

    $w('#matchingCollar').onChange(async (event) => {
        choices["Matching Collar w/Metal Buckle (+15) Save $10"] = event.target.value;
        variant = await findVariant(choices);
        if (variant) {
            $w("#price").text = variant.variant.formattedPrice;
            $w("#discountedPrice").text = variant.variant.formattedDiscountedPrice;
            let price2Node = $w("#price2");
            let discountedPrice2Node = $w("#discountedPrice2");
            if (formFactor === 'Mobile') {
                price2Node = $w("#mobileDiscountedPrice");
                discountedPrice2Node = $w("#mobilePrice");
            }
            price2Node.text = variant.variant.formattedPrice;
            discountedPrice2Node.text = variant.variant.formattedDiscountedPrice;
            if (!variant.availableForPurchase) {
                $w("#addToCart").label = "Out of Stock";
                $w("#addToCart").disable();
            } else {
                $w("#addToCart").label = "Add to Cart";
                $w("#addToCart").enable();
            }
        }
    });

    $w("#quantity").onChange(event => {
        quantity = Number(event.target.value);
    })

    $w("#addToCart").onClick(async () => {
        const options = {
            choices
        };
        const addToCart = await cart.addProducts([{ productId: PRODUCT_ID, quantity, options }]).then(updatedCart => updatedCart).catch(err => err);
        if (!gclid) {
            wixLocation.to('/cart');
        }
    })

    async function findVariant(choices) {
        let variant = variants.find(variant => _.isEqual(variant.choices, choices));
        console.log(variant);
        if (variant) {
            const availability = await product.getOptionsAvailability(PRODUCT_ID, choices).then(availability => availability).catch(err => err);
            variant = { ...variant, availableForPurchase: availability.availableForPurchase };
            console.log(variant);
            return variant;
        }
        return variant;


Have questions? We'd love to chat! Contact us at 225-250-1888 or email robert@roberthebertmedia.com.



About our company


RHM specializes in helping businesses of all sizes and across all industries achieve their digital and web marketing needs. Whether designing a new website, building an app, performing custom development, or running Google Ads, our goal is to showcase how you are the best at what you do and help people connect with you. Contact us at 225-250-1888 to get started!





 
 
 

22 Comments


Philipsalt
2 days ago

When talking about any game, I feel that looking only at the final result is not enough. jalwa game login Understanding the gameplay, rules, different situations, and the decisions players make gives a much better overall picture.

Like

Philipsalt
2 days ago

Game-related discussions become much more useful when people talk about their actual experiences instead of only discussing the outcome. tc lottery login Sharing what happened, what was difficult, and what they learned makes the conversation more meaningful.

Like

Khi bài nói về thông tin công khai, mình nghĩ ngay đến việc học sinh cần tự xem kết quả thay vì nhờ người lạ. Đưa số báo danh cho group “hỗ trợ” là rủi ro không đáng. Mình tự tra cứu điểm trên điện thoại, ngồi nơi yên, tắt thông báo cho khỏi bấm nhầm. Đọc hết họ tên, ngày sinh, rồi mới tới cột điểm. Nếu trang yêu cầu mã xác nhận thì điền đúng, không gửi mã cho ai. Xong việc thì đóng tab. Những bước nhàm chán đó lại là phần giữ thông tin cá nhân đứng im.

Like

When I have an important parcel coming, india post tracking helps me stay informed about its movement and gives me a better idea of the delivery progress.

Like

syzoz
Sep 02

Building strength through yoga can be an effective complement to other forms of exercise. Many yoga poses engage different muscle groups while requiring participants to maintain balance and controlled movement. A holistic health center and yoga studio may offer classes that gradually introduce stronger sequences for https://clubhippocrate.ca/ those who want a more active practice. By progressing at an appropriate pace, participants can develop confidence while learning how mindful movement can contribute to an active and balanced lifestyle.

Like
bottom of page