Monday 8 April 2024

OrderCloud .NET SDK logging

Just thought I'd drop a handy little piece of code for when you're running / debugging the OrderCloud .NET SDK locally. If you ever need to see which HTTP calls are being made, and any info about the request URL, body, response, or more importantly errors, you can just add this little snippet to your Program.cs after var app = builder.Build();

Hope this helps someone! Enjoy :)

Friday 22 March 2024

Sitecore GraphQL query - children

I thought I'd put up a friendly reminder for those who know, or some useful information for those who don't: using children in your GraphQL will (by default) only return 10 items, however the children keyword in Sitecore GraphQL is in fact a function! With this information you can find that you can filter and paginate your list of child items.

While the vast majority of examples you find are something like this:

You can actually write it as:

There really don't seem to be that many examples around which use these features of children (though there are many showing similar parameters for search), so hope this helps someone!

Thursday 7 March 2024

OrderCloud Variants Deep-Dive

In this article I'd like to dive a bit deeper into the concept of Variants (and by assocation "Variant" Specs and Spec Options) in OrderCloud. While there is a bit of information around on the web (natually on the OrderCloud website iself) it's all fairly high level and there are a few things I discovered on an implementation recently that I thought were worth sharing.

Let's start with a quick recap of what (Variant) Specs, Spec Options, and Variants are:

  1. Product: Sellable/purchase-able item
    example: shirt, pants
  2. (Variant) Spec: A (re-usable across Products) way of splitting a Product (or multiple products) into different options
    example: Size, Colour
  3. Spec Option: Options a user can select to configure their Product
    example: S / M / L; red / green / blue
  4. Variant: Each variation of a "configurable" Product, generally with its own SKU
    examples: Small green shirt, medium blue shirt; medium green pants, large blue pants, etc.

So as you can probably tell from the examples above, Specs will generally be options which are presented to the user when viewing a specific product, and generally presented in the form of a radio list or dropdown(s); once these have been selected by the user, a specific Variant will be shown/ordered.  

As mentioned in the OrderCloud documentation on Variant Specs, it is worth noting:

Variant specs must be marked as Required as the product object by itself no longer represents a unique product, but as housing for related variant products and cannot be added to an order without specifying a specific variant product.

Selecting Your Specs (and therefore Variants)

You might think, given the example above (size + colour), that it's going to be quite obvious how you will go about splitting your Product into different Variants. Depending on how fleshed-out and/or specific your business requirements are this indeed may be the case, however it is not a guarantee.  An important consideration will be: how many of the available combinations will actually be purchaseable? Will Products actually be available in small, medium, and large for all those colour combinations?  When generating Variants using multiple Specs, on your frontend you will need to handle the dynamic showing and hiding of the different variant dropdown options.  There is also no point in generating a whole bunch of Variants, many of which you will then need to disable.  On that note - per the OrderCloud documentation Generate Variants - this is how you would need to handle any "invalid" Variants (Spec Option combinations):

In some instances, one or more of the generated variants may not represent a valid product. To manage this, any unwanted variants can be patched to have their Active property set to false.

Let me provide a different example than the standard above: what if, instead, your Product is tickets to a show (imagine a touring comedy show) and you need to be able to allow users to select their location and date. Let's say that there will be multiple locations and each location will have multiple dates available (eg. Sydney on 24th and 25th March 2024, Melbourne 15th and 18th April, etc.).  Does it make sense to have Specs/Variants for both Location and date, or does it make more sense to have a combination (location + date, call it "session") and have Sydney 24th, Sydney 25th, Melbourne 15th, etc.? In this case I would argue that it makes no sense to separate the specs into Location and Date, but to group them into a single Variant Spec and a single dropdown on the frontend.  This may, however, depend on into which other systems you are integrating.

Product vs Variant Info

There is an important decision that needs to be made, or at least an important requirement which should be documented before selecting your Specs or generating your Variants: what data needs to live at the Product level vs what data needs to live at the Variant level.  Both Product and Variant (like most OC entities) contain Name, Description, and xp properties allowing you to store information in either entity; in addition to these properties is Price, which is a separate entity. An important thing to note (more on this below) is that there are occasions in which you will need to re-populate a Variant's data.  Since everything in OC is done via API this is not necessarily painful, just something to be aware of.

Also as a part of this exercise it is important to decide / document whether inventory should be tracked at Product or Variant level. If you wish to track inventory at the Variant level, you will simply have to set:

Product.Inventory.VariantLevelTracking = true

As mentioned above, part of the requirements gathering should include documenting which information is common between variantions of a Product, and which data is specific to the Variant.

  • Shared data - which should be assigned to the Product - could include such things as: as a general description of the product, a generic image, weight of an item (if it's the same for all variations), or presenter or duration of a show.  
  • Variable data - which should be assigned to the Variant - could include such things as: a more specific image, measurements of an item of clothing (if Spec is size), venue information for a show (if Spec is location)

It is important to keep in mind: it may seem obvious, but for searching or sorting while retrieving a list of Products, you will need to use Product-level data. This may involve duplication of data, which often feels wrong. So, for example, if you want to show a list of Products on a PLP and allow the user to filter the list on a range of locations or dates (which could be Variant data) or sort by price (which would be in the Price Schedule) you will need to add these to the Product xp which can be used in the query.

Adding and Removing Variants ad-hoc

Continuing with the second Product example above (the touring show with "session" Variants), let's explore how OrderCloud handles the ad-hoc addition and removal of new Spec Options (ie. if shows sell out and so new sessions are added, or old shows are hidden/removed).

  1. First we create our Product (call it "Jason's Australian tour")
  2. Next we add our (Variant) Spec (called "AU tour sessions")
  3. We then add 2x Spec Options to start with:
    1. Sydney 24th March 2024
    2. Melbourne 15th April 2024
  4. We assign our Spec to the Product
  5. Finally, we generate our Variants

The output will be our initial list of 2 sessions which can be purchased.  

GET /me/products/:productID/variants

Because we merged our location and dates together into a single Spec Option, we don't have to remove or disable anything here.  We do, however, need to update the Variant to include Name, Description, and any xp we wish to use.

Next up, let's imagine our tour is doing so well in Sydney that it's sold out and we need more sessions!

  1. Add one more session (Sydney 28th March 2024)
  2. Generate Variants (no "overwrite existing")

Now we have 3 Variants, with no changes to the existing previous 2.

Let's say that it's now after 24th March and we want to stop showing the first option. If you recall above, the correct way to handle this is to set the Active property of the Variant to false. For the purposes of experimentation let's go ahead and totally remove that Spec Option just to see what happens.

  1. Remove Spec Option (Sydney 24th March)
  2. Generate Variants (no "overwrite existing")

Interesting... at this point we still have 3 Variants, but 1 (the removed one) has null data. If you ever find you have a Variant without any Specs in your array, that's probably what's happened (you'll want to regenerate your Variants with "overwrite").  Let's go ahead and try with "overwrite existing".

  1. Generate Variants (with "overwrite existing")

And we're back to the 2 remaining Variants as expected, however with none of the data (Name, Description, xp) present. This highlights one of the challenges of working with Variants, and why we should use the active property instead of removing Spec Options and regenerating Variants.  Also keep in mind that there are other cases where you will need to regenerate Variants, such as changing Spec Option ID, so try to think about your Variants in advance! Rest easy, however, as simply changing some details of a Spec / Spec Option such as Name or Description (or even PriceMarkup) will not mean that you need to regenerate Variants, so no need to stress if you make a typo.

Pricing

Perhaps unfortunately for some (myself included), a Price Schedule can only be assigned at the Product level, and not to a Variant (see my next post on other options which support Price Schedules). There is a workaround, however, in the form of price markup (which includes the fields PriceMarkupType and PriceMarkup). Despite the name, it does not need to be an increase since it can be set to a negative value. One major limitation you should be aware of at this point: price markups do not support multi-currency.

Somewhat unintuitively (at least in my opinion) the price markup can only be set on a Spec Option (which is used to generate the Variant).  It can be retrieved from the Variant under the Specs array property.  Once you get your head around the fact that pricing is set and retrieved at the Spec Option level, it makes sense that when adding a line item to your Order, you must pass the selected Spec Options (and the appropriate Variant is automatically calculated by OrderCloud). 

As the price markup documentation includes some good examples of the various price markup options, let's have a look at what happens if we have a Variant generated from multiple Spec Options and add that as a Line Item to our Order:

  1. Product - Price $10
  2. Spec Option Medium - PriceMarkupType AmountTotal - PriceMarkup 2
  3. Spec Option Black - PriceMarkupType Percentage - PriceMarkup -50
  4. Final line item price: $7

Interestingly this seems to indicate a PriceMarkupType of Percentage is executed first.

Should your requirement to be to handle amounts before percentage, the OrderCloud support team have recommended changing the markup type of Percentage to be an auto-apply line item level promotion. I haven't tried this out, but it seems like a good workaround.

Should you need to change the PriceMarkup on your Spec Options, these are reflected immediately in the Cart (ie unsubmitted Order) but do not affect submitted Orders, as one would expect.

Events

Product Sync is triggered on (at least):

  1. Assigning a Spec to Product
  2. Updating a Spec already assigned to a Product
  3. Generating Variants

if the Product data changes - ie it will not be triggered if your 'generate variants' does not actually overwrite/modify anything. The resulting message contains the data of the updated Product.

You can see a sample of a message below:

Conclusion

(Spec) Variants are a quick and easy way to split your Products - with options that users can choose - into multiple options each with their own SKU.  It's a great option for basic usage, but does have its limitations for more complex scenarios; most notably: there are situations where Variants must be re-generated, meaning they lose their data (which needs to be re-added); pricing is not very easy to work with and does not support multi-currency. You should definitely think through your Spec/Option/Variant strategy as you document business requirements and not leave it to the last minute. 

Alternatives

Stay tuned to my next article where I will discuss other options and how they compare!