---
schema_version: "1"
id: 0a99cfe9ce7b39ff849c36c90c9f310d6dd1c7b68937e3f5581ca403ea0b749f
title: Get Started with Salesforce Commerce Extensions
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/commerce-cloud/salesforce-commerce/guides/extensions.md
canonical_url: https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/extensions.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 68e0a4c2dd335c5a3a1c3e0b85b2a07f2d7882c30d6ada08192866f06cca77c8
products:
  - B2B Commerce Developer Guide
  - Salesforce APIs
---
# Get Started with Salesforce Commerce Extensions

Extensions are a mechanism for using Apex to customize the functionality that powers B2B and B2C storefronts. The custom Apex class that implements an extension is called an extension provider.

There are two types of extensions: **domain extensions** and **endpoint extensions**. Domain extensions are related to a functional domain, such as pricing. Endpoint extensions are related to specific Connect API endpoints (resources).

When you implement an extension provider for a domain extension, you affect a functional area, and the customizations that you provide can affect multiple Connect API endpoints. In contrast, when you implement an extension provider for an endpoint extension, you affect only a single Connect API endpoint (resource).

For domain extensions, a provider can extend or _replace_ the default functionality of a commerce domain. Extensions are available for a wide range of commerce domains, including cart, pricing, inventory, and more.

For endpoint extensions, a provider can modify the request and response of the Connect API endpoint, but can't replace the default functionality.

For the complete list of extensions that you can customize, see [Available Extensions](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/available-extensions.md).

**important:** Extensions don’t apply to the B2C Commerce architecture, which uses a different extensibility system called hooks.

## Extensions and Integrations

Extensions represent the next step for Salesforce Commerce extensibility that began with [integrations](https://developer.salesforce.com/docs/atlas.en-us.b2b_b2c_comm_dev.meta/b2b_b2c_comm_dev/b2b_b2c_comm_integration_architecture.htm?q=integrations). Extensions allow you to customize functionality in a more targeted way than integrations. Also, extensions are available for more commerce domains than integrations.

Here’s a summary of the key differences between integrations and extensions:

|                  | Integrations             | Extensions                                                                         |
| ---------------- | ------------------------ | ---------------------------------------------------------------------------------- |
| Coding approach  | Implement Apex interface | Extend Apex base class                                                             |
| Customization    | Replace                  | Extend (for both domain or endpoint extensions) or replace (for domain extensions) |
| Commerce domains | Checkout calculators (4) | Cart/checkout calculators (5), pricing service, other services                     |

**important:** To check whether an extension is generally available, see [Available Extensions](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/available-extensions.md).

Although extensions are now the preferred way to customize Salesforce Commerce, integrations remain fully supported. Currently, payments can’t be customized with an extension.

## Use Cases

Extensions can be used by a wide range of developers. An in-house team or a systems integrator can create an extension provider to make small, targeted changes to a storefront to meet a merchant’s unique business needs. For more comprehensive solutions, a vendor can bundle several extension providers together and distribute them as a package on AppExchange.

Extensions unlock new opportunities to integrate B2C Commerce with other software (such as ERP systems), cut maintenance costs, and deliver great customer experiences.

## Cart and Checkout Calculations

Several domain extensions are designed to support cart calculation use cases, including cart calculations that occur during checkout. These extensions, taken together, comprise the Cart Calculate API. For more information, see [Cart Calculate API](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/cart-calculate-api.md).

## Architecture

In the Salesforce Commerce architecture, extensions can interact with many other parts of the system, including other extensions.

This diagram traces how a domain extension fits into the architecture using Pricing Service as an example.

![Extensions Flow](https://developer.salesforce.com/docs/media/salesforce-commerce/extension-flow.svg)

Let’s look at what’s happening at each stage of the extension flow, as indicated by the corresponding numbers in the diagram:

1. The Pricing Service extension is invoked. An extension can be triggered by a user action, a Connect API request—or even another extension. The extensible code checks to see if an extension provider class is mapped for the specific extension and store. The code that checks the mapping is called an **extension point**. The identifier used to uniquely identify an extension is called an **extension point name** (EPN). The EPN is used to map an extension point to one or more extension providers.
2. If an extension provider class is registered and mapped to the extension point name, the custom Apex in the extension provider class is executed. The extension provider can optionally make API requests.
3. For domain extensions, the extension provider can invoke the default implementation using the `super()` method. If you plan to modify -- but not completely replace -- default functionality, we strongly recommend calling the `super()` method as a best practice to ensure platform compatibility. If we add features, the features are automatically supported in the super() method implementation.
4. The extension provider can optionally invoke other commerce domain functionality, which can also be extended.

Each domain extension has a corresponding base class. Endpoint extensions, in contrast, all extend the same base class, and the extension provider can’t invoke a `super()` method.

## Domain Extension Provider Class Walkthrough

To show how a domain extension provider class is constructed, let’s walk through a series of code snippets. The snippets extend the base Apex class for the Pricing Service extension.

**note:** The actual implementation details are left out of the snippets so that you can follow the structure of the extension class more easily. A working version of this extension class (along with other examples) is available on the [Extension Provider Examples](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/extension-provider-examples.md) page. This example class is provided for illustration purposes only and isn’t designed to represent a realistic use case.

Start by extending the base class, which is [`commercestorepricing.PricingService`](/docs/commerce/salesforce-commerce/references/comm-apex-reference/PricingService.html):

```java
public class PricingServiceSample extends commercestorepricing.PricingService {
    // Extension code.
}
```

You can override the `processPrice` method of [`commercestorepricing.PricingService`](/docs/commerce/salesforce-commerce/references/comm-apex-reference/PricingService.html), which is used on PLPs and PDPs. In this example, we’ve replaced the entire method with custom logic to extract product data, get the price from an external service, and process the pricing response.

```java
    public override commercestorepricing.PricingResponse processPrice(commercestorepricing.PricingRequest request) {

        // Extract product data from the request with custom logic and get the product's price from an external service.

        // Create a pricing response without the default processing.
        commercestorepricing.PricingResponse response = new commercestorepricing.PricingResponse('USD');

        // Process the pricing response with more custom logic.

        // Return the processed pricing response.
        return response;
    }
```

The base class has another method that you can override: `processTransactionalPrice`. Overriding this method affects cart and checkout. For illustration purposes only, we treat this method differently than `processPrice`. Instead of replacing the entire method with custom logic, we call the base method with the `super()` method. Although we’re calling the base method, we can still insert custom logic before and after the `super()` call.

```java
    public override commercestorepricing.TransactionalPricingResponse processTransactionalPrice(commercestorepricing.TransactionalPricingRequest request2) {
        // Get the transactional pricing response using the default implementation of the processPrice method. Although processTransactionalPrice is called unmodified, you can supply it with a modified version of the request.
        commercestorepricing.TransactionalPricingResponse txnResponse = super.processTransactionalPrice(request2);

        // Modify the transactional pricing response with custom logic.

        // Return the modified transactional pricing response.
        return txnResponse;
    }
```

We define a custom private method to get the prices from an external service:

```java
    private Map<String, PriceDataFromExternalService> getPricesFromExternalService(Set<String> productIds){
        // Custom logic.
    }
```

As you can see from this example, for domain extensions, you have the flexibility to create extension classes that can:

- Replace the entire default implementation of each base class method with custom logic.
- Add custom logic before calling the default implementation of a base class method.
- Add customer logic after calling the default implementation of a base class method.
- Add custom methods and classes.

To learn how to add your own Apex classes to a Salesforce org, see [Adding an Apex Class](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_qs_class.htm).

## Endpoint Extension Provider Class Walkthough

All endpoint extension provider classes extend the [ConnectApi.BaseEndpointExtension](/docs/commerce/salesforce-commerce/references/comm-apex-reference/BaseEndpointExtension.html) class.

### Virtual Methods

The `ConnectApi.BaseEndpointExtension` class defines the following virtual methods:

- `global virtual ConnectApi.EndpointExtensionRequest beforeGet(ConnectApi.EndpointExtensionRequest request)`
- `global virtual ConnectApi.EndpointExtensionResponse afterGet(ConnectApi.EndpointExtensionResponse response, ConnectApi.EndpointExtensionRequest request)`
- `global virtual ConnectApi.EndpointExtensionRequest beforePost(ConnectApi.EndpointExtensionRequest request)`
- `global virtual ConnectApi.EndpointExtensionResponse afterPost(ConnectApi.EndpointExtensionResponse response, ConnectApi.EndpointExtensionRequest request)`
- `global virtual ConnectApi.EndpointExtensionRequest beforePatch(ConnectApi.EndpointExtensionRequest request)`
- `global virtual ConnectApi.EndpointExtensionResponse afterPatch(ConnectApi.EndpointExtensionResponse response, ConnectApi.EndpointExtensionRequest request)`
- `global virtual ConnectApi.EndpointExtensionRequest beforePut(ConnectApi.EndpointExtensionRequest request)`
- `global virtual ConnectApi.EndpointExtensionResponse afterPut(ConnectApi.EndpointExtensionResponse response, ConnectApi.EndpointExtensionRequest request)`
- `global virtual ConnectApi.EndpointExtensionRequest beforeDelete(ConnectApi.EndpointExtensionRequest request)`
- `global virtual ConnectApi.EndpointExtensionResponse afterDelete(ConnectApi.EndpointExtensionResponse response, ConnectApi.EndpointExtensionRequest request)`

For each HTTP method, the base class provides a `before` and `after` method. You can override `before` methods to modify the request before the Connect API endpoint is called. And you can override `after` methods to modify the response of the Connect API endpoint after it's called.

### ConnectApi.EndpointExtensionRequest

The [ConnectApi.EndpointExtensionRequest](/docs/commerce/salesforce-commerce/references/comm-apex-reference/EndpointExtensionRequest.html) object wraps the request payload for the Connect API endpoint request. This object provides the following methods:

- `global Object getParam(String name)` -- get the value for a parameter name.
- `global void setParam(String name, Object value)` -- set the value for a parameter name.
- `global Set<String> getKeys()` -- return all parameter names in the request.

### ConnectApi.EndpointExtensionResponse

The [ConnectApi.EndpointExtensionResponse](/docs/commerce/salesforce-commerce/references/comm-apex-reference/EndpointExtensionResponse.html) object wraps the response payload returned by the Connect API endpoint, and provides the following method:

- `global Object getResponseObject()` -- returns the Connect API response wrapped as an Object.

### Manipulating Requests and Responses

To manipulate a request or response, you cast the request or response to a type that's expected for the Connect API endpoint.

For example, let's consider the [Commerce Webstore Account Addresses](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_commerce_webstore_accounts_addresses.htm) Connect API endpoint.

This endpoint has an HTTP GET method and an HTTP POST method. Therefore, in your extension provider class for this endpoint, you can override the `beforeGet`, `afterGet`, `beforePost`, and `afterPost` methods.

To handle the requests and responses, you must know the Apex types for the various inputs and outputs.

In this example, the GET method doesn't take an input, but the request URL can specify multiple URL parameters.

The GET method returns a [Commerce Address Collection](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_responses_commerce_address_collection.htm) output. Within your Apex code, you reference this type as `ConnectApi.CommerceAddressCollectionRepresentation`.

The POST method takes an input, but the request URL doesn't specify URL parameters. The POST method takes a [Commerce Address Input](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_requests_commerce_address_input.htm) input. Within your Apex code, you reference this type as `ConnectApi.CommerceAddressInputRepresentation`.

The POST method returns a [Commerce Address](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_responses_commerce_address_output.htm) output. Within your Apex code, you reference this type as `ConnectApi.CommerceAddressOutputRepresentation`.

In the `beforeGet` method, you can access the URL parameters in the request like this:

```java
// Getting the value of the sortOrder request parameter
String mySortOrder = request.getParam('sortOrder');
```

In the `afterGet` method, you access the body of the response like this:

```java
// Cast the response object to the type returned by Connect API endpoint
ConnectApi.CommerceAddressCollectionRepresentation output = (ConnectApi.CommerceAddressCollectionRepresentation)response.getResponseObject();
```

In the `beforePost` method, you can access the request like this:

```java
// Cast the request body to the input type for the Connect API endpoint
// Notice the lowercase "c" in the argument to getParam()
ConnectApi.CommerceAddressInputRepresentation input = (ConnectApi.CommerceAddressInputRepresentation)request.getParam('commerceAddressInputRepresentation');
```

Lastly, in the `afterPost` method, you can access the response like this:

```java
// Cast the response object to the type returned by Connect API endpoint
ConnectApi.CommerceAddressOutputRepresentation output = (ConnectApi.CommerceAddressOutputRepresentation)response.getResponseObject();
```

After you create a variable for the request or response, you can access the properties of the request and response with getters and setters. Each property has a corresponding getter and setter.

For example, you can access the `count` property of the `ConnectApi.CommerceAddressCollectionRepresentation` response like this:

```java
ConnectApi.CommerceAddressCollectionRepresentation output = (ConnectApi.CommerceAddressCollectionRepresentation)response.getResponseObject();
Integer myCount = output.getCount();
```

## Manage Extensions with Salesforce CLI

After adding an extension class to a Salesforce org, there are two more tasks required before you can fill an extension slot with a custom extension provider:

1. Register the extension class.
2. Map the extension class to a B2B store.

The easiest way to register and map extension classes is with Salesforce CLI and the Salesforce Commerce plug-in for `sf`.

**important:** To manage extensions, you must use the latest version of Salesforce CLI. For detailed instructions, see [Install Salesforce CLI](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_install_cli.htm) and [Update Salesforce CLI](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_update_cli.htm).

To install the plug-in, run `sf plugins install @salesforce/commerce`.

Example commands:

```bash
# Register an extension class
sf commerce:extension:register --targetusername pia@northerntrailoutfitters.com --apex-class-name PricingDemoService --extension-point-name Commerce_Domain_Pricing_Service --registered-extension-name PricingDemoService

# Map an extension class
sf commerce:extension:map --registered-extension-name PricingDemoService --store-id 0ZETC000000DflJ4AS

# Unmap an extension class
sf commerce:extension:unmap --registered-extension-name PricingDemoService --store-id 0ZETC000000DflJ4AS
```

For detailed installation and usage information, see the plug-in’s [README](https://github.com/forcedotcom/commerce-on-lightning).

### Alternate Methods

You can also register and map an extension provider by inserting custom Apex into sObjects. The setup process for extensions is similar to the [setup process for integrations](https://developer.salesforce.com/docs/atlas.en-us.b2b_b2c_comm_dev.meta/b2b_b2c_comm_dev/b2b_b2c_comm_integration_setup.htm). To register an extension provider, modify [RegisteredExternalService](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_registeredexternalservice.htm) and to map an extension provider, modify [StoreIntegratedService](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_storeintegratedservice.htm).

### Commerce Extensions Resources

Developers can register an extension Apex class and map it to a web store using the Commerce Extensions resources. To accomplish this, make a POST request to the [Commerce Extension Providers API](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_extension_providers.htm) to register the extension class. Then, make a POST request to the [Commerce Extension Mappings API](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_extension_mappings.htm) to map the extension class to the store. To unmap the extension class, send a DELETE request to the [Commerce Extension Mapping API](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_extension_mapping.htm).

### User Interface

Merchants can map and unmap domain extension providers directly in the administration interface. See [Replace a Default Commerce Process with an Apex Class](https://help.salesforce.com/s/articleView?id=commerce.comm_extensions.htm&type=5) on Salesforce Help.

## Next Steps

In this guide we’ve explored how Salesforce Commerce extensions give you fine-grained control over storefront functionality. We’ve examined how extensions fit into the Salesforce Commerce architecture. We've walked through the construction of an example extension provider. We've also described the methods for registering and mapping extension providers.

Now that you have a solid understanding of extensions, the next steps are to:

- Explore the [Extension Provider Examples](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/extension-provider-examples.md).
- Explore the list of [Available Extensions](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/available-extensions.md) and look up the base Apex classes that are relevant to your application.
- Learn more about extension development and testing with other guides, including:
  - [Write Tests for an Extension Provider](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/write-tests-for-an-extension-provider.md)
  - [Mock the Base Apex Class](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/mock-the-base-apex-class.md)
