# Using a session commercetools Frontend provides a session mechanism for its [extensions](/frontend-development/extensions.md). Action extensions can read and write the session, while data source and dynamic page handler extensions can only read the session. You can [write the session](/frontend-development/using-a-session.md#write-the-session) by setting the `sessionData` property on the response returned from the action extensions. Then, you can [read the session](/frontend-development/using-a-session.md#read-the-session) from the `sessionData` property on the extension's incoming request object. The session mechanism is meant for server functions. Frontend components can't access the session directly. If you only need to conserve data for the frontend, use [cookies](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie), [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), or a similar mechanism. By default, a session expiration date is not set. ## Write the session The Action extensions receives the `Request` and `Response` objects as function argument. The mechanics to write the session works as follows: 1. The action code ensures to have properly initialized `sessionData`. 2. During the execution of the action, the session data is updated (in this case, the value `42` is stored). 3. The extension returns `sessionData` as part of the `Response`. To avoid failures, store only necessary information in the session. Although you can store up to 4 KB of arbitrary data in the session (any write operation that exceeds this limit will fail with a warning in the browser console), we recommend that you keep the data stored in session tokens to a minimum. This is because these tokens are included in every request that is sent to the API hub and in its corresponding responses. For example, if you want to persist with using customers' cart information in the session instead of storing the entire cart object, then write `cartId` in the session and fetch the cart information by using `cartId` from the API hub. Do not include sensitive or personally identifiable information (PII) in sessions because these details are stored in customers' web browsers. Even though payloads are encrypted, we do not recommend including such data in payloads. The example below shows an action `saveCartIdInSession` saving the `cartId` to the session object. ```typescript title="Implementing the action extension" export default { actions: { saveCartIdInSession: async ( request: Request, actionContext: ActionContext ): Response => { const sessionData = { cartId: '42', ...(request.sessionData || {}), }; return { body: actualActionResult, statusCode: 200, sessionData, } as Response; }, }, }; ``` If you return `sessionData` from an action, you need to maintain all session information, even that which has not been updated. If you only return the `sessionData` with the keys added by the action, the existing session data will be lost because commercetools Frontend doesn't perform merge on the session but only stores the returned `sessionData`. When multiple action calls write the session, the last action call to finish executing defines the outcome. Since this might lead to unexpected behavior in asynchronous and non-deterministic implementations, we recommended using the `sdk.callAction()` [method](/frontend-development/developing-an-action-extension.md#perform-the-fetch-call). It handles sequential execution of multiple action calls automatically using a queue and provides a deterministic outcome. ## Read the session Any extension can read the `sessionData` since it's part of the `Request` object. An Action extension receives the `Request` directly as its input. Other extensions (data source and dynamic page handler) receive the `Request` as part of their corresponding `context` object. Direct session access in the frontend code is prohibited as the session might contain sensitive data, such as access tokens. Thus, the session JSON Web Token (JWT) is encrypted in the production environment. To use parts of the session in a Frontend component, you can expose these parts selectively through a data source or action. For example, you can use the following data source extension to read the tracked `cartId`. The `DataSourceContext` carries the `Request`, which in turn carries `sessionData` (that might be empty if no session was written before). ```typescript title="Implementing the data source extension" export default { 'data-sources': { 'example/get-cart-id': ( configs: DataSourceConfiguration, context: DataSourceContext ): DataSourceResult => { console.log('Session data', context.request.sessionData?.cartId); return { dataSourcePayload: { cartId: context.request.sessionData?.cartId, }, }; }, }, }; ``` A Frontend component can use the exposed part of the `sessionData` after [the data source is registered in the Studio](/frontend-development/developing-a-data-source-extension.md), for example: ```typescript title="Implementing the React component" import React from 'react'; type ShowCartIdTasticProps = { data: { cartId: string; }; }; const ShowCartIdTastic: React.FC = ({ data }) => { return !data?.cartId?.dataSource ? (
No cart Id available. Please continue to use our page!
) : (
The active cart Id is {data?.cartId?.dataSource}
); }; export default ShowCartIdTastic; ``` ```json title="Frontend component schema" { "tasticType": "example/show-cart-id", "name": "Show active cart Id", "icon": "star", "description": "A frontend component showing the active cart Id", "schema": [ { "name": "Data source", "fields": [ { "label": "Active cart Id", "field": "cartId", "type": "dataSource", "dataSourceType": "example/get-cart-id" } ] } ] } ``` ## Related pages - [Area overview page with navigation](/frontend-development.md) - [Previous page: Dynamic filters for data sources and dynamic pages](/frontend-development/dynamic-filters-for-data-sources-and-dynamic-pages.md) - [Next page: Composable Commerce extension](/frontend-development/using-the-commercetools-extension.md)