This article is for Apex developers, implementation partners, and solution architects who need to supply product-type-specific detail content in the storefront shopping cart.
Use a custom cart item detail provider when the standard cart row title and subtitle are not enough and the cart needs to show derived detail text, rich text, or a supported row-level action for a specific product type.
When to build a custom provider
Build a custom provider when cart detail content depends on cart-item data or product type.
Typical use cases include:
- showing derived detail text that is different for each product type
- summarizing product-specific configuration choices in the cart row
- exposing a supported screen-flow action such as a guided edit or review step
- replacing the default grouped or addon detail block with product-type-specific content
If you only need to choose which provider applies to which product type, use the configuration article instead of building a new provider.
How the provider contract works
A cart item detail provider is an Apex class that implements IUIContentProvider.
The interface has two responsibilities:
getRequiredFields()declares which cart-item fields your provider needsgetContent(UIContentContext context)returns the content and actions that the cart should render
At runtime, the shopping cart controller automatically:
- gathers the required fields declared by configured providers
- includes those fields when cart items are loaded
- creates a
UIContentContextfor each matching cart line - stores the returned result in the cart item's
cartItemDetailfield
Your provider does not query cart items directly for this use case. Instead, it declares the fields it needs and reads them from the provided context.
Declare required cart-item fields
Use getRequiredFields() to return the exact Schema.SObjectField tokens that your provider reads later in getContent().
Example:
public List<Schema.SObjectField> getRequiredFields() {
return new List<Schema.SObjectField>{
Shopping_Cart_Item__c.Name
};
}
Keep this list precise. The runtime only guarantees access to fields that your provider registered here.
Inside getContent(), read values through UIContentContext.getValue(fieldToken).
String itemName = (String) context.getValue(Shopping_Cart_Item__c.Name);
If getContent() tries to read a field that was not returned from getRequiredFields(), the context throws a developer exception. Register every field before you use it.
Return content and actions
Your provider returns a UIContentResult. This result contains two public parts:
content: aUIContentimplementation for the detail bodyactions: a list ofBaseUIActionitems for row-level actions
A provider can return content, actions, or both.
Supported content types in the cart
The cart detail renderer supports these content types:
MarkdownContent: rendered as formatted markdownHtmlContent: rendered as rich text
Return only supported content types for cart item detail. Unsupported content types are not rendered by the shared cart detail renderer.
For most implementations, MarkdownContent is the simplest choice for readable multi-line detail text. Use HtmlContent when the cart detail needs markup that is better expressed as rich text.
Supported action type in the cart
The cart detail experience publicly supports ScreenFlowAction.
A ScreenFlowAction supplies:
label: button label shown in the cart rowname: stable action name used by the componentcomponentName: Flow API name to launchattributes: optional additional Flow input variables
When a buyer clicks a screen-flow action, the cart component opens the Flow in a modal dialog.
The component always passes a recordId Flow input variable automatically. Its value is the current cart item record ID. Any action attributes you define are appended as additional Flow input variables.
After the Flow finishes with a FINISHED or FINISHED_SCREEN status, the cart publishes the RefreshShoppingCart message so the cart reloads its data.
Minimal provider example
This example shows a provider that reads the cart item name, returns markdown detail text, and exposes a screen-flow action.
public with sharing class CustomCartItemDetailProvider implements IUIContentProvider {
public List<Schema.SObjectField> getRequiredFields() {
return new List<Schema.SObjectField>{ Shopping_Cart_Item__c.Name };
}
public UIContentResult getContent(UIContentContext context) {
String itemName = (String) context.getValue(Shopping_Cart_Item__c.Name);
UIContentResult result = new UIContentResult();
result.content = new MarkdownContent('**Cart item**\n' + '- Name: ' + itemName);
ScreenFlowAction action = new ScreenFlowAction(
'Review Details',
'reviewDetails',
'Review_Cart_Item_Details'
);
result.actions.add(action);
return result;
}
}
This example stays on the supported contract:
- it implements
IUIContentProvider - it declares the field it reads
- it reads the value through
UIContentContext - it returns
UIContentResult - it uses
MarkdownContentandScreenFlowAction, which the cart detail experience supports
Screen Flow action requirements
If your provider returns a ScreenFlowAction, validate the target Flow against the cart component's behavior.
Use these rules:
- the Flow API name must be supplied in
componentName - the Flow should accept
recordIdas an input variable because the cart passes it automatically - any additional attributes should use Flow-compatible names and types such as
String,Number, orBoolean - if the Flow updates cart data, let the Flow finish normally so the cart refresh event can run afterward
If an action is not a ScreenFlowAction, the standard cart item detail component does not execute it.
Map the provider to a product type
Deploy the provider class first, then map it to the relevant Web Product record type through the cart item detail override configuration.
Each cart line uses the provider configured for its product type. If no provider is mapped for a product type, the cart continues using its default detail presentation for that line.
For the mapping steps, see the configuration article:
- Configure cart item detail content overrides
Testing and validation guidance
Test the provider at two levels.
Unit test the Apex provider
Add Apex tests that verify:
getRequiredFields()returns every field used by the providergetContent()returns the expectedUIContentResult- markdown or html content is populated as expected
- screen-flow actions include the expected label, name, Flow API name, and optional attributes
Also include at least one negative test for field access discipline. If the provider depends on a field, that field should be present in getRequiredFields().
Validate the storefront behavior
After you map the provider to a product type, validate the cart end to end:
- Add a product of the mapped type to the cart.
- Confirm the cart row shows the expected custom detail content.
- If the provider returns an action, click it and verify that the Flow opens.
- Complete the Flow and confirm the cart refreshes after the Flow finishes.
- Check one product type with no provider mapping to confirm the cart still uses the default detail presentation.