Post Featured Image

Use Your Browser's Developer Tools to Troubleshoot Your SuiteCommerce Site

This blog post is generally appropriate for all versions of SuiteCommerce and SuiteCommerce Advanced, but there is some additional material for sites running Aconcagua or newer.

This week, I am joined by a special guest, Florencia Meilan, who is a principal product manager in the commerce team. She has a wealth of technical expertise and depth of SuiteCommerce knowledge, and she has kindly offered a lot of pointers for new developers who want to get started troubleshooting their code in the browser. As the blog post goes along, we'll start with some basics before moving on to some more advanced/interesting/cool examples that even experienced SCA developers might not know about!

Those with long memories will remember that three years ago I put some quick tips for troubleshooting in the browser, and you'll have undoubtedly seen me point to a few in other blog posts before. However, all of these should be fresh and if you're new, I suggest taking a look at that blog post and then diving into these too!

Browser developer tools can be very powerful when you're building and troubleshooting your site. They do a range of things, from inspecting a page's current HTML, CSS and JavaScript to showing which assets the page has requested and how long they took to load. This article explains how to use some functions of your browser's developer tools that will help you debug your SuiteCommerce and SuiteCommerce Advanced web store, mainly focused on JavaScript and network issues.

Each browser differs in exactly which tools they provide, but they're more similar than they are different. The UIs for the browsers' developer tools can be a little overwhelming, and if you're completely unfamiliar with them, you may want to do some background reading first. I'm going to be using Chrome's DevTools — if you are not familiar with them, I recommend you start by reading Google's beginner's guide.

Finally, just before we begin, the code I'm going to offer below often isn't necessarily best practice in terms of the site code you should put in your site's files. I really only recommend using them for troubleshooting, testing and prototyping.

Using the JavaScript Console to Analyze the Global SC Variable

To open the JavaScript, open the tools (press Command+Option+I (Mac) or Control+Shift+I (Windows, Linux)) and then click on the Console tab.

We don't typically use global variables, but we have one that runs on every site: SC. If you type SC into the console, it'll return a number of objects.

You can click through each one and see data and settings about the current state of the site as your current user. Some of these things will be context specific, which means that they will be affected by your current user (or if you're not logged in at all) and what page you're currently on, and some will be global.

Use the Environment Object to Check Site Settings

A good place to start is with some site settings. We make them available as properties to the ENVIRONMENT object attached to SC. To access it, you can type in SC.ENVIRONMENT.

From there, you can do something like this to access site settings:

SC.ENVIRONMENT.siteSettings

Remember, this is case-sensitive.

One interesting thing about DevTools is that it will 'eagerly' evaluate what you type in, to show you the results of functions, the available properties of an object, and the values of those properties. You can see in the above gif how you might check the values of certain site settings.

Get the Site Configuration

Another common issue is that you make a change to a site's configuration record, but it doesn't seem to be affecting the frontend of the website. Is the value making it to the frontend? Is it being cached in your browser? You can find out by querying the configuration object.

SC.CONFIGURATION

From there, you can access a number of properties, just like you could with the ENVIRONMENT object:

Now you can look for the configuration value and see if it's coming through to the frontend.

Get the Current Model

Common customizations to webstores involve adding extra data to the model before it's sent to the view and then to the template. If your data, such as a custom field, doesn't show up on the frontend, it can be tricky to figure out what exactly is the problem.

One thing you can do is check the model and see if the data has been sent from NetSuite to your site's frontend. Type in:

SC._applications.Shopping._layoutInstance.currentView.model.attributes

Depending on where you are, you'll see different things. If you're on a product detail page, you can click on item > attributes to see if the field is there. If you're on a product list or search results page, you can click on items > models and then find the specific item in the array.

Bonus tip: if it's not there, make sure you've updated the relevant field set and refreshed your search index!

List All Loaded Files

Now we're getting a bit more advanced.

When you use define() in your code, you're creating a new class in your application. If it's included in your compiled JavaScript, then it will have a 'definition' and will be made available to be called by the application.

You might sometimes get an error where it says something like:

Uncaught Error: No MyCustomization.View

Where MyCustomization.View is the name of a class you've tried to call in your code. In simple terms, it returns this if it hasn't been loaded by RequireJS, the library we use for managing dependencies. You can get a full list of every file loaded into the application by typing in:

requirejs._defined

This will return everything that is currently loaded into the application. Of course, you might get other areas where you suspect that the problem is because the file has not been loaded into the application.

Log a View's Context Object to the Console

The getContext() method returns an object of data that the template is going to render. If text isn't showing, or conditionals aren't returning the correct values, then it's possible that they're not receiving the correct values.

We've touched on accessing the application, layout and view objects in passing, and another part of that is accessing their context objects:

// Get the context object for the current parent view
SC._applications.Shopping._layoutInstance.currentView.getContext()

// Get the context object of a specific child view in modern versions of SC/SCA
SC._applications.Shopping._layoutInstance.currentView.childViewInstances['Product.Price']['Product.Price'].childViewInstance.getContext()

// Get the context object of a specific child view in older versions of SCA
SC._applications.Shopping._layoutInstance.currentView.childViewInstances['Item.Price'].getContext()

The childViewInstances will return the actual child views that have been constructed. You can use childViews instead to return the views that are listed in the parent file itself (ie pre-construction).

Access Extensibility API Components

These tips only apply if you're using Aconcagua or newer.

Make a Simple Change with a Component

When you're coding, you typically access the components from an argument available from the mountToApp function in an entry point file. However, you can also access them through the JavaScript console by accessing the same object we used for the model. For example, if I wanted to test out some code using the PDP component, I can use:

var PDP = SC.Application('Shopping').getComponent('PDP')

I'm using SC.Application('Shopping') instead of SC._applications.Shopping to make a point (the old way will still work). In newer versions of SuiteCommerce Advanced, we obviously discourage the access of private methods/functions/objects and instead the encourage the use of our API. While we're only using this method for testing, I just wanted to point this out so that you're aware. There are a number of other examples where this is the case; for example, we might use getLayout() instead of _layoutInstance. Remember: we recommend the use of our best practices because they're stable; the use of private methods is not recommended.

Anyway, back on track and looking at the code example, this will make the PDP component available as PDP in my console (assuming, of course, that you are on a product detail page — some components such as the PDP, PLP and checkout only work when you're in those contexts). From there, you can use all of its available methods to quickly test out changes. For example, if I wanted to try out changing the selected color option of a matrix item on a PDP, I could use:

var PDP = SC.Application('Shopping').getComponent('PDP')
PDP.setOption('custcol_gen_color', '1')

The values you'll enter on your site will depend on your site's custom fields, setup and the item you're viewing.

Test a New Child View

Let's say you've created a new view and template and they don't seem to be working correctly. You've checked and they're being loaded into the application (see above), so you just want to add them to your current page and see how they will look. How do you do this?

In this example, I've already created the view and template and I want to load it into my login page. You can also do this through the console, including re-rendering the main view so that it shows in the page.

In my example, I'm going to be adding this to the login page.

How do we do this?

Here's the view:

define('Vendor.Extension.Module.SimpleView'
, [
    'vendor_extension_module_simple.tpl'
  ]
, function
  (
    vendor_extension_module_simple_tpl
  )
{
  'use strict';


  return Backbone.View.extend({
    template: vendor_extension_module_simple_tpl

  , getContext: function getContext ()
    {
      return {
        message: 'I\'m a child view added via the extensibility API! Go me!'
      }
    }
  })
})

And here's the template:

<h2>Test!</h2>
<p>{{message}}</p>

After adding these to an extension, I can use the these console commands:

var Layout = SC.Application('Checkout').getComponent('Layout') // Note we're using the checkout application because we're on the login page
var SimpleView = require('Vendor.Extension.Module.SimpleView'); // The view you want to render (I created mine earlier)
Layout.addChildView('Login', function () { // The place you want the view to render
  return new SimpleView();
});
Layout.application.getLayout().getCurrentView().render(); // Re-render the main view

After calling the layout component (on the checkout application because we're on the login page), we create a version of the view we want to render by using require() and passing it its class name. This is essentially what happens when you pass class names in a define() statement, listing your dependencies — ie, "load this file".

Then we use addChildView() to add the view to the place where we want to render it, and then re-render the main view. The getLayout() method gets the current layout, which is the skeleton of the application, and then we call getCurrentView() to call the main view currently being used. Then we just re-render it.

Bonus tip: while I don't think it's going to be useful, you can create a confirmation dialog or modal in the console too!

How do we do this?

var Layout = SC.Application('Shopping').getComponent('Layout')
, ConfirmationView = require('GlobalViews.Confirmation.View')
, confirmation = new ConfirmationView(
  {
    title: 'Test Confirmation Popup'
  , body: 'Did you create this in your developer console?'
  , autohide: true
  });
Layout.showContent(confirmation, {showInModal: true});

Like before, we are creating variables for the layout component and our confirmation view. Then we create a final one, creating a new instance of the confirmation view with our test properties.

To create it, we use the familiar showContent() method, which is used to render views. You'll note that after passing it our newly constructed view, we also pass an object of options; specifically, we passed it showInModal: true, which tells it to create it in the modal.

Use the Network Tab to Analyze Requests

We've spent a lot of time looking at the JavaScript console, and there's still plenty of interesting things to play around with in there, but let's move onto another useful aspect of the developer tools: the network tab.

As long as you have the developer tools open, all HTTP requests will be logged in it (requests made before you opened the tools are not logged).

All kinds of requests are logged by the tools, and you can filter them by clicking on the specific buttons (eg, XHR, JS, CSS, images, etc).

If you filter by XHR (XMLHttpRequests — eg, AJAX requests to the items API) and then click one of the requests you will be shown the specific details of the request being made. This is particularly valuable

To debug issues in the applications, we will typically use the Headers and Preview sub-tabs. The HTTP headers are the bits of information about the request being made as well as any additional information that might be required. By inspecting the headers, you can see the basics of your requests, such as the query string parameters, which are the bits of data at the end of a URL. For example, the request URL for the items API is api/items/ and everything else included afterwards are the specifics of the request, such as the item URL we want (or keyword for searching), as well as information such as currency and country.

To review the response from the server, we can use the Response sub-tab, but we prefer the Preview tab because it formats JSON responses so they can be clicked through and explored more easily.

This can be quite useful for troubleshooting search results. If you ever wonder what data is being returned from the API after performing a keyword search, or when a shopper hits a commerce category, you can right-click on the XHR and then click on Open in a new tab to get a full-screen look at the API results.

The above gif shows a developer clicking through a sample XHR. Note that when the API response was opened in a new tab, there was a brief moment when it was unformatted and then formatted — this is a plugin that formats JSON responses and there are many available in the Chrome web store.

Any service that is called by an application can be inspected to see the request/response, not just the items API. Important services to check include LiveOrder.Service.ss (the XHR for the cart) and Categories.Service.ss (the XHR for commerce categories). As with the checking with did earlier with JavaScript console, you can check the API/service responses to see if the correct data is being sent and if the correct data is being returned.

Use the Network Tab to Analyze Performance

There are a lot of resources on this site that cover how to analyze performance problems, so we won't go into too much detail about this.

However, something worth reiterating is that performance is important. Search engines prefer faster sites, and so do shoppers. Very slow sites can be problematic and you can get simple stats from the developer tools.

For more information, see our performance guidelines.

Final Thoughts

Thanks again to Flo for giving me information about this and suggesting it as a topic.

If you're new to commerce web development, or developing on SuiteCommerce, then troubleshooting errors can be time-consuming and frustrating; hopefully this blog post has pointed you in the right direction. If you're an experienced developer, I hope you'll explore the possibilities opened up by the extensibility API to do troubleshooting and even some prototyping.

If you're the curious type, and want to explore more with the SC global variable, then you can explore the current state of the page you're on with commands like this:

// Get the main application object (assuming you're in the shopping application)
SC._applications.Shopping

// Get the main view for the current application (ie the layout skeleton)
SC._applications.Shopping._layoutInstance

// Get the main view for the current parent view (eg the PDP or home page)
SC._applications.Shopping._layoutInstance.currentView

If you're clicking through objects, don't forget to take a look at their prototypes too — you can normally see them at the bottom of property lists as __proto__ and can show inherited properties and methods.

Further Reading