Implement custom cart item detail providers

Prev Next

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 needs
  • getContent(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 UIContentContext for each matching cart line
  • stores the returned result in the cart item's cartItemDetail field

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: a UIContent implementation for the detail body
  • actions: a list of BaseUIAction items 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 markdown
  • HtmlContent: 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 row
  • name: stable action name used by the component
  • componentName: Flow API name to launch
  • attributes: 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 MarkdownContent and ScreenFlowAction, 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 recordId as an input variable because the cart passes it automatically
  • any additional attributes should use Flow-compatible names and types such as String, Number, or Boolean
  • 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 provider
  • getContent() returns the expected UIContentResult
  • 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:

  1. Add a product of the mapped type to the cart.
  2. Confirm the cart row shows the expected custom detail content.
  3. If the provider returns an action, click it and verify that the Flow opens.
  4. Complete the Flow and confirm the cart refreshes after the Flow finishes.
  5. Check one product type with no provider mapping to confirm the cart still uses the default detail presentation.