Customization with Hooks
Hooks allow you to alter and extend the behaviour of existing Shopper API resources using the Script API.
For more information on Script API, refer to the following documentation:
Each customizable resource provides
GET requests support
modifyResponse hooks. State changing HTTP methods like POST, PATCH, PUT, and DELETE additionally support
after hooks. The latter also writes transactions to the database accordingly.
Typical use cases are:
before: apply filter criteria for the API execution, and perform status checks.
after: finalize the mutation of an object such as setting status for a payment method or integrate with a third-party system like with an order placement.
modifyResponse: modify the response document to add or remove details.
The Hook List contains available hooks.
To use hooks for Commerce API, first enable it in Business Manager for your B2C Commerce instance.
Navigate to Administration > Global Preferences > Feature Switches and check Enable Salesforce Commerce Cloud API hook execution.
To enable, you must have the Account Manager role of
Business Manager Administrator for the instance.
- Place a
package.jsonfile in the top-level directory of your cartridge.
- In the
package.jsonfile, define the
hooksproperty to the path of the
hooks.jsonconfiguration file. This path is relative to the directory containing the
- In the
hooks.jsonfile, configure an array with the mappings of hooks to their script files with paths relative to the
- For site specific use, register the cartridge to each appropriate site in Business Manager. To customize organization-level resources across all sites, such as libraries, register the cartridge to the Business Manager site.
Hook scripts are loaded as CommonJS modules. Hook functions must be exported. The exported name must match the name of the hook, without the package qualification. For example, the
dw.ocapi.shop.basket.billing_address.beforePUT hook is exported as
For each hook, your code SHOULD return a
Status object to the server. Otherwise multiple registered hook scripts may be executed. If the status is
OK, the server continues processing. If the status is
ERROR, representing a handled exception, the server stops further processing, rolls back the transaction and responds with an HTTP 400 Bad Request fault. When an
ERROR occurs, the server returns a fault to the caller, containing information like the error code, message, and details from the
Status object. Uncaught exceptions in your code including the errors you throw cause an HTTP 500 Internal Error fault; in this case, the server rolls back the transaction.
ERROR occurs, the server returns an RFC IETF rfc7807 ErrorResponse to the caller, containing information like the error code, message, and details from the
The Hook Circuit Breaker protects the system from excessive hook execution failures. For more information, see Hook Circuit Breaker.
The Calculate hook,
dw.order.calculate, enables you to implement customized basket calculation logic. It can be used as the single place for basket calculation and recalculation. This hook provides a default implementation, can be overridden. The default logic of the following hooks implicitly call this hook:
The following code snippet shows a sample call:
In this sample call, the parameters are:
"dw.order.calculate"- the extension point to call
"calculate"- the script function to call
basket- the basket to be calculated
SiteGenesis uses the default implementation of the
dw.order.calculate hook for basket calculation logic.
Using hooks with the Salesforce Commerce API is similar to using hooks with OCAPI, but there are differences developers must be aware of. When you enable and maintain hooks, you must be aware that the same hooks are called for both SCAPI and the related OCAPI endpoints. This is important if you use both API frameworks for your client applications.
Hooks enabled for SCAPI still run under the timeout definition of the SCAPI endpoint. The amount of time that your hook takes to run adds to the overall processing time and the entire response, with the hook execution, and must still complete within the timeout period.
All Shopper APIs have a timeout of 10 seconds, except the Shopper-Products endpoint that has a timeout of 30 seconds.
One of the benefits of SCAPI is its contract-based API definition. It makes responses from SCAPI predictable, able to be documented, and the ability to put an SDK in use for them.
modifyResponse hooks are a powerful way to create a response that best fits the needs of the application. You can add additional information to objects, or provide a more UI-friendly property set to improve the consumption on the client application. However, any changes to the response must fit in the API contract that has been established.
Keep the following in mind when dealing with
- Additional properties must be added only as custom properties (
- Other modifications (deletion or changing of a property) must only occur within the boundaries of the API contract.
With the hooks enabled for SCAPI, the basket calculations built into the B2C Commerce backend are now in play for determining the basket information. There are endpoints created specifically for SCAPI (without hooks) that allowed the manipulation of tax information on the basket.
These endpoints no longer work with the hooks enabled. Calling these endpoints result in a HTTP 409 error response from the request.
When writing your hook logic, it’s important to keep in mind the context of the API that is calling the hook. Both OCAPI and SCAPI share the same hooks, so it’s possible to write a hook that is used for both. Use
request.isSCAPI() to determine SCAPI or OCAPI usage, especially if you’re already using the calculate hook in the context of controllers and use transactions in that hook, as that breaks SCAPI.
To add conditional behaviour to a hook use custom query string parameters. Parameters must be prefixed with
Do not use HTTP headers for conditional behaviour as header values are not used to construct the cache keys for resources.
If a hook errors during processing, the request will fail. You can track hook errors with Log Center. Configure a search using the
category: ( com.demandware.wapi.servlet.ShopRestServlet ) AND stackTrace: ( HookInvocationException ).
As a result of many projects with customers, our community is maintaining a hook collection with many useful implementations to extend functionality or even provide new functionality. The hooks in the community collection cover a wide range of practical use cases. SCAPI supported hooks in the collection are:
For more information, check out the OCAPI Hooks Collection on the Salesforce Commerce Cloud GitHub repository.
The OCAPI Hooks Collection GitHub repository isn’t open source. It’s part of a private collection of repositories for Salesforce Commerce Cloud customers. If you’re unable to access the repository, refer to the Salesforce Commerce Cloud GitHub Repositories and Access documentation in the Salesforce B2C Commerce Infocenter.