The commerce extension framework enables you to create extensions that plug into your web store, making it easy for developers to customize web stores and update the core code with little fuss. However, in order for that to be successful, developers should follow best practices to ensure customizations can be moved between sites and versions.

In some ways, this is a follow-on post to The Extension Framework and Extensibility API, which I would recommend reading first.

Before Approaching Customizations

I would also be remiss if I didn’t preface a document like this with the wild suggestion that perhaps you don’t need a customization or extension. What I mean by that is: is there a way you can do this without introducing new code?

Can you do what you want to with configuration rather than customization?

The reason I emphasize this question is because over the releases, we have made improvements to the tools available to users to introduce change to their site without the need to intervene on a code-level. Introducing code-level changes will always introduce a level of fragility to the customization, as well as make it difficult for non-technical users to make future changes.

For more information, see Use Configuration Instead of Customization.

Approaching Customizations

Before we dive in to specifics, I want to have a quick look at what has necessitated this discussion and provide some simple principles that you can use to guide you through this.

SuiteCommerce is NetSuite's commerce offering that is truly software-as-a-service (SaaS). The principle idea is that a site can be customized but still migrated to a new version automatically, whenever an update becomes available. For SCA this was problematic because of the nature of the customizations, how they were written, and how they were integrated into the code. The extension framework aims to separate customizations from the source code with a code layer — the extensibility API — and a framework for activating customizations so that they are automatically combined, as much as is necessary, into your site's final code.

There a numerous differences and similarities between editions of NetSuite Commerce, but for the purposes of customizations, we should focus on four:

  SuiteCommerce SuiteCommerce Advanced
Extensions Yes Aconcagua or newer
Extensibility API Yes Aconcagua or newer
Customization Types Extensions and themes Extensions, themes and full source
Migration to Newer Version Automatic, always up-to-date Manual, when you decide to

There has been some confusion about whether the extension framework — the API, extensions and extension manager — are available for SCA and the answer is yes. If you're working on a modern version of SCA then the customizations available to SuiteCommerce are also available to you; the principle difference is that you are also given full access to the site's source code, so you can make more complex customizations if you wish. The extensibility API is available throughout the SCA source code (ie not just extensions).

Key Principles of Stability and Sustainability

Using the table of differences and similarities above, we can extrapolate some of the most important things to keep in mind when working on a SuiteCommerce site. Before we do, let’s think about the motivation behind using SuiteCommerce and the commerce extension framework.

  1. Migrations to new versions are done automatically, so the customizations I write shouldn’t break on new versions
  2. The code base for SuiteCommerce is identical across all sites that run it
  3. The commerce extension framework, which is built on top of this identical code base, is designed with stability and sustainability in mind

While SCA sites might not be full SaaS by design, you can certainly streamline it as much as possible by following the same best practices that we provide SuiteCommerce developers.

Using the following bullet points, we can set ourselves some principles to follow when approaching customizations:

  1. Upgradeability
  2. Reusability
  3. Maintainability

Firstly, upgradeability means that a site or customization is easy to keep current. We don't want sites locked to a particular version of SuiteCommerce Advanced because of a customization that has gone awry. Modifying a site's source SCA directory will by definition make the migration process manual, as you will need to move across any modifications to the new version, but you can still put in work early on so that it's as painless as possible later.

Next, reusability. There's two ways to look at this: reuse the components that we provide (rather than writing your own) and write your customizations in such a way that they can be used on multiple sites. The latter is perhaps more important for developers who work at agencies who customize a lot of sites, or those who work at a business with multiple brands. In either case, you need to think about what exactly exists in the code and how you can plug it in to other sites.

Finally, we have the concept of maintability. This is all about increasing your productivity and reducing the time spent doing non-technical things. As an example, we are rapidly developing the site management tools and enriching them with new features. I strongly recommend that you take a look at them when building a site to see what you could use to lighten your load. As for your code, we're also thinking about how much work you need to put into your customizations to keep them running and interoperable (ie playing nicely with other customizations on your site).

So, why have these come up and now, and how do they factor into SuiteCommerce and SuiteCommerce Advanced? Well, we think that the best practices we used to prescribe are no longer appropriate. If you were to customize your SuiteCommerce Advanced site the same way you used to, you'd run into the same problems all over again. Instead, we need to redefine the best approaches to customization, keeping in mind SuiteCommerce and then we have new tools at our disposal — the API, extensions and the extension manager.

Traditional SCA Customizations in Extensions

To provide context, let's return to how we compare the two ways of making customizations to a SuiteCommerce (or SuiteCommerce Advanced) site: as a customization to the core code ('the old way') and as extensions ('the new way').

Before the extension framework, you created a folder in your SuiteCommerce source directory, wrote a bunch of stuff, updated your distro file and pushed it up to NetSuite. The compilation happened on your local computer and once it was finished, it was pushed up to NetSuite and immediately made live (you may have to clear the cache but it was there). With the extension framework, you work locally and push it up to NetSuite as before, but there is a round of what we call activation, which triggers recompilation and concatenation; when that finishes, then your code is live.

In this context, how you write your code didn't really need to change if this was just your site. However, there are two dimensions that we need to consider when creating SuiteCommerce customizations:

  1. How well will this age when the base SuiteCommerce Advanced source code is migrated to a new release?
  2. How well will this interoperate when it is added to other sites?

To put these another way: you need to keep in mind the changes that we, NetSuite, may make over SuiteCommerce's life cycle as well as the changes a customer may make to their SuiteCommerce site of it's life.

The reason why we consider the extensibility API to be your best bet is because it wraps so many customization avenues in a layer that is generally indifferent to version or site.

Version-Agnosticism

Version-agnostic customizations are those that don’t ‘care’ what version of SuiteCommerce or SuiteCommerce Advanced they are installed on to.

This is particularly important for the software-as-a-service SuiteCommerce product as its core code is automatically updated every release. Problems can arise if you write a customization that relies on core code modules as there is no guarantee that it will continue working the same across releases. If this happens on your live site, this could have serious ramifications on its ability to trade and serve customers.

To give a specific example, consider the refactoring and renaming of the SuiteCommerce Advanced source code in Elbrus that changed how we handle product data, specifically the product detail page. If, before that time, you made customizations that relied on the ItemDetails module, you would have had to completely rewrite them because the class names you depended on no longer existed when you migrated to this release. This is because Elbrus split up the functionality into other modules, such as Item and ProductDetails.

Other examples come from two additional projects going on behind the scenes:

  1. Our migration to TypeScript
  2. Our migration to SuiteScript 2.0

Apart from changing the behavior of migrated modules, they also change the way that developers can interact with the modules. This can range from basic syntax changes, to some methods becoming protected or private, to the modules being completely unavailable to customizations.

You can achieve version-agnosticism and avoid version migration problems by relying solely on the extensibility API.

As developers for live ecommerce sites, you shouldn't have to worry about when we change the internals of our code. Instead, you should be free to make customizations with a high degree of certainty that when it comes to migrating to a new release. This is why we have the extensibility API — it doesn't matter what we name our internal files and methods: all that matters are the names of the components and methods, and the things they output.

Site-Agnosticism

The second risk is more applicable to our partners, or developers who plan to develop customizations for use on multiple sites: site-dependence.

When you make a modification to fit the requirements of a specific site, you might fork so intimately away from the base code that renders it inapplicable to other sites. What I'm thinking about here are customizations that extend base SuiteCommerce classes, modifying prototypes, file overrides, adding configuration to the code (rather than the configuration record), modifying helpers, private functions, etc.

This behavior is risky not only because of the risks associated with NetSuite changing these files every release, but because there may be other site-specific customizations that exist on other sites. To give an easy example, consider a customization for which there is currently no easy extension-based solution: customizing the loading icon.

If you've read the article on this already, then you'll be aware that in order to modify this behavior, you can edit (override) jQueryExtras > JavaScript > jQuery.ajaxSetup.js, as well as provide any additional assets. If you own and operate the site you’re customizing, and it’s an SCA site, then this is relatively straight-forward, but packaging up this customization into something that is distributable and applicable to many sites is problematic.

jQuery.ajaxSetup() is an important file. It defines the settings that will apply to all AJAX calls made using jQuery (including jQuery.ajax() and jQuery.get()). jQuery themselves recommend against using it, stating:

This can cause undesirable behavior since other callers (for example, plugins) may be expecting the normal default settings. For that reason we strongly recommend against using this API. Instead, set the options explicitly in the call or define a simple plugin to do so.

Indeed, this is also good advice in general. But specific to us, some sites may have their own customizations within this file and you creating an extension that overrides it will remove their customizations.

This is part of the reason why we have another way of achieving this goal, which is to leave the existing core code in place but unbind its callers. While this may some unused, vestigial code in your site, it means that your extension can be plugged and unplugged into any site without interfering with of the other code in the file that may be used.

To offer a second, more abstract example, consider the traditional methods for customization: extending an object, wrapping a function, modifying a prototype, etc, which all rely on changing the behavior of core code modules. While this might be OK on a particular site locked on a particular version, it can become unpredictably problematic when added into an extension that could be installed on a site you don’t know about.

A final example could be custom NetSuite ERP features: custom fields, records, lists, etc. If your customization introduces new custom objects you should make sure they are properly namespaced because you could end up with clashes.

Can I Use vs Should I Use

Since the release of the extensibility API, a question I was frequently asked was, "Can I use [x]?" To which my answer is, "yes, but should you?".

Many SuiteCommerce developers have been around long enough to see customization methods change over time. Understandably, these developers are used to doing things a certain way and, unfortunately, many of those methods are no longer recommended.

To put it bluntly: avoid using core SuiteCommerce classes/modules/objects as much as possible.

If you can't avoid it, then you need to be able to assess the risk using the two factors I mentioned above.

An important thing to keep in mind is that with every release, we are adding in new components and methods, which will diminish reliance on base SC classes.

Consider for example:

  • The layout component — available globally, you can use this for the timebeing to add, remove or replace the views throughout the site, particularly areas such as the homepage or customer account section, which don't currently have components
  • The environment component — also available globally, you can use this to access values from the site configuration and settings records, which means you no longer have to use SC.Configuration, for example

These are good things. It's part of our philosophy which is where we move towards extensions having complete independence from core SC code. Eventually, your code should hook into our code purely through API calls. Indeed, if you're a pure SuiteCommerce developer — with no access to the source code — you are not going to know any base SC classes.

But What About Backbone, Handlebars Extras, Global Views, Etc?

Once you've hooked your customization into NetSuite, and you want to build it out, you are free to use Backbone classes — routers, models, views and the like — how you wish to achieve your customizations. Using Backbone is considered particularly low-risk because of how it forms, well, the backbone of our applications. However, over time we have been looking to introduce more agnostic replacements for core Backbone classes.

Backbone Class Extensibility API Replacement Version Availability
Backbone.Collection SCCollection 2020.1
Backbone.CollectionView SCCollectionView 2020.2
Backbone.FormView SCFormView 2020.2
Backbone.Model SCModel 2020.1
Backbone.View SCView 2020.2

If your site has these new classes available, you should prefer them over the base classes.

When it comes to our custom 'utility' code such as HandlebarsExtras, Utilities, GlobalViews, BackboneExtras, etc, you should be relatively fine — there may be some risks involved with these as we make changes across versions, but they are fundamentally stable.

Keep in mind that a lot of custom utility functions are have been added to the Underscore namespace (_). So, for example, if you need to use the formatCurrency() method, you can use _.formatCurrency() instead. It is also where we make available a few extra bits of environment information, such as whether you're currently in the shopping domain. Explore the API docs for more information.

Some things, like Backbone.Validation, might be a little tricky because some sites implement custom validation rules to standard fields. Again, however, I would say that it is safe to assume that it would be rare for any site-specific customizations to interfere with an extension's validation (ie, I think it's unlikely to see extensions that modify the validation rules of standard fields).

Also note that there may be some nuances to developing on SuiteCommerce compared to SuiteCommerce Advanced. One of the things you can change in SCA is the distro file: you can control which (source) modules are included in your applications. There was an interesting thing that came up recently where someone was trying to use the country and states global view dropdowns. This was a good idea: re-use what we give you. However, there was an issue because the source code does not use these global views in the shopping application — only on the account and checkout applications. Therefore, they were not available for use in the shopping application as they weren't compiled into the source. If this was an SCA site, they could have just modified the distro to include them in the compile, but, as of me writing this, there are not currently available in the shopping application.

Examples of Extensibility API Best Practice

All of this is theoretical, so let's look at some examples.

I think no matter what we do to stabilize the customization process, there is always a very small risk that customizations may not work as intended when transferred to a different site, or the current site is migrated to a newer version. However, the extensibility API should be the safest bet. As much of your customizations should be done with the API as possible.

Getting Configuration Record Values

We have a global variable, SC, which can be accessed anywhere; generally speaking, we don't encourage pulling stuff out of it. For configuration values, we would normally recommend adding SC.Configuration as a dependency (named, for example, as Configuration) and then just use that. However, now we have the environment component, so just use that and then use its getConfig() method.

// ❌ Don't use the SC global variable
var isMultiShipEnabled = SC.CONFIGURATION.isMultiShippingEnabled;

// ❌ Don't add the Configuration module as a dependency
var isMultiShipEnabled = Configuration.isMultiShippingEnabled;

// ✅ Use the Environment component of the extensibility API
var Environment = container.getComponent('Environment');
var isMultiShipEnabled = Environment.getConfig('isMultiShipEnabled');

Adding a New Child View

If you've written some new functionality that plugs into existing functionality, then you'll likely need to add a new child view. Ever since we made every view a composite view in the Elbrus release, adding a new view meant adding the view you want to add a child to as a dependency, and then just modifying the childViews object of its prototype. Prior to that, there was a lengthy process which involved converting simple views into composite views but, now, with the extensibility API, you can use a component specific for an area of a site, or use the layout component in general.

// ❌ Don't modify a core module's prototype object
CartSummaryView.prototype.childViews.MySuperCoolView = function ()
{
  return new MySuperCoolView
  ({
    model: this.model
  })
}

// ✅ Use a visual component's addChildView() method
var Cart = container.getComponent('Cart');
Cart.addChildView('Cart.Summary', function ()
{
  return new MySuperCoolView
  ({
    model: this.model
  })
});

Another way of making child views available is through something we added in 2018.2: registerView(). Unlike addChildView, which requires you to specify at the time of construction where you want it to go, this method lets you create a new child view that can be included anywhere on a site by simply adding markup to templates.

// ✅ If your page doesn't have a specific visual component, then you can use the the Layout component
var Layout = container.getComponent('Layout');
Layout.registerView('MySuperCoolView', function ()
{
  return new MySuperCoolView
});

This method is perfect for situations where your extension adds new functionality but it is up to the implementor where it should be rendered. It's also good when responsibilities between theme development and code development are divided: ie, new views can be added without updating the JavaScript core code / extension after the initial implementation.

Adding a New Value to a Context Object

The Underscore method wrap() comes up in a lot of example customizations because it enables us to run a function and modify its output before its returned. In other words, if we have a finished context object, but want to add an additional property to it, then we can put it in a wrapper function that runs it, and then adds in our property.

With the extensibility API, we can access the addToViewContextDefinition() method which does the job for us. We specify the view whose context we want to modify, the property name (new or existing), its type, and then the function that determines its value. Handily for us, the existing context object is passed along with it, so we can query it, should we need a value out of it.

// For example, I want to add a property that returns the number of characters in the name of an item
// ❌ Don't modify a core module's prototype or wrap its context object generator method
ProductDetailsFullView.prototype.getContext = _.wrap(ProductDetailsFullView.prototype.getContext, function(fn)
{
  var context = fn.apply(this, _.toArray(arguments).slice(1));
  context.nameLength = this.model.get('item').get('displayname').length;
  return context;
});

// ✅ Use a visual component's addToViewContextDefinition() method to modify a view's context object 
var PDP = container.getComponent('PDP');
PDP.addToViewContextDefinition(PDP.PDP_FULL_VIEW, 'nameLength', 'number', function nameLength (context)
{
  return context.model.item.displayname.length
});

Modifying Backend Behavior

At the time of writing we have one component to our backend extensibility API: the cart. Thus, if you wish to modify the service (controller) of any other part of the backend, you will probably have to use traditional methods of customization. However, if you want to modify the behavior of the cart, you should use the backend cart component.

The cart component has a number of methods, as well as a myriad of events that you can listen for. The backend component is designed to have the same syntax and behavior of the frontend one, and although it operates synchronously behind the scenes, you can still write code that is asynchronous (ie, it won't operate asynchronously but it means the code you use on the frontend can be easily ported to the backend).

So, let's take another example, for which there are (at least) two ways of doing it. Let's say that when a shopper updates a line item in the cart (eg adjusts its quantity) we want to trigger a check so that we can test if its purple.

// ❌ Don't extend the core module or wrap its methods
_.extend(LiveOrderLineServiceController,
{
  put: _.wrap(LiveOrderLineServiceController.put, function (fn)
  {
    var options = this.data.options;

    _.each(options, function (option)
    {
      if (option.value && option.value.label == 'purple')
      {
        console.log('I like purple!')
      }
    });

    return fn.apply(this, _.toArray(arguments).slice(1));
  })
});

// ⚠️ Avoid using the Application module's backend events
Application.on('after:LiveOrder.Line.ServiceController.put', function (line)
{
  // ...
});

// ✅ Use the backend Cart component's cancelable events
var Cart = Application.getComponent('Cart');
Cart.on('afterUpdateLine', function checkForPurple (data)
{
  var options = data.line.options;

  _.each(options, function (option)
  {
    if (option.value && option.value.label == 'purple')
    {
      console.log('I like purple!')
    }
  });
})

In other words, the backend cart component works like a wrapper for the LiveOrder model. So, I can recommend the above approach because it is possible to achieve what I want to achieve without touching the base class by virtue of the cart component.

There are a few functionality changes we make to the core code:

  1. We extend a view
  2. We extend a service controller to wrap a method of it
  3. We override a template

Interacting with views and templates are things that we could handle with the extensibility API, but it's the question of our interaction with the service controller that's perhaps the most controversial. In this scenario I recognize that we really don't have an alternative for it.

It's unlikely that we will create components for every backend service on a SuiteCommerce site, and it's unlikely that we will create a generic backend component that can apply to all backend services (like the layout component does for the frontend). You will need to use traditional methods for these.

Can I Put Non-API Customizations into Extensions?

Let's say that you've decided on the customization you want to make. However, you can't figure out a way to write it in such a way so that it relies entirely on the API. Are you allowed to add these to your extensions?

For SuiteCommerce sites, we recommend against using core modules in your customizations. SuiteCommerce Advanced sites may use them with caution.

We strongly recommend you use extensions as much as possible. We would recommend and prefer that you only connect to the core code through the extensibility API but if you have to make a customization that modifies/extends the source code, then it's still a good idea to put them into extensions.

Keeping no code in the SCA source directory for your site will ensure that when it comes time to migrate to a new release, no manual work to the source code needs to be done to get your site moved over. Consider this scenario:

  1. All site customizations are in extensions
  2. I upgrade my site's bundle to a new version of SCA
  3. I activate my theme and extensions

This clean process will ensure that even a non-developer can migrate a site to a new version. Compare with this scenario:

  1. Some site customizations are in the SCA source directory
  2. I upgrade my site's bundle to a new version
  3. I must wait for my developer to copy the customizations over, modify the distribution files, and deploy, before I am able to take advantage of all of my site's customizations

Yes, if some customizations are not compatible with the new version, that is not going to be fixed by having them in extensions. However, it does mean that if one malfunctions and is not ready, it can be just deactivated and the site go on (assuming, of course, it's non-essential functionality).

Anyway, I digress: keep in mind that using source classes and methods is risky. Remember, we're here to ensure sites can be upgraded and maintained easily. Extensions and the extensibility API are there to minimize risk by only using code that is reliably stable. You need to make the decision about whether it is worth it.

How Risky is 'Risky'?

Having given this advice before, I've had some questions about specific areas of functionality. As a team, it's hard for us to really analyze and propose definitive answers about each individual class, method and property in the source code. The new vs old examples above are pretty explicit, but what about more nuanced areas of the platform, those untouched by the API? Here's an illustration I made; note again: this is not definitive or there to give you a yes/no answer. Use it to help inform your decision-making process:

A matrix representing the author's opinions on how much risk is associated with various approaches to customizations.

The two axes are trans-version risks (changes to the source code made by NetSuite in each release) and trans-site risks (changes made to a specific site).

So, for example, if you've written some custom functionality that depends on a custom field that you don't control, or is otherwise specific to the site it was written for, it's almost certainly not going to work on another site (unless you go through the steps to recreate them and their values) — but is this going to break when you upgrade the site? Probably not.

Let's take a look at Bootstrap, the third-party library we include in all of our sites to solve some of our presentation needs. Well, we might upgrade that library in a future release, and when we do, we might reference some part of that doesn't exist in older versions. So, if you try to use an extension that contains references to it in older sites, they're not going to work.

Those of you with long memories or experience migrating sites will have to cast yourselves back to that time and think about the things that caused you pain when you tried to reintegrate customizations. Some of the changes that SuiteCommerce code updates can bring include:

  • Class name changes
  • Method name changes
  • Source code refactoring

I mentioned this earlier with references to the changes we made to the ProductDetails module. Anyway, this is why we say you should use the API: if you call the names or methods directly then you may end up calling something that could change either its name, method name, or method behavior. API names, methods, and behavior should remain stable across releases; as for the contents of the source code, there's no guarantee.

If you've ever done a site migration from one version of SCA to another, then remember that the extensibility API and extension framework are there to alleviate those headaches. Thus, in this context, risk could be defined as having to do extra work when you migrate your site the next time.

If you've ever written code that is to be used on multiple sites, then addressing the idiosyncrasies of those sites (plus the risk of differing versions) come into play. Thus, risk in this context might be thought of the extra work you have to put in to getting it to work in those different scenarios.

Ultimately, you can look at this way: you could avoid using the extensibility API entirely, but you'll probably end up doing more work. It's not strictly mandatory (ie if your code works, it works) but the API is here to aid you; it's here to make your lives easier and ensure that your code continues to work when it's transported from site to site, and those sites get updated.

Remember when we talked about site-specificity and version-specificity? Well, if you're working on your own site and you're happy introducing a bit of risk, then that's your call. If you're working on a customer's site then you should obviously minimize it as much as possible, or let the customer take that the risk from an informed position. If you're writing an extension for the marketplace, where you don't know the site or what version they're using, you should avoid risk as much as possible.

Can I Put API Customizations into My SCA Core Code Customizations?

Yes, we recommend it wherever possible.

How Do I Manage Small Customizations?

When it comes to big customizations: blog functionality, size guide, gift certificate value checker, etc, it's easy to package these up into individual extensions. But what about small changes? What's the best way to handle those? How do you package up a small change to the footer, or an addition to the PDP?

Having looked at how people are developing on SuiteCommerce Advanced in the wild, there seems to be two approaches:

  1. Follow traditional customization processes and put them all into a customizations folder in your SCA directory
  2. Create one big, generic, site-specific extension and put all of them into there?

And the answer is that we think you should use one big extension. Think about what we just looked at: how it's best to keep the source directory clean. In short, I think in most cases it would be much more preferable to put as many customizations as you can into extensions. The fact is, putting code into extensions keep your source code clean. Remember, one of the key benefits of the framework is that we make it easy to upgrade SuiteCommerce Advanced sites.

A combined screenshot of two representations of how to organize customizations. The first shows a "Customizations" folder in the "Modules" source directory of an SCA site; the second shows a "Site Specific Extension" folder in the "Extensions" directory.

When it comes to upgrade time, the process for migrating a site to a newer version should be much easier if the base source code is untouched.

Are API Methods Backwards Compatible?

No. Just like the example above about Bootstrap, if you reference a method used in a newer version of the API than the site has access to, it won't work.

This might be problematic, but keep in mind that if a site follows best practices, there is no reason why they cannot keep their SuiteCommerce Advanced version up to date.

We recommend adding fail-safe checks before using a component or method (such as checking they exist) before using them in your extensions.

Are API Methods Forwards Compatible?

Generally, yes. We take steps not to deprecate or fundamentally change how a component, its methods or its events in future releases. If we do make changes, we will communicate them through the release notes and, if necessary, PFCNs.

Can I Extend Extensions?

It is technically possible but not recommended unless you own/control the extension you are extending.

I think when you're considering this, you need to be careful. By doing this you're effectively creating a dependency in an environment where it's possible for a site administrator to disable one using the backend interface. Generally speaking, if these are extensions that you own and operate, it's probably low risk if the site administrators are aware that they are not to be treated independently.

Treat third-party (or NetSuite) extensions like you would core modules: the original author may push an update for their extension that changes the behavior, removes a class or method, and you're stuck having to either rewrite your extension or removing it entirely.

In this sense, you might think of extending extension classes as like extending base SuiteCommerce classes — we generally don't recommend it, and the risks detailed above (about moving sites or versions) apply.

There might be some exceptions to this. If the extension you're extending is very simple, or provides some sort of library or utility function, then you might be able to get away with it. Again, however, like so much of this stuff, it's a judgment call: how important is it to you that you create this dependency? Can you work around it?

If you are going to extend an extension consider the advice that Joaquín gave at SuiteWorld and in our previous post:

  • If you own the extension, consider creating an API for it (maybe a new component?) within that extension's code
  • If you don't own the extension, consider creating an adapter for it and then have your customization talk to it through that

There is a very good diagram (and explanation) in our article on The Extension Framework and Extensibility API.

Can I Use Overrides?

The only overrides we recommend using now are the ones that are available in the theme development tools. What this mechanism lets you do is override an HTML or Sass file originally found in an extension, with one that you're adding to your theme. The example we give in the documentation is a scenario where you want to add a site-specific Sass variable to an extension Sass file. Therefore, the developer chooses to override the file and add their Sass variable to the declarations found in that file. Good idea!

As for doing this in your source code, I really must advise against it. This is precisely the type of thing that will make it very difficult for you to migrate your site to a new release and you will certainly experience difficulties should you override a particular big file. Remember, with templates and Sass files now moved out into standalone themes, changes to templates and Sass files are done there and you shouldn't feel afraid to use them there.

I am aware of some anxiety around making extension-specific changes to your theme files. If it is not possible to replace or add a view for your functionality using the API, then this can be problematic but I would encourage perseverance. If you own both the extension and the site, and you're making a site-specific change to a template or style, then make it in your theme.

What Should I Keep in Mind When Developing an Extension for SuiteCommerce Versus SuiteCommerce Advanced?

SuiteCommerce sites are automatically migrated to a new version when available; SuiteCommerce Advanced sites are not. Therefore, SaaS SuiteCommerce sites face additional risks when you reference core modules — this is why we strongly recommend against including them in your extensions. PaaS SuiteCommerce Advanced sites don’t face these risks as much, so developers may be afforded greater leeway, but the risks may be realized later on when it comes to manually migrating the site to a newer version.

For more information on this, see The Technical Differences Between SuiteCommerce and SuiteCommerce Advanced.

How Do I Know When Certain Architectural Changes Were Made?

For the extensibility API, the Extensibility API documentation includes notes for many components and methods on when they were introduced.

You can also check the Architecture and Extensibility API rows in the SuiteCommerce Advanced Feature Compatibility Matrix, which indicates which versions certain architectural aspects are compatible.

Final Thoughts

When it comes to customizing SuiteCommerce Advanced, the rules have changed. And they have been brought in line with the advise we give to SuiteCommerce site developers: upgradeability, reusability and maintainability. We also want to recommend that whatever customizations you make, you evaluate the risk of how it will affect your site when you upgrade and if you were to migrate it to another site.

Keeping a site fresh, using the latest source should be the prize you keep your eye on. However, we're aware that if you're using SuiteCommerce Advanced over SuiteCommerce, there is a good chance that you want to get into the guts of the application — and that's OK — but think about the changes you're making and whether they are things that could be made through extensions or, at least, made in such a way that does not hinder your ability to upgrade. We still encourage you to use the extensibility API and extensions as much as possible. Remember, the API is available throughout the source application, but you will need to have access to the container/application object in order to invoke its components and their methods.