Overview

The commercetools Frontend SDK is a set of tools consisting of the base SDK and integrations that improve the overall developer experience when working with extensions. It provides an interface to easily communicate with these services with persistent configuration, automation, and types for payloads, queries, and returns.

The following diagram illustrates the interaction between the SDK components (on the right) and the API hub along with extensions (on the left). It highlights how domain types are shared between an SDK integration (in this example, Composable Commerce) and the extensions.

Architectural diagram of SDK components and backend code

Base SDK

The commercetools Frontend SDK is set up within a template class, which extends the base SDK: @commercetools/frontend-sdk. After the SDK is configured, it manages the configurable options such as endpoint, locale, currency, and extension version, and it relays these options to the underlying utilities. For example, to HTTP headers and additional query parameters.

The base SDK is also responsible for handling cookies, errors, event management, integration interfaces, page API methods, and calls to the action extensions. For calling the action extensions and interacting with integrations, it provides the callAction method. The base SDK is generic in nature, it doesn't specify the domain types (such as Cart or Wishlist), particular action names, or other requirements out-of-the-box but provides the tools for the SDK integrations to flexibly fill in the missing type information.

The base SDK also includes an event manager, which lets SDK integrations add event handlers and communicate with each other. It also lets you add custom event handlers to meet your use cases, such as tracking global events across the application.

SDK template file

The SDK template file located in your project at packages/PROJECT_NAME/frontend/sdk/CommercetoolsSDK.ts is the single source of truth for setting up and using the base SDK and integrations.

We strongly recommended using this file because it enforces best practices and battle-tested design patterns. These design patterns include the setup of the integration events, and the initialization of the integrations ensuring all components of the SDK behave as singletons throughout your project. It also provides a space to set up global rules for events (in the constructor), and contains further documentation in the file's comments.

SDK template file codeTypeScript
import { SDK } from '@commercetools/frontend-sdk';
import {
ComposableCommerce,
ComposableCommerceEvents,
} from '@commercetools/frontend-composable-commerce';
import { getLocalizationInfo } from 'project.config';
// Add other integration's custom events to the SDK's generic type here,
// by extending ComposableCommerceEvents with their type using an intersection.
// For example, <ComposableCommerceEvents & OtherEvents>.
// You may also wish to add your own custom events.
class CommercetoolsSDK extends SDK<ComposableCommerceEvents> {
composableCommerce!: ComposableCommerce;
// Add any other integrations here.
constructor() {
super();
this.composableCommerce = new ComposableCommerce(this);
// Initialize your other integrations here.
this.on('errorCaught', (event) => {
// Globally handle any errors caught by the SDK and integrations. For
// example, log error, fire notification, etc.
console.log('SDK error: ', event.data);
});
// Set up any other custom global event handlers here.
// Ensure types are created and added to the SDK generic type
// if specific to your project.
}
// A simplified, reusable method for configuring the SDK, as for
// most cases only the locale and currency require input from runtime, or
// may change on user input.
defaultConfigure(localeString: string) {
const { locale, currency } = getLocalizationInfo(localeString);
sdk.configure({
locale,
currency,
extensionVersion: process.env.NEXT_PUBLIC_EXT_BUILD_ID ?? 'dev',
endpoint: process.env.NEXT_PUBLIC_FRONTASTIC_HOST
? process.env.NEXT_PUBLIC_FRONTASTIC_HOST!.split('/frontastic')[0]
: '',
});
}
}
// Create a single instance of the SDK.
const sdk = new CommercetoolsSDK();
// Export only the instance to serve as a singleton throughout the project.
export { sdk };

The key aspects of this file are the following:

CommercetoolsSDK class and ComposableCommerceEvents type

The CommercetoolsSDK template class extends the main base SDK class from @commercetools/frontend-sdk. The base SDK provides the CommercetoolsSDK class with the methods and properties available in the SDK.

The ComposableCommerceEvents type is passed to the generic SDK argument. The ComposableCommerceEvents type comes from the Composable Commerce integration package and specifies the types of any custom events of this particular package. In the base SDK, this type is then combined with the StandardEvents type with a type intersection.

If an event is not defined or passed to the generic SDK argument, trying to trigger the event or add a handler will cause a TypeScript compilation error.

The following code specifies the events type format and an CustomEventTriggers as an example event type.

Extend a event type with custom typesTypeScript
export type Events = {
[key: string]: {
[key: string]: unknown;
};
};
export type CustomEventTriggers = {
someEventTriggered: { time: string };
someComponentClicked: { posX: number; posY: number };
};

CommercetoolsSDK.ts constructor

The CommercetoolsSDK.ts constructor does the following tasks:

  • Initializes the Composable Commerce integration by passing the SDK instance to the constructor in the form of this. This ensures that event triggers and handlers are set on the single instance of the @commercetools/frontend-sdk SDK and that actions called on the integration use the same SDK instance that was configured.
  • Sets up an event handler for the errorCaught event, which is triggered by the @commercetools/frontend-sdk SDK when an error occurs.
    You can also set other globally managed custom event handlers in the constructor. You can use this for global error handling, such as logging the error or triggering a notification. You can also deactivate the handler by commenting it out.

The SDK doesn't throw any errors. It returns the SDKResponse<T> type, { data: T, isError: false } on success or { isError: true, error: FetchError } on error.

Instance of the CommercetoolsSDK class

Instead of exporting the CommercetoolsSDK class, we create an instance of the class and export it. This ensures that once configured, the SDK integrations and event handlers are initialized and added only once.

If you create multiple instances of the CommercetoolsSDK class, the errorCaught handler will be added continuously and executed as many times as constructed. Furthermore, some integrations may add event handlers upon construction. Creating multiple instances of integrations will cause the same side-effect.

SDK integrations

Unlike the base SDK, the SDK integrations are provided as editable code. This gives you full control over the actions and their types, ensuring that if extensions are modified or built on, the SDK integrations are kept in sync. SDK integrations implement the base SDK integration interface and are initialized with a singleton instance of the base SDK. They are set up within the template file as singleton instances, and stored as properties, allowing the setup of events to be globally handled.

SDK integrations primarily utilize the base SDK's callAction method to write action calls for each extension by providing the return type, query, and payload parameters. SDK integrations may also trigger events on successful action calls. You can add event handlers to your website in the SDK template file, such as productAddedToCart. Event handlers can also be temporary, tied to the lifecycle of a React component.