Related Products

//-------------Imports-------------//  import wixData from 'wix-data'; import wixLocation from 'wix-location';  //-------------Page Setup-------------//  $w.onReady(async function () {     // Get the current product's data.     let product = await $w('#productPage').getProduct();     // Load the products that are related to the currently displayed product using the loadRelatedProducts() function.     loadRelatedProducts(product);      wixLocation.onChange(async (location) => {         let product = await $w('#productPage').getProduct();         loadRelatedProducts(product);     }); });  // Load the products that are related to the currently displayed product. async function loadRelatedProducts(product) {     // Get the related product results using the relatedProductsByCollection() and relatedProductsByPrice() functions.     let relatedProductResults = await Promise.all([         relatedProductsByCollection(product),         relatedProductsByPrice(product)     ]);      // If there are related products found in the "related-products" collection:     if (relatedProductResults[0].length > 0)         // Show the related products from the collection.         showRelatedProducts(relatedProductResults[0]);     // If there are no related products found in the "related-products" collection:     else         // Fallback to showing the related products by price.         showRelatedProducts(relatedProductResults[1]); }  // Get related products based on the relations set in the "related-products" collection. async function relatedProductsByCollection(product) {     // Get the current product's ID.     let productId = product._id;      // Find related products in the relationship collection by querying for related products in both relation directions.     let relatedByTable = await Promise.all([         wixData.query('related-products')         .eq('productA', productId)         .include('productB')         .find(),         wixData.query('related-products')         .eq('productB', productId)         .include('productA')         .find()     ]);      // Merge related products found from both sides of the relationship collection.     let relatedProducts = [         ...relatedByTable[0].items.map(_ => _.productB),         ...relatedByTable[1].items.map(_ => _.productA)     ];      //Return the related products found in the collection.     return relatedProducts; }  // Get related products based on the the product prices. async function relatedProductsByPrice(product) {     // Get the current product's ID.     let productId = product._id;      // Query the "Products" collection for product's whose price is within 20% of the current product's price.     let relatedByPrice = await wixData.query('Stores/Products')         .between('price', product.price * 0.8, product.price * 1.2)         .ne('_id', productId)         .find();     // Return the related items extracted from the query results.     return relatedByPrice.items; }  // Show the related products on the page. function showRelatedProducts(relatedProducts) {     // If there are any related products:     if (relatedProducts.length > 0) {         // Remove all but the first four related items.         relatedProducts.splice(4, relatedProducts.length);         // Set the function that runs when the related items repeater data is loaded to be relatedItemReady().         $w('#relatedItemsRepeater').onItemReady(relatedItemReady);         // Set the related items repeater data to the first four related items.         $w("#relatedItemsRepeater").data = relatedProducts;         // Expand the related items repeater.         $w("#relatedItems").expand();     }     // If there are no related products:     else {         // Collapse the related items repeater.         $w("#relatedItems").collapse();     } }  // Set up the related items repeater as its data is loaded. function relatedItemReady($item, product) {     // Populate the repeater elements from the item data.     $item("#productImage").src = product.mainMedia;     $item("#productName").text = product.name;     $item("#productPrice").text = product.formattedPrice;     // Set the action that occurs when the image is clicked.     $item('#productImage').onClick(() => {         // Navigate to the related product's product page.         wixLocation.to(product.productPageUrl);     }); }

How We Built It

The Collection We Added: related-products

The related-products collection we added has the following fields:

  • Product A: A reference to a product in the Products collection

  • Product B: A reference to a product in the Products collection

This collection is where we manually created a relationship between products. Each item in the collection represents two items in the Products collection that we decided should relate to each other. Note that a product may appear in both the Product A and Product B fields.

Displaying Related Products

On the Product page, we created the Related Products area in a repeater that is inside a strip. The repeater is set to display a maximum of four items, and each repeated item has elements that display the related product’s image, name, and price.

When the Product page loads, it tries to find related products in the following ways:

  1. It queries both the Product A and Product B fields in the related-products collection to find any products that are related to the current product.

  2. It queries the Products collection for any products whose price is 20% greater or 20% less than the current product.

If either query returns results, it displays those results in the repeater. If no related products are found, the repeater is hidden.