1 min read

Product Carousel

Last Updated - Platform 25.0 - SDK 20.0

The SDK contains the ProductCarouselWidget which has a component wrapper for the Dynamic Content feature. Both are components and can be used in different contexts.

The Product Carousel should really be named a 'Listing Carousel' as it presents listings not products. It does not have Variant information (at all) so it cannot directly add to cart or have full stock or swatch capabilities.

Dynamic Content

The Product Carousel component wraps a ProductCarouselWidget in a SectionView. It can be presented by the backend as part of a feature's slotContent.


Present a Product Carousel using a SearchResponse URL with the following json:

"type": "url-carousel",
"content": {
"id": "{id}", // Optional id for tracking.
"title": "{title}",
"url": "{search-response-url}",
"customData": { ... }


Sources can be used to present components directly within a SlotView. The Product Carousel component supports any set up method available to the ProductCarouselWidget.

ViewSource(path: "product-carousel", content: ProductCarouselComponentContent(
id: "{id}", // Optional id for tracking.
title: "{title}",
source: .init(...),
customData: ...


The ProductCarouselWidget can be added to a view hierarchy and is a standalone view that manages its own state. It can be set up in a number of ways:

  • With ProductCarouselInput to initialise the widget.
  • With ProductCarouselState for full control of the widget.
  • With ProductCarouselComponentContent similar to input.
  • As a Recently Viewed carousel.


Previously ProductCarouselWidget would be built using a ProductCarouselBuilder but this has been fully deprecated from v25 to allow easier widget container injection. Subclass, inject and customise it's makeMiddleware and makeReducer functions instead.

Container.shared.views.productCarouselWidget.replace { ProductCarouselWidget() }


The widget supports filtering the listings to present before they are presented using the setFilter(...) function. Setting a filter wraps the viewDataMapper so the widget instead uses the viewDataMapperFilter to map and filter the listings to present.

let carousel = ProductCarousel().setupRecentlyViewed()
carousel.setFilter { listing in listing.listingId != listingId }


When a Product Carousel item is tapped:

carousel: product
carouselId: {id}
title: {title}
id: {item.analyticsId}
productId: {item.productId}
listingId: {item.listingId}
sku: {item.variantId}