Post Featured Image

Extension Spotlight: Infinite Scroll

As this post is about a SuiteCommerce extension, it is only appropriate for sites running Aconcagua or newer.

In this, the second of the series, we turn our attention to an extension that adds infinite scrolling (also known as endless scrolling) to product list pages. What this means is that when a user starts to scroll down towards the end of a page of search results, the site anticipates that they may want to use look at more results and so loads in additional items without the user requesting them. This functionality replaces the manual pagination options that lets shoppers navigate back and forth between pages by clicking buttons.

It's kinda hard to demonstrate this in GIF form, but I'll try here:

What I hope you can see here is a search results page for my entire inventory. As I scroll towards the end of the list, the JavaScript will anticipate this and automatically send the request for the next items in the list and append them to the end. This process repeats and continues until it runs out of items.

As with the previous blog post in this series (where we looked at the grid order extension), I'm going to take the time to reflect on what it is the extension does, why I think it is important for you as developers to know about it, and what you can learn from looking at the code.

As a reminder, it is important to keep up-to-date with the latest developments from the NetSuite SuiteCommerce extensions team — they update and release new extensions periodically outside of the normal NetSuite and SuiteCommerce release cycle. You can do this by periodically checking the extensions release notes or by subscribing to our newsletter.

Summary

First, be sure to check out our documentation on infinite scroll.

So, infinite scroll is a concept that has been around for a while. In fact, it has become so ubiquitous in mobile apps and websites that you may not even notice it anymore. However, if it is so ubiquitous, how come it is conspicuously missing from ecommerce sites?

The most obvious answer is that web stores simply haven't kept pace with non-commerce sites. Manual pagination and navigation has been the default for so long and a lot of people are used to it in that context. A slightly more nuanced answer can be found in articles from those who specialize in this user experience, for example in this one by Smashing Magazine. In it, they make the point that from a usability point of view, manual pagination is simple to implement and use. However, infinite scrolling is a superior feature — an opinion they back up with user testing. There is, though, potential for infinite scrolling to ruin the user experience completely.

From a technical point of view, we are tying AJAX calls to the scrolling user event. Anyone who has worked with this over the years can atest to flakiness and the potential for the unexpected to happen. Some sites choose an approach that compromises between the two: appending new results to the bottom of the page after a user clicks a Show More Results button.

For clarity, there are three broad types of result pagination that we could implement:

  1. Fully manual — a single page of results is shown at a time and the user can navigate back and forth between them (or go to a specific page by clicking a page number); choosing a new page empties the current page of results and loads in the desired page
  2. Fully automatic — a single page of results is shown initially but additional ones are automatically added to the bottom of the page as the user scrolls down
  3. Hybrid manual/automatic — a single of page of results is shown initially but additional ones may be added to the bottom of the page if the user clicks a button

By default, your site is running the manual approach. This SuiteCommerce extension adds both the fully automatic and hybrid approaches. They each come with their own pros and cons.

One potential downside to the fully automatic approach (that the hybrid approach mitigates) is that as the user scrolls down, the page grows longer with additional results, which means that they will never be able to reach the footer. This may be only be a minor inconvenience if you never anticipate users needing to interact with it with they are on a PLP (the footer will still be accessible on other, fixed-length pages), but some may find it particularly frustrating.

Another thing to consider is your audience. Young, app-using audiences may be more likely to prefer (or expect) automatic scrolling, whereas older, less technology-versed audiences might not. You also need to think about your vertical. In my opinion, there are benefits and drawbacks to implementing this on both B2B and B2C sites — I think that in the absence of interviews and user studies with your shoppers, you'll have to make an executive decision about whether you want it. Generally speaking however, I think some form of infinite scrolling is an improvement over the default manual behavior.

Configuration

There are four configuration options included with the functionality. The most important is the one that switches between the second and third options above. In other words, you can choose to enable fully automatic or hybrid mode by toggling this setting.

The second setting is one that determines how many pages to load in at once (either by automatic loading or hybrid). You can choose a number between 1 and 5. As the items API works on the bases of pages, this setting will determine how many requests should be made sequentially. For example, if you set it to load three pages, then when a user scrolls down to the bottom of the page (ie triggers automatic loading) the application will load the next page of results automatically, appending it to the end; once that is done, it will load the next one and append it; after that one is done it will load and append the next one, and then stop. This also applies to the hybrid solution: clicking Show More Results will then trigger the additional page loads sequentially.

The final two settings relate to the text labels you want to show on the navigation buttons if you adopt the hybrid method.

Code Examination

Remember, we don't make the code for extensions directly available. However, once it is installed on your instance, and activated on your site, you can see the code by looking at the JavaScript loaded into your browser when you visit your web store.

The PLP Component

The first thing that interested me about this feature was how much of it relied upon the PLP component. As you'll know, the PLP component in the extensibility API has a number of methods that make it easy for you to manipulate the product list page of a site. In the implementation of the infinite scroll extension, the team have made extensive use of it.

For example, when determining whether to send a request to load more pages of results, it has determine whether there are more pages of results to load in the first place. To do this, it uses the getPagination() like this:

self.hasMoreToLoad = (this.plp.getPagination() && (this.plp.getPagination().pageCount > 1))

If you check what getPagination() returns, we can see an object with some useful properties on it. Pertinent to our situation, we can see that there is a property that returns a count of the number of pages there are in the search results. Every time a new page is loaded in, we can check whether the current page is the final page and thus prevent further attempts to load more. Smart.

In the extension spotlight post on grid order, we mused over the correct way to remove child views. In that post we came to the conclusion that the generic removeChildView() method is suitable when you are dealing with classes rather than instances. So, a small note here: we know that we will definitely not require the pagination child view associated with manual pagination navigation because we are installing infinite scroll, therefore we know that we can remove all instances of it (ie its class). This is the correct usage of removeChildView() — removing it with jQuery would not be.

Events

In particular, I am pleased to see the many utilizations of events. Events are things that we have talked about before in different situations. On the PLP, we have events that can trigger, for example, before or after a user changes sorting, either to cancel it from happening (ie using cancelable events) or to do something afterwards. What the infinite scroll extension does is listen to a whole host of events in order to trigger a call to 'reset' the page. Changed the page size? Reset the page. Changed the filters? Reset the page.

'Reseting the page' is a pretty contextual thing to say. But because of the way this functionality works, there are a lot of things that we need to keep track of. We need to keep track of the number of pages loaded; we need to keep track of where we are in that chain of pages. We also need to remove any of the child views that we don't need, such as the facet items list (as we need to replace it with a version of our own).

There are also a number of custom events. While you'll be familiar with the fact that we build a number of events into the various components, it's also possible to create your own. For example, we can have code that starts like this:

this.plp.on('InfiniteScroll-afterRenderPage', function afterRenderPage (options) {
  ...
});

By doing this, you are binding a new event to the PLP component. Within the callback, you can put whatever you want.

Now, just because we called it InfiniteScroll-afterRenderPage, doesn't mean that it will automatically load after the page has rendered. No, we need to trigger it. This is why in our renderPage property, we have:

this.plp.cancelableTrigger('InfiniteScroll-afterRenderPage', {
  ...
});

Give it a think about what events you might need to trigger in your extensions, and custom events you might need to write.

Links