Using version 2 of the Frontend SDK
Learn about using various features of version 2 of the Frontend SDK.
The Frontend SDK, its integrations, components, and dependencies are ready to use out-of-the-box and should not require further installation. To check if the SDK is successfully installed for your project, or to manually install it, see Installing the Frontend SDK.
API methods
The base SDK provides various methods to interact with the backend extensions API. We recommend using the SDK methods for all backend extension requests because the base SDK lets you configure options such as the locale, currency, endpoint, and extension version, and it maintains these and the user session throughout your application.
All API methods return the SDKResponse type, which has an isError
boolean property that you can use for narrowing. When isError
is false
, the response contains a data
property with the return type from the API hub. When true
, the response contains an error
property that includes the error details. In both responses, the SDKResponse
also contains tracing information for use in debugging and logging.
callAction
The callAction
method lets you make requests to the action extensions. The method takes the expected return type as its generic argument that defines the type of data
returned in the SDKResponse of a successful request. It also accepts the following options:
actionName
- String - Required. The name of the action extension to call. For example, useproduct/getProduct
to call the following extension:{ actions: { product: { getProduct: (...) => { ... } } } }
.payload
- AcceptedPayloadTypes - Optional. A payload object with key-value pairs to be serialized into the request body.query
- AcceptedQueryTypes - Optional. An object of key-value pairs to be serialized into the request query parameters.parallel
- Boolean - Optional. Defaults totrue
. If set totrue
, the action is executed asynchronously. If set tofalse
, the action is added to a queue and executed in sequence. Setting to false is useful for actions that may cause race conditions.customHeaderValue
- String - Optional. The value to assign to thecoFE-Custom-Configuration
header value. Overrides the globalcustomHeaderValue
option set when configuring the SDK.serverOptions
- ServerOptions - Optional for client-side configuration and required for server-side session management. Contains thereq
object of type IncomingMessage andres
object of type ServerResponse with cookies.
The following code example uses the callAction
method to call a custom extension customActions/getCustomerCoupons
with a custom header, query, and payload to be executed in sequence.
You only need to use the callAction
method for custom actions. For commercetools extensions, you can use the sdk.composableCommerce
integration to access the extensions which internally use callAction
and already have the types and parameters completed.
const response = await sdk.callAction<Customer>({actionName: 'customActions/getCustomerCoupons',payload: { customer: { email: 'username@example.com' } },query: { customerId: '4' },parallel: false,customHeaderValue: '{"customerAuthId":9188377992}',});if (response.isError) {setError(response.error);} else {setCustomer(response.data);}
getPage
The getPage
method retrieves the page or redirect data for static and dynamic pages from the API hub. This method is primarily used to fetch the page data from the Studio and render the pages with the Frontend components. This method is used at the catch-all route packages/<projectName>/frontend/app/[locale]/[[...slug]]/page.tsx
. This method accepts the following options:
path
- String - Required. The relative path of the page of which you want to fetch the data. For example,/sale
or/home/best-sellers
.query
- Object - Optional. An object of key-value pairs to be serialized into the URL query parameters. It accepts the value types specified in AcceptedQueryTypes.customHeaderValue
- String - Optional. The value to assign to thecoFE-Custom-Configuration
header value. Overrides the globalcustomHeaderValue
option set when configuring the SDK.serverOptions
- ServerOptions - Optional for client-side configuration and required for server-side session management. Contains thereq
object of type IncomingMessage andres
object of type ServerResponse with cookies.
The following code example uses the getPage
method to get the /sale
page information with a query and custom header:
const response = await sdk.page.getPage({path: '/sale',query: { size: 'M' },customHeaderValue: '{"customerAuthId":9188377992}',});if (response.isError) {const router = useRouter();router.push('/404');} else {setPageData(response.data);}
getPreview
The getPreview
method retrieves the preview data for Studio page previews, used at packages/<projectName>/frontend/app/[locale]/preview/[previewId]/page.tsx
. This method accepts the following options:
previewId
- String - Required. A string representing the ID of the preview to fetch.customHeaderValue
- String - Optional. The value to assign to thecoFE-Custom-Configuration
header value. Overrides the globalcustomHeaderValue
option set when configuring the SDK.serverOptions
- ServerOptions - Optional for client-side configuration and required for server-side session management. Contains thereq
object of type IncomingMessage andres
object of type ServerResponse with cookies.
The following code example uses the getPreview
method to get page preview data with the previewId
and custom header:
const response = await sdk.page.getPreview({previewId: 'p9986b2d', // Replace this with the variable containing the previewIdcustomHeaderValue: '{"customerAuthId":9188377992}',});if (response.isError) {handleError(response.error);} else {setPreviewData(response.data);}
getPages
The getPages
method lets you fetch the page data for a page folder and all its sub-pages. This method is primarily used in B2C projects to generate the sitemap for static pages at packages/<projectName>/frontend/app/[locale]/sitemap-static.xml/route.ts
. This method accepts the following options:
path
- String - Optional. Defaults to/
. The relative path of the page of which you want to fetch the data.depth
- Number - Optional. Defaults to16
. The depth of the page folder tree up to which you want to fetch the data.types
- String - Optional. Defaults tostatic
. The types of pages to fetch.customHeaderValue
- String - Optional. Defaults to an empty string. The value to assign to thecoFE-Custom-Configuration
header value. Overrides the globalcustomHeaderValue
option set when configuring the SDK.serverOptions
- ServerOptions - Optional for client-side configuration and required for server-side session management. Contains thereq
object of type IncomingMessage andres
object of type ServerResponse with cookies.
The following code example uses the getPages
method to get the page data for all pages under the /sale
hierarchy up to two levels deep. For example, /sale
, /sale/shirts
, /sale/shirts/special
, and so on.
const response = await sdk.page.getPages({path: '/sale',depth: 2,customHeaderValue: '{"customerAuthId":9188377992}',});if (response.isError) {handleError(response.error);} else {generateSitemap(response.data.pageFolderStructure);}
Add SDK integrations
It is possible to extend the SDK with the integrations you develop. To do so, set up the integrations in the CommercetoolsSDK
constructor and pass the SDK instance, such as the ComposableCommerce
instance. For example:
//.... Other codeconstructor() {super();// customIntegration is an example name herethis.customIntegration = new CustomIntegration(this);}//.... Other code
Additionally, any custom events must be added to the SDK generic type as a type intersection. For example:
class CommercetoolsSDK extends SDK<ComposableCommerceEvents & CustomIntegrationEvents> {...}
The backend actions must be added to your backend service to extend your extensions API.
The event engine
The commercetools Frontend SDK comes with event management tools to let integrations communicate with other integrations and the user of the integration to add or create an event handler. The source for this functionality is the EventManager
class, extended by the SDK. It is also possible to extend the event types with custom events with the generic argument passed from the SDK.
Following is a description of the three methods available on the SDK to manage event handlers:
trigger
is called to trigger an event, for which an instance of theEvent
class from@comercetools/frontend-sdk
is passed.
An event is constructed witheventName
anddata
. TheeventName
corresponds to the[key: string]
value in@comercetools/frontend-sdk
'sStandardEvents
. In custom eventsdata
corresponds to the type of value set for the event.
For example, to trigger themarketingBannerClicked
custom event,trigger
is called on thesdk
and an event constructed witheventName: 'marketingBannerClicked'
anddata: { id: "<string>" }
is passed.on
is called to add an event handler for an event. The method takes theeventName
andhandler
arguments.
For example, for themarketingBannerClicked
custom event,marketingBannerClicked
is passed for theeventName
argument and a function withevent
parameter of type{ data: { id: "<string>" } }
is passed for thehandler
argument.off
is called to remove an event handler. For example, to persist the handler only for the lifecycle of a particular component.
The function takes the same arguments as theon
function. For it to work, a named function for thehandler
argument must be defined. To successfully pass a named function to thehandler
parameter, theevent
type in the function's argument must be fully typed, as shown in the following examples.
Events are likely to be triggered only during action calls. The integrations you use may also create handlers so they can communicate with other integrations. However, you must be careful to avoid infinite recursion by mistakenly triggering events from event handlers.
The SDK event engine should only be used for events specific to the base SDK and integrations. The standard React events should be used for component events such as onclick
and onchange
.
Create custom events handlers
The commercetools Frontend SDK lets you create custom events that you can trigger from within the application, such as when clicking on a particular component or holding the pointer over it.
By default, event triggers and handlers will exist for the website's lifetime. However, you may want some to exist only during the lifetime of a specific React component. In that case, you must remove the event handlers on component unmounts. Otherwise, events can stack up due to component unmounting and remounting and may attempt to perform state updates on unmounted components, depending on the nature of the custom events.
To understand event handlers better, let's suppose you have a MarketingBanner
component and you want to track how many times the banner image is clicked using the marketingBannerClicked
event. To achieve this behavior, the MarketingBanner
component can use the onClick
React event handler, which triggers the marketingBannerClicked
event.
To add custom event triggers to the SDK event definition, follow these steps:
Create a
MyCustomEvents.ts
file in thepackages/PROJECT_NAME/frontend/sdk
folder with the following content:Custom events type definitionTypeScript// packages/PROJECT_NAME/frontend/sdk/MyCustomEvents.tsexport type MyCustomEvents = {marketingBannerClicked: { id: string };};Add the type you created to the
CommercetoolsSDK
class in the generic SDK argument. The type must be added in the form of an intersection, as shown in the following example:Extend the base SDK type with custom events typeTypeScript// packages/PROJECT_NAME/frontend/sdk/CommercetoolsSDK.tsimport { SDK } from "@commercetools/frontend-sdk";import {ComposableCommerce,ComposableCommerceEvents} from "@commercetools/frontend-composable-commerce";import { MyCustomEvents } from "./MyCustomEvents";class CommercetoolsSDK extends SDK<ComposableCommerceEvents & MyCustomEvents> {...}...Implement the
MarketingBanner
React component. In this example, we're making a simple banner component with an image.MarketingBanner React component implementation with event handlersTypeScript Reactimport Image from 'next/image';import { useEffect } from 'react';import { sdk } from '../../sdk';import { Event } from '@commercetools/frontend-sdk';interface Props {marketingId: string;imageSrc: string;}const MarketingBanner = ({ marketingId, imageSrc }: Props) => {const marketingBannerClickedHandler = (event: Event<'marketingBannerClicked',{id: string;}>) => {// Perform custom event handling logic here.console.log('Marketing banner clicked, id: ' + event.data.id);};const clickHandler = (id: string) => {sdk.trigger(new Event({eventName: 'marketingBannerClicked',data: {id: id,},}));};useEffect(() => {sdk.on('marketingBannerClicked', marketingBannerClickedHandler);return () => {sdk.off('marketingBannerClicked', marketingBannerClickedHandler);};}, []);return <Image src={imageSrc} onClick={() => clickHandler(marketingId)} />;};export default MarketingBanner;We define a function named
marketingBannerClickedHandler
that takes a parameterevent
of classEvent
from the@commercetools/frontend-sdk
library. This class takes theEventName
andEventData
parameters as the generic arguments, matching the event we defined earlier in theMyCustomEvents.ts
file by name (key) and data (value) respectively.Then, we define a function
clickHandler
that constructs themarketingBannerClicked
event and triggers it using thesdk.trigger
method. The event has the following properties:eventName
: the name of the custom event.data
: value of the custom event whereid
is the identifier of the clicked marketing banner.
Then, we use the React
useEffect
hook to callsdk.on
to set up the event handler on component mount andsdk.off
to remove the handler on component unmount by passing the named handler on both occasions.Finally we call the
clickHandler
from theonClick
event of theImage
component.
For more information about how you can extend the SDK with integrations, see Developing SDK integrations.