Developer forum

Forum » Ecommerce - Standard features » Optimizing cart feed JSON using CartViewModel

Optimizing cart feed JSON using CartViewModel

Adrian Ursu Dynamicweb Employee
Adrian Ursu
Reply

Hi guys,

I am trying to optimize the performance for large carts by switching from a regular Cart module for CartOrderlineFeeds to a template using CartViewModel.

In this process, I have noticed that the CartViewMOdel is a bit limited in terms of the properties available. 

I am wondering what is the best way to access OrderFields and OrderLineFields as well as other properties like Taxes and Customer Comment.

Does anybody have a suggestion for a good/performant approach?

I am using DW 9.10.13

Thank you,

Adrian


Replies

 
Nicolai Pedersen
Reply

CartViewmodel is part of Dynamicweb frontend name space and the pageview viewmodel - used for minicarts.

If you want full blown cart in json, you should use the cart or orders endpoint of the webapi - that will give you an OrderViewmodel which has i.e. custom order fields.

See: https://doc.dynamicweb.com/api/html/2b7ce250-5717-9ef7-d73f-0ebece363e8a.htm

You can see an example from the Swift: 

http://r4.master.public2.dynamicweb.dk/dwapi/ecommerce/carts/ced5bab913af496688e8df53c19d5278

Response will look like this:

{
  "Id": "string",
  "Secret": "string",
  "ShopId": "string",
  "DisplayName": "string",
  "VoucherCode": "string",
  "Weight": 0,
  "Volume": 0,
  "CreatedAt": "2021-11-04T12:39:20.679Z",
  "Modified": "2021-11-04T12:39:20.679Z",
  "CompletedDate": "2021-11-04T12:39:20.679Z",
  "Completed": true,
  "StateId": "string",
  "StateName": "string",
  "StateDescription": "string",
  "IntegrationOrderId": "string",
  "RecurringOrderId": 0,
  "CustomerUserId": 0,
  "CustomerNumber": "string",
  "CustomerEan": "string",
  "CustomerRefId": "string",
  "CustomerCompany": "string",
  "CustomerTitle": "string",
  "CustomerName": "string",
  "CustomerFirstName": "string",
  "CustomerSurname": "string",
  "CustomerMiddleName": "string",
  "CustomerHouseNumber": "string",
  "CustomerInitials": "string",
  "CustomerPrefix": "string",
  "CustomerAddress": "string",
  "CustomerAddress2": "string",
  "CustomerZip": "string",
  "CustomerCity": "string",
  "CustomerCountry": "string",
  "CustomerCountryCode": "string",
  "CustomerRegion": "string",
  "CustomerPhone": "string",
  "CustomerEmail": "string",
  "CustomerCell": "string",
  "CustomerAccepted": true,
  "DeliveryCompany": "string",
  "DeliveryName": "string",
  "DeliveryFirstName": "string",
  "DeliverySurname": "string",
  "DeliveryMiddleName": "string",
  "DeliveryTitle": "string",
  "DeliveryHouseNumber": "string",
  "DeliveryInitials": "string",
  "DeliveryPrefix": "string",
  "DeliveryAddress": "string",
  "DeliveryAddress2": "string",
  "DeliveryZip": "string",
  "DeliveryCity": "string",
  "DeliveryCountry": "string",
  "DeliveryCountryCode": "string",
  "DeliveryRegion": "string",
  "DeliveryPhone": "string",
  "DeliveryEmail": "string",
  "DeliveryCell": "string",
  "NewsletterSubscribe": true,
  "TransactionCardnumber": "string",
  "TransactionCardType": "string",
  "TransactionNumber": "string",
  "TransactionStatus": "string",
  "ShippingDate": "2021-11-04T12:39:20.679Z",
  "OrderLines": [
    {
      "Id": "string",
      "ProductId": "string",
      "ProductVariantId": "string",
      "ProductLanguageId": "string",
      "ProductName": "string",
      "ProductNumber": "string",
      "ProductVariantName": "string",
      "ProductImage": "string",
      "Reference": "string",
      "Quantity": 0,
      "Weight": 0,
      "Volume": 0,
      "UnitId": "string",
      "StockLocationId": 0,
      "OrderLineType": "Product",
      "OrderLineFields": {
        "additionalProp1": {
          "SystemName": "string",
          "Name": "string",
          "Type": "string",
          "ListType": 0
        },
        "additionalProp2": {
          "SystemName": "string",
          "Name": "string",
          "Type": "string",
          "ListType": 0
        },
        "additionalProp3": {
          "SystemName": "string",
          "Name": "string",
          "Type": "string",
          "ListType": 0
        }
      }
    }
  ],
  "OrderFields": {
    "additionalProp1": {
      "SystemName": "string",
      "Name": "string",
      "Type": "string",
      "ListType": 0
    },
    "additionalProp2": {
      "SystemName": "string",
      "Name": "string",
      "Type": "string",
      "ListType": 0
    },
    "additionalProp3": {
      "SystemName": "string",
      "Name": "string",
      "Type": "string",
      "ListType": 0
    }
  }
}
 
Nicolai Pedersen
Reply

Oh, that webapi cal requires that the user is logged in...

 
Adrian Ursu Dynamicweb Employee
Adrian Ursu
Reply

Hi Nicolai,

Thank you for the suggestion.

In my case, I might be able to use it since it's mainly a B2B scenario. But I will have to check if that's accurate.

What are my options in case I cannot use it?

Thank you,

Adrian

 
Nicolai Pedersen
Reply

You can create the viewmodel by code:

var request = new OrderViewModelSettings();
            request.EnsureFilledPropertiesExist();
            request.FilledProperties = new[] { "CreatedAt", "DeliveryEmail", "OrderLines" };
            request.OrderLineSettings.FilledProperties = new[] { "ProductName", "Quantity", "Price" };
            request.OrderLineSettings.PriceSettings.FilledProperties = new[] { "CurrencyCode", "PriceWithVatFormatted", "PriceWithoutVatFormatted" };
            var order = Services.Orders.GetBySecret(secret);
            var model = ViewModelFactory.CreateView(request, order);

The OrderViewModelSettings controls stuff like currency. See the API docs: https://doc.dynamicweb.com/api/html/d9697605-f18f-ae8d-1e1f-89e80f1e6baa.htm

By using the FilledProperties property on the OrderViewModelSettings and underlying settings objects you can control what properties should be filled on the viewmodel and its subviewmodels.

 
Nicolai Pedersen
Reply

But let me know if webapi could be a way to go. Then we can make changes so you can use that instead.

It also has a full cart API so you can add, remove and change orderlines, update the cart info, add vouchers and other funny stuff.

 
Adrian Ursu Dynamicweb Employee
Adrian Ursu
Reply

Hi Nicolai,

Thank you very much for the info. I need to analyze it before I can provide an answer.
Our use case is a cart with +200 orderlines. For these cases (which seem to be very usual for the webshop) the loading of the page is very slow.

It is a good candidate for this type of optimization.

We have started with Rapido and added a lot of customizations for the checkout process and I need to first review all customizations in order to identify potential issues with the refactoring.

Thank you very much.


Adrian

 
Nuno Aguiar Dynamicweb Employee
Nuno Aguiar
Reply

Hi Adrian,

 

We going through a similar process (+400 orderlines in some cases), and managed to add to cart in about 15secs with +200 orderlines (having spent 4sec going to the ERP and back to get live prices in chunks of 50 SKUs - this was custom though).

 

 

If you have Live Integration, I can bet there's 1 or 2 things you'll need (we had to do that too) but the main thing is adding to the cart using addmulti (not the reorder from order history).

 

What problems in particular are you experiencing?

 

Nuno

 
Adrian Ursu Dynamicweb Employee
Adrian Ursu
Reply

Hi Nuno,

Thank you for the feedback.

I hear you. We have investigated the LiveIntegration part and Emil has changed the way we retrieve prices and we have a bulk request of prices + some caching of the values. That part is probably optimized to the max.

We are now trying to optimize the loading of the minicart in the front-end. Since we have started with Rapido, the minicart is loaded with Handlebars based on the JSON feed with minicart orderlines. And just the JSON itself takes about 12-15 seconds. And this load time also affects adding to the cart, as you correctly mentioned.

I have moved away from the cart module and used an instance of the CartViewModel and the load dropped to 1-2 seconds. But I still don't have all details about the products (custom fields) and some OrderFields and OrderLineFields. I expect that grabbing product custom fields to add to this load time. We have also noticed that ProductImage logic in the minicart json feed (the standard one) also had a great impact on performance. This is probably why we will try to either optimize loading the images or drop images from the minicart completely if the cart has more than 20 orderlines. The default ProductImage property of the CartOrderline does not render anything yet, which means that we will have to be creative about how we get a hold of the patterns and use them to get the product image (if we decide to keep images in minicart).

All in all, it is challenging and I have high hopes from this OrderViewModel :)

Thank you both for all your support.


Adrian

 

 
Adrian Ursu Dynamicweb Employee
Adrian Ursu
Reply

Hi Nicolai,

One more question. I see that I can get the order using the "secret" key. And I assume that the link you have mentioned to the API, is also using the secret:

ced5bab913af496688e8df53c19d5278

Is there a direct/easy method of getting the secret key of the current cart? It seems that the CartViewModel does not have a Secret property. What is the most efficient way of getting this key?

Thank you,

Adrian

 
Nicolai Pedersen
Reply

Get the order from the orderservice and take the secret from the order object.

 
Adrian Ursu Dynamicweb Employee
Adrian Ursu
Reply

Hi Nicolai,

I have one more question.

In my use case, the user is impersonated.

I have tried your suggestion to use the API and I get a permissions message: The current user does not have permissions to access this cart.

Is this a known limitation while impersonating?

Thank you,
Adrian

 

 
Adrian Ursu Dynamicweb Employee
Adrian Ursu
Reply

Hi Nicolai,

I have a few more questions about this approach which, by the way, looks fantastic!

I have some issues with a few properties that I cannot find in the regular Order or Orderline Objects.

One of them is Unit, which I would have expected as a property of the OrderlineView class, but maybe I can find it somewhere else.

The other one is ProductImage. I had to initialize a ProductViewModel object trying to get the image of the product. I have tried AssetCategories,DefaultImage,ImagePatternImages but none of them renders anything else apart from the default "missing-image.jpg". Is this the right approach? Should I try something else? For now, I have not created a ProductViewModel Settings in order to make sure that I have all of these properties available. At the end of my refactoring, I will create the Settings just with what I am using.

The dwapi call does not return product images either. Which is why I am suspecting some configuration issue. But the Rapido default mini cart feed returns the images.

Thank you in advance,

Adrian

 

 
Adrian Ursu Dynamicweb Employee
Adrian Ursu
Reply

Hi Nicolai,

I have a few more properties that I could not identify properly:

On the Order object

  • PaymentMethod
  • ShippingMethod
  • Taxes
  • CustomerAccepted
  • Earnings/Reward Points
  • VoucherCode
  • GiftCardCode
  • CustomerComment

On the OrderLine object:

  • VariantName
  • ProductNumber (I had to use a separate ProductViewModel)
  • Link (I can probably use the ProductViewModel and get the Groups or GroupPaths but I have no way of telling which one is the Default)
  • ProductImage (already mentioned but maybe worth adding here)
  • BOM Items
  • Points

 

That's what I have found so far. Please keep in mind that I am attempting to replace a Rapido MiniCart feed and some of these properties mentioned here are used in our implementation.

I hope this summary helps out identifying what needs to be added or clarifying how these properties can be retrieved in the feed.

Thank you,

Adrian

 

You must be logged in to post in the forum