Velo Tutorial: Adding a Related Products Area to a Wix Store Product Page

Visit the Velo by Wix website to onboard and continue learning.
This article describes how you can use Velo to add a Related Products area to a Wix Stores Product page. Throughout this article, we're going to use this site to illustrate the process. You can open the site in the Editor to work with the template. We're going to explain what we did in the sample site, the code we added to make it work, and give you guidance on how you can modify each step to do something similar on your site.

Overview

In our example we add a repeater inside a strip that we add to the Stores Product page. This serves as the Related Products area. We define related products in two ways:
  1. Products that we manually define as relating to the current product. We create that relationship in a relatedProducts collection.
  2. Products whose price is 20% greater or 20% less than the current product.
The code then follows the following logic:
  1. Get the ID of the currently displayed product.
  2. Query the relatedProducts collection and return the products that we defined manually as relating to the currently displayed product. 
  3. Query the Products collection for items whose price falls within a specific range, relative to the current item's price. 
  4. Add the results of both queries into an array.
  5. First try to display the products that we defined manually as relating to the currently displayed product. If there are none, then display the items whose price falls within a specific range. Display a maximum of four related items.
  6. If neither query returns results, hide the repeater.

Step 1: Site Setup

To recreate this functionality you'll need to have Wix Stores added to your site with some products. Once you add Stores to your site, you'll see pages (by clicking on Page Code in the Velo Sidebar) and collections (by clicking on Databases in the Velo Sidebar) automatically added to your site.
Note
You may need to save or publish the site and refresh your browser to view the Stores collections in the Databases.

Database Setup

This is what some of the data in our site looks like:
In our example we don't work with the Collections collection, although it is in our sample site's store. 

The relatedProducts collection has two fields: Product A and Product B, which are both reference fields. For each item, Product A values reference an item in the Products collection. Product B values then reference the product related to the item in Product A. Note that a product may appear in both the Product A or Product B fields. Note also that the field keys for the two fields are productA and productB.

This is what the relatedProducts collection looks like:
You can see a copy of the data from the Collections, Products, and relatedProducts collections here. The Products and Collections collections are created automatically when you have a site with Wix Stores. Because these collections are read-only, you must use the Store Manager to create your product list. 
In our example we use a repeater inside a strip as the Related Products area, and we set up the page with the following IDs. 

Step 3: Create the loadRelatedProducts Function

loadRelatedProducts is called from onReady. It gets the current product from the product page and passes that to the functions that find the related products. It then calls the functions to display the results.

Note:
Throughout this example we use the new async/await JavaScript functionality.
1import wixData from 'wix-data';
2import wixLocation from 'wix-location';
3
4$w.onReady(function () {
5    loadRelatedProducts();
6});
7
8async function loadRelatedProducts() {
9    let product = await $w('#productPage').getProduct();
10    let relatedProductResults = await Promise.all([
11        relatedProductsByTable(product),
12        relatedProductsByPrice(product)
13    ]);
14
15    if (relatedProductResults[0].length > 0)
16        showRelatedProducts(relatedProductResults[0]);
17    else
18        showRelatedProducts(relatedProductResults[1]);
19};

Understanding the Code

Line 1-2: Import the modules we need to work with Wix Data and Wix Location libraries.
Lines 4-5: Call loadRelatedProducts inside the page's onReady function. loadRelatedProducts calls the functions that run the related product queries. It then calls the function to display the query results.
Note that we don't return the loadRelatedProducts result promise from $w.onReady. If we return a promise from $w.onReady, it will delay the page load until the promise is resolved. By not returning the promise, we allow the page to load as fast as possible while the related products load in the background.
Line 9: Get the current product from the Product page.
Lines 10-12: Create the relatedProductResults array from the results of the relatedProductsByTable and relatedProductsByPrice functions. Each of these functions accepts the current product as a parameter and returns an array of related products.
Lines 15-18: If the relatedProductResults isn't empty, then first try to display the results of relatedProductsByTable. If there are none, display the results of relatedProductsByPrice.

Identifiers you may need to change based on your site's elements

If you want to use this exact scenario and code in your site, you may need to modify these items to match the ones on your site:
  • productPage

Step 4: Create the relatedProductsByTable Function

relatedproductsByTable finds all the products that relate to the current product, based on the relationships defined in the relatedProducts collection.

1async function relatedProductsByTable(product) {
2    let productId = product._id;
3
4    // find related products by relation table
5    let relatedByTable = await Promise.all([
6        wixData.query('relatedProducts')
7        .eq('productA', productId)
8        .include('productB')
9        .find(),
10        wixData.query('relatedProducts')
11        .eq('productB', productId)
12        .include('productA')
13        .find()
14    ]);
15
16    let relatedProducts = [
17        ...relatedByTable[0].items.map(_ => _.productB),
18        ...relatedByTable[1].items.map(_ => _.productA)
19    ];
20    return relatedProducts;
21};

Understanding the Code

Lines 5-14: Run two parallel queries on the relatedProducts collection. Each query returns the value in the productA or productB fields that relate to the currently displayed product. Use .include to include all the data from the referenced field for the related product.
Lines 16-19: Use the spread operator and map function to build an array of related products from both fields. The spread operator flattens the results of both queries into one array. The map function extracts only the related product from the item object of the query results while removing the current product.
Note that the _ is a variable that represents the current element being processed in the array.

Items you may need to change based on your site's collections

If you want to use this exact scenario and code in your site, you may need to modify these items to match the ones on your site:
  • relatedProducts
  • productA
  • productB

Step 5: Create the relatedProductsByPrice Function

relatedproductsByPrice finds all the products that relate to the current product, based on a price range.

1async function relatedProductsByPrice(product) {
2    let productId = product._id;
3
4    // find related products by price
5    let relatedByPrice = await wixData.query('Stores/Products')
6        .between('price', product.price * 0.8, product.price * 1.2)
7        .ne('_id', productId)
8        .find();
9    return relatedByPrice.items;
10};

Understanding the Code

Lines 5-8: Run a query on the Products collection for any products whose price is within 20% of the price of the currently displayed product. Use .ne to exclude the current product from the results.
Line 9: Return the .items object of the query results.

Step 6: Create the showRelatedProducts Function

showrelatedProducts accepts the results of relatedProductsByTable or relatedProductsByPrice and truncates the results so only a maximum of four items are displayed. It then sets the onItemReady function for the repeater, defines the repeater data, and decide whether to hide or display the repeater.

1function showRelatedProducts(relatedProducts) {
2    if (relatedProducts.length > 0) {
3        relatedProducts.splice(4, relatedProducts.length);
4        $w('#relatedItemsRepeater').onItemReady(relatedItemReady);
5        $w("#relatedItemsRepeater").data = relatedProducts;
6        $w("#relatedItems").expand();
7    } else {
8        $w("#relatedItems").collapse();
9    }
10};

Understanding the Code

Line 2: Check if relatedProducts contains data. If it does, run lines 3-6.
Line 3: Remove all but the first four results from relatedProducts.
Line 4: Set the onItemReady function for the repeater to relatedItemReady. We'll define that function in the next step.
Line 5: Set the data property for the repeater.
Line 6: Expand the repeater.
Line 7-8: If the relatedProducts does not contains data, collapse it.

Identifiers you may need to change based on your site's elements

If you want to use this exact scenario and code in your site, you may need to modify these items to match the ones on your site:
  • relatedItemsRepeater
  • relatedItems

Step 7: Create the relatedItemReady Function

relatedItemReady is the onItemReady function for the repeater. It's the function that runs when a new repeated item is created.

1function relatedItemReady($w, product) {
2    $w("#productImage").src = product.mainMedia;
3    $w("#productName").text = product.name;
4    $w("#productPrice").text = product.formattedPrice;
5    $w('#productImage').onClick(() => {
6        wixLocation.to(product.productPageUrl);
7    });
8};

Understanding the Code

Lines 2-4: Bind each element in the repeater to the corresponding data for the product.
Lines 5-6: Set the onClick property of the productImage element to open the product page for the specific product.

Identifiers you may need to change based on your site's elements

If you want to use this exact scenario and code in your site, you may need to modify these items to match the ones on your site:
  • productImage
  • productName
  • productPrice
  • productImage

Next Steps

Did this help?

|
Hire a Velo Web Developer
Need a little extra help with your site? Hire a developer from the Wix Marketplace to build and deploy advanced web applications.
Get Started