Reaction Commerce is an open-source E-Commerce platform that allows anyone to customize, extend, and deploy an online store or marketplace.

In this article, we will explore the evolution of Product in Reaction from creation to the final order of the product. We will also explore what all phases a product goes through, all its important fields and their significance.

This blog post will not only serve as a guide to Reaction Commerce Products but also can be used as a reference for designing product schema in any E-Commerce application. The schemas and GraphQL APIs mentioned in this blog are referenced from v3.0.0 branch.

Pre-requisites

  • You need to have Reaction installed to be able to actually try and use the Storefront and Admin UI. You can install Reaction using the instructions in reaction-development-platform repo.

  • Operations that we perform from Admin UI and Storefront are because of GraphQL API reaction server provides, so basic understanding of GraphQL would be helpful to follow this blog though not necessary.

Creating a Product

  • When we login to operator/admin UI, we can create a Product from the products page, found inside the navigation.

  • Clicking on the Create Product button takes us to the product creation page.

  • Here we can enter all the details for products and variants to create a product.

  • We need to use createProduct, updateProduct, cloneProducts and archiveProducts mutations to create/update/clone/archive products.

  • To fetch the products, we may use product or products queries.

  • These GraphQL API specifications can be found in product/schema

  • Product schema can be found in product/simpleSchema.

  • Reaction provides some events to allow custom logic to be executed once the product is updated or archived using afterProductUpdate and afterProductSoftDelete appEvents.

  • We will be going through some of the important fields of product schema in the next sections.

Title

  • We need to add a title for a product which could be something like Earphone, SmartWatch.

  • This title is also used to create a product page link on the marketplace. So it would be better to have it unique, so the product page URL is unique(i.e. Permalink).

  • So the title should be the product name along with model and vendor name so its unique as compared to other products.

  • For example, if T-Shirt is our product and Hanes is our vendor then we must identify the product model and make like Hanes Men's Long Sleeve Cool Dry T-Shirt. This will not only make the name unique but also identifiable while searching/browsing.

MetaFields/Metadata

  • On the Product page, we will find another input called Metadata which can be used to store extra product-related information. For T-Shirt we can have metadata field like
    Detail Name: Wash and Detail Information: Dry. It could also be about the type of material.

  • Metadata for the product is saved in the database as MetaFields.

  • This is an array of objects meaning we can have many key-value pairs as Metadata.

  • Its schema is available in product/simpleSchema file.

Variants

  • Variants is the actual sellable item and needs inventory and price tracking.

  • A variant is nothing but an extension of the product. So if we need to find any variant in the database, we must look into the Products collection by its variantId.

  • Also is in the database, if a document is a variant it will be identified by following two fields and its whole schema can be found here.

{
  ...
  _id: "variantId1"
  type: "variant",
  ancestors: ["productId"],
  ...
}
  • While a product document has type simple and its ancestors array is empty.

  • If T-Shirt is a product, then sizes or colors could be its variants. But if we do not want to add any variant to this product, we can let the variant title be empty.

  • We could use logic to display such a product on the marketplace that will not show its variant name or even add a default variant name to all products whose variants need not be shown. This is needed because we cannot have a product without a variant.

  • Also if we have some warehouse management in place, we can use variants ID to track the inventory and price.

  • We can add as many variants to products as needed.

  • There are other important fields like:

    • index: Order in which the variants should be shown on the marketplace products page.

    • minOrderQuantity: Indicates the number of product variants a user can order in order.

    • lowInventoryWarningThreshold: Indicates when the stock should be shown as limited for a product. This flag is used to set isLowQuantity field of variant product to true or false.

  • We need to use createProductVariant, updateProductVariant, cloneProductVariants and archiveProductVariants mutations to create/update/clone/archive product variants.

  • Reaction provides afterVariantUpdate event for variants.

Sub-variants

  • Reaction Commerce allows us to add sub-variants as Options to a variant that can be found at the bottom of the variants page.

  • Like variants, we can have as many options as we like.

  • Sub-variant or Options schema is same as variant. It has its ancestors as its parent variantId.

  • If we have want to add a T-Shirt of color Red and Blue in various sizes, we can use:

const product = {
 ...
 title: "T-Shirt"
 ...
 variants: [
  {
    ...
    label: "Color",
    title: "Red",
    options: [
      {
        ...
        label: "Size",
        title: "Large"
        ...
      },
      {
        ...
        label: "Size",
        title: "Small"
        ...
      }
    ]
  ...
  },
  {
    ...
    label: "Color",
    title: "Blue",
    options: [
      {
        ...
        label: "Size",
        title: "Large"
        ...
      },
      {
        ...
        label: "Size",
        title: "Small"
        ...
      }
    ]
    ...
  },
 ]
}
  • Final Product-Variant-Option structure looks like below:

Product-variant-1

  • Terminal Item could either be a variant or an option of a variant and the user on the marketplace needs to select it to add the product to the cart.

  • Also, terminal items track price and inventory.

  • Sub-variants level nesting is not permitted. However, we can have n number of sub-variants.

  • Hence, we can either have terminal items as variant or sub-variant.

Tags

  • We can add tags to products(not variants or options) to categorize the Product to a particular type, vendor, material or even color so the user can browse all such products using those tags in search or navigation on the marketplace.

  • Tags could be t-shirts, shirts, shorts, shoes, earring or whatever you feel are the main variety of products we intend to sell in our store.

  • On the Products page, we can add tags from the Tags section. When we type any tag name while adding a tag, we get suggestions of existing tags and if there's no tag with the name we type, after hitting the Enter button a new tag gets created by that name.

  • We need to be very careful while tagging our products, as it might give the wrong impression to users.

  • Tag created from the Product page, might not be visible on the marketplace if its Tag is enabled in storefront input is not checked which can be found on the tag edit page.

  • When associating tags with products, one of the important features that a marketplace needs are making some products featured for particular tags.

  • This could be handy in many situations like displaying a few most selling products on the homepage for those categories or even the top brand products. As we cannot show the last n created products for that section, which might lead to fewer product sales or even the wrong impression of our store.

  • Using featuredProducts for a Tag, we want to attract users by showing out top quality or top brand or top-selling products, so the user is at least compelled to open that tags page and see other products listed under that tag.

  • This can be done using the Tag edit page. Go to a particular Tag page and switch to the Products tab on that page. You will see all the products listed for that tag in that section and also the option to assign Priority.

  • When we add a tag to any product, the product hashtags field gets updated with the new tagId and it contains all the tags associated with the product.

const product = {
 ...
 hashtags: [ "tagId1", "tagId2" ],
 ...
}

  • Tag schema can be found in tags/simpleSchema

  • When we assign priority to any product from tags page, tag featuredProductIds field gets updated in priority order.

//when product1 is assigned priority 0 for a tag1, the tag1 looks like below

const tag1 = {
 ...
 featuredProductIds: [ "productId1" ]
 ...
}
  • The productId priority number is nothing but the index/position of productId in featuredProductIds array.

  • We need to use addTag, updateTag, removeTag and setTagHeroMedia mutations for tags.

  • To query tags data we can use tag, tags and productsByTagId queries.

  • These API specifications can be found in Tags GraphQL schema

Publishing a Product(Catalog)

  • When we publish a product, a new document gets added to the Catalog collection. This can be done from the product listing page or from the product page itself.

  • What we see on the marketplace or store is not a product but is a published version of the product i.e a Catalog document. This is added to the cart and can only be ordered from Store.

  • When we make a product hidden and published then the catalog is updated with that flag and the product is not sent in the query response.

  • Catalog schema can be found in catalog/simpleSchema

  • We use catalogItems query to fetch all the catalog items and publishProductsToCatalog mutation to publish any changes to the catalog. These can be found in catalog/schema.

  • When a product is published all its association gets aggregated to form its catalog. Things like media, tags, variants get added as an object into the catalog so that its self contained and has all the required data for the marketplace.

Product-catalog-1

  • If you are implementing search/navigation using ElasticSearch, then Catalog collection is what you will need to index to make the product search by tags, titles, description, price or quantityInStock.

Adding a Product to Cart

  • When a Product gets published, it is available for store visitors to view and order. When a visitor decides to buy a product, visitor will need to add the product to the Cart.

  • When a product gets added to the cart, following two things are checked before adding:

    1. If the productVariant price for an item in the cart is the same as the actual productVariant price.
    2. If the item quantity for the productVariant is less than or equal to minOrderQuantity which we created in product.
  • If the cart item passes the above two checks they get added to the cart else the item is added minOrderQuantityFailures or incorrectPriceFailures array.

  • Code for this can be found in this cart mutation

  • Once the items are added to the cart we then need to set a shipping address for the cart before checkout using setShippingAddressOnCart mutation.

  • At this stage, the product quantity doesn't get updated as the product is still not purchased.

  • ReactionCommerce provides afterCartCreate and afterCartUpdate events for cart, so that we can perform extra operations related to cart in our custom plugin using those events. Its definition is here. We will need to write the logic for this in startup.js with appEvents.on("afterCartCreate", callback).

Ordering a Product

  • After adding product to cart, the user can proceed to the checkout page and select all the required information like shipping address, payment method and finish the checkout to create the final Order.

  • When an order gets created the product inventory count gets updated, to reflect the ordered product quantity in total stock.

  • After the cart gets created we need to:

    • set shipping address for the cart using setShippingAddressOnCart mutation.
    • set fulfillment option for the cart using selectFulfillmentOptionForGroup mutation.
  • After the above steps, we will need to select the payment method to place the order using placeOrder mutation.

  • Then the order email gets sent and product stock quantity gets updated.

  • The order/simpleSchema provides the schema for order.

  • Events related to order are afterOrderUpdate, afterOrderCancel, afterOrderCreate, afterOrderPaymentCapture, afterOrderApprovePayment which provide emit events related to order.

I hope this blog gave you a basic understanding of all the phases a product goes through and also the APIs which get used in each phase. You can explore more on ReactionCommerce official docs or on github.

Thanks for reading.

Edit: Updated the reaction repo github links