# Extension Patterns
SF B2B Commerce consists of a bunch of elements put together to work as a system:
- The front end runs on "Visualforce Communities" and is executed from VF pages/components...but it's 99% backbone and handlebars, not your usual Visualforce stuff. As of 4.10. it's not Lightning either.
- The core functionality runs on the Salesforce "Lighting Platform" and is a large collection of APEX classes (Global APIs, Logic Classes, Service Classes, Extension points, etc.)
- The way these two talks is via remote actions implemented through APEX classes (controllers) that interact with the VF community.
For simplicity, we'll split the Visualforce Community part in two: The Front End (for the VF Pages, components and stuff), and the Back End (for the controllers)
Salesforce experts vs. non-salesforce experts
People who are familiar with Salesforce applications may not (or want to) understand the non-salesforce elements (and concepts) included in B2B Commerce. Likewise, people who are familiar with B2B or Java, or Javascript may not "get" the salesforce parts.
As a result, storefronts ends up with an unbalanced amount of customizations over OOTB capabilities. Sometimes there are valid reasons for this (e.g. performance or user experience), but more likely than not, they'll be re writing existing functionality (just because they didn't have the patience to understand how B2B commerce works OOTB).
Consult with B2B SF B2B Services or SF B2B Commerce expert to verify what are the OOTB capabilities and how much of them can be used to cover your business needs.
# Extending the Front End
There are different ways to extend the way SF B2B Commerce in order to adapt it to your business needs. Based on your team maturity level, we can suggest the following patterns:
- The "Classic" Pattern
- Using External Handlebars
- Going Headless
About the metadata
In order to fit business needs, it is very common to have additional fields added to the CC Objects (and mofify the related cc classes to do something on them). When you do so, make sure these changes are properly reflected in your code repo. It is not common to modify the cc classes to use other objects instead of the cc ones (e.g. replacing ccrz_products with products2). The reason is that there are a lot of relationships and underlying queries that may be broken if the recommended cc objects are not used. It's better to use integration endpoints instead (e.g. a job, trigger or flow that syncs ccrz_products with products2)
# Pattern 1: The "Classic" Pattern
This is what the average Consulting company and the SF B2B Services team will always suggest.
- Extend the VF Community FE using Page Include settings that maps to VF Pages and VF Components. Also, create the essential theme for your storefront and the layouts.
- Create custom Apex controllers for any new remote action needed. Call these controllers from your page includes.
- Create any extensions needed for the CC logic, CC services, CC hook classes.
Pros:
- It's closer to what the SF B2B Services team best practices are
- More support than the other approaches
Cons:
- Lots of configurations settings needed in order to enable the customizations. It's easier to miss them.
- Slowest (allegedly) to both develop and at runtime
# Pattern 2: Using External Handlebars
If you have a complex front end (and/or a good front end team), you can take advantage of the fact that B2B commerce FE is "just javascript" to change the source of your handlebars templates.
- Similar to the classic approach, but all your custom UI and Front end will be in your custom theme (or a CDN if you prefer so).
- Create one custom Apex controller for all new remote actions needed. Call these one controller from a VF page/component available across your storefront (e.g. header or footer).
- Create any extensions needed for the CC logic, CC services, CC hook classes.
Pros:
- No more configuration settings for page includes (as long as no additional controllers needed)
- The theme drives not only the stylesheets, but most of the look and feel (making the UI more portable)
- One stop for all your remote actions under one controller
- Handlebars can be compiled into one js for extra performance (and it can be cached in the browser for even better performance!)
Cons:
- Workarounds needed to reduce the dependency on backbone code (e.g. using handlebars helpers instead of jQuery)
- Less support from the SF B2B Services team
# Pattern 3: Headless
Visualforce, backbone, jQuery, bootstrap...they are all dinosaurs (allegedly). The reality is that finding good developers interested into using these old school technologies is getting harder. The preference will always be towards the more modern standard/technologies, like lightning, react.js or vue.js (as of 2019). It helps their careers, and is also easier to find community support for them as well. Here is how this can be achieved:
- Create a custom experience in your framework of choice. Host it in your server of choice.
- Similar to the other patterns, create one or more custom Apex controller class(es) for all the actions needed (most likely Aura for Salesforce or REST services for external hosts). You could even try to take it one step farther and use GraphQL.
- Create any extensions needed for the CC logic, CC services, CC hook classes.
Pros:
- Bring your own front end
- Most likely, better user experience
- Reduces the dependency on Salesforce B2B since the whole thing is delivered via service APIs
Cons:
- The whole front end is a blank canvas. More effort needed in both creating and integrating it
- May require a custom CSR experience
- May trigger governor limits faster
- Way less support from the SF B2B Services team
CC Pages vs Headless
- CC Pages are technically not headless. They are another way to create your own VF Page experience. Underneath, they still have access to the user context, the storefront theme and common functionality, etc.
- CC Pages also run on top of a Salesforce instance, wherever the org is.
Using CC Pages
Overall, we should not recommend CC pages in the long term, unless new pages needed. Instead, create custom template layouts and handlebars overrides, so you take better advantage of what's OOTB. Otherwise, consider going the headless route.
# Extending the Back End
WIP
# Extras
# The Product Catalog Performance
WIP <!-- To increase performance in Salesforce, sometimes is best to move away from it. No, we are not saying go do your ecommerce somewhere else, but instead to look outside the box and complement the OOTB capabilities.
The default functionality of using a Product "index" is fast relatively to Salesforce, but it is not fast for complex queries or with larger amount of data. Yes, Salesforce constantly tries to make it faster, and yes, you can spend some time trying to work around the guardrails here: https://resources.docs.salesforce.com/latest/latest/en-us/sfdc/pdf/b2b_commerce_guardrails_cheatsheet.pdf. But if you can't wait, you have alternatives.
Here is an idea:
We can make it more performant by using an external database instead of a salesforce one.
- Set a relational database (e.g. PostgreSQL) to hold your product index data
- Extend ccLogicPICreate to save in this external database
- Create any extensions needed for the CC logic, CC services, CC hook classes (e.g. ccServiceProductIndex) to read from the external database instead of the internal mechanism
- You can use something similar for other Salesforce objects. Just be wary of the security model 😉
-->
# Improving Integrations
Typically, you will have apex classes that calls your integration endpoints (e.g. SAP orders, FedEx shipments, Payment Gateways, etc.). They may require different setups and implementations (e.g. json vs soap, get vs post, etc.) and may not always mechanisms for caching, failovers, reporting and whatnot.
It's better if you could have an standardized way to access your enterprise systems, dictated by your business needs/industry standards, not the software provider. One option is to use "Enterprise Services Bus", like Dell Boomi, Mulesoft, etc. With it, you have now the ability to design the APIs that makes the most sense to the solution, taking away all the underlying complexity so implementation teams can deliver faster.
E.g. instead of having a POST to a SOAP service in SAP, a GET to a REST service to Fedex, etc. you can now have everything under a RESTFUL interface, and hide from Salesforce whether you are connecting to SAP, Fedex, or whatever.
References: