Implementing Rich Card and Carousel Rendering in Bot Responses for Visual Product Selection

Implementing Rich Card and Carousel Rendering in Bot Responses for Visual Product Selection

What This Guide Covers

This guide details the configuration of dynamic bot flows to render interactive product carousels within Genesys Cloud CX Messaging channels. It covers the construction of JSON payloads that define card elements, the integration of external product catalog APIs via Architect HTTP actions, and the mapping of response variables to UI components. Upon completion, you will have a production-ready flow capable of displaying up to ten product cards with images, titles, descriptions, and action buttons, handling empty states and image load failures gracefully.

Prerequisites, Roles & Licensing

  • Platform: Genesys Cloud CX Messaging (Webchat, Facebook Messenger, WhatsApp)
  • Licensing: Genesys Cloud CX Enterprise or Professional with Messaging Add-on. Bot Builder license is required for Architect flow design.
  • Permissions: Bot > Edit, Messaging Channels > Read, External Integrations > HTTP Request.
  • OAuth Scopes: If using a secured product catalog API, the integration must include openid and custom scopes (e.g., product:read) via an OAuth Client Credentials Grant configured in Genesys Cloud.
  • External Dependencies: A RESTful Product Catalog API that returns JSON objects containing id, name, image_url, and price. The image URLs must be HTTPS accessible to prevent rendering failures on mobile devices.

The Implementation Deep-Dive

1. Designing the Messaging Card Payload Schema

The foundation of any rich card implementation is the JSON structure that defines the visual components. Genesys Cloud CX Messaging supports a specific schema for cards which includes text elements, image media, and action buttons. You must construct this payload within the Architect flow rather than hardcoding it in the UI editor to allow for dynamic data population.

The root object of the response must specify the message type as card. The elements array contains individual card definitions. Each element requires a title, subtitle (description), and an image URL. Buttons are defined as sub-elements within each card to handle user actions like “Add to Cart” or “View Details”.

{
  "type": "card",
  "elements": [
    {
      "title": "{{productName}}",
      "subtitle": "{{productDescription}}",
      "image_url": "{{imageUrl}}",
      "button_text": "Purchase Now",
      "button_value": "purchase_action_{{productId}}"
    },
    {
      "title": "{{relatedProductName}}",
      "subtitle": "{{relatedProductDescription}}",
      "image_url": "{{relatedImageUrl}}",
      "button_text": "View Details",
      "button_value": "view_action_{{relatedProductId}}"
    }
  ]
}

The Trap: Many engineers attempt to use standard HTML within the text field of a bot response to style cards. This approach fails on mobile channels and breaks accessibility standards. Genesys Cloud CX parses the type field to determine rendering behavior. If you omit the type key or use an invalid type, the client SDK falls back to plain text, destroying the visual experience. Additionally, image URLs must be valid HTTPS endpoints. HTTP images will block rendering on secure channels like Webchat due to Mixed Content policies enforced by modern browsers. Always validate image URLs against a whitelist in your integration layer before passing them to the bot response.

Architectural Reasoning: We define the payload structure as a variable named rich_card_payload within the Architect flow. This allows us to inject dynamic values from API responses without altering the flow logic during runtime. Using variables ensures that if the product catalog API returns a new field, you can update the mapping logic in one location rather than editing every card definition manually.

2. Integrating External Data via HTTP Request Action

Dynamic content requires fetching data from an external system. In Genesys Cloud CX Architect, this is achieved using the HTTP Request action block. You must configure a connection to your Product Catalog API that authenticates the request and retrieves the relevant product objects.

The HTTP Request action should be configured as follows:

  • Method: GET
  • Endpoint: https://api.product-catalog.com/v1/items/search?q={{search_query}}
  • Authentication: OAuth 2.0 Client Credentials (configured in Genesys Cloud External Integrations)
  • Headers: Content-Type: application/json, Accept: application/json

You must map the incoming user query (stored in the flow variable {{user_input_text}}) to the API search parameter. The response body will contain a JSON array of product objects. This raw response must be transformed into the card payload structure defined in Step 1.

The Trap: A common failure mode occurs when the HTTP Request action times out before the bot responds to the user. Messaging channels have strict timeout limits (typically 5 seconds for Webchat). If your external API is slow or network latency is high, the Architect flow will return an error state. This causes the bot to appear unresponsive or disconnects the session. To mitigate this, you must implement a Timeout setting on the HTTP Request action set to 3000 milliseconds. However, relying solely on timeouts is insufficient for user experience. You must implement a fallback mechanism that returns a static message asking the user to try again later if the API fails, rather than letting the flow terminate abruptly.

Architectural Reasoning: Do not perform string concatenation of JSON within the Architect expression editor. It is error-prone and difficult to maintain. Instead, use the JSON Transform action block or map the API response fields directly into the rich_card_payload variables. This ensures type safety (e.g., ensuring IDs remain strings if required by the UI) and prevents syntax errors in the final payload. If you use Expressions for JSON construction, ensure all variable references are wrapped correctly to avoid null pointer exceptions when a field is missing from the API response.

3. Binding Variables to Card Elements

Once the HTTP request returns successfully, the flow must map the data fields to the card variables defined in Step 1. This occurs within the Set Variable action block following the HTTP Request. You must iterate through the returned array of products and construct a single elements array for the final payload if you intend to show a carousel.

Genesys Cloud CX Messaging supports carousels where multiple cards are displayed horizontally or vertically depending on the channel. To create a carousel, the elements array in the root JSON object must contain multiple card objects. You will need to loop through the API results and append each product as a new element object.

Example logic for mapping:

  1. Initialize rich_card_payload with type: "card" and empty elements: [].
  2. Iterate over {{api_response.body.products}}.
  3. For each product, create an object containing title, subtitle, image_url, etc.
  4. Push this object into the rich_card_payload.elements array.

The Trap: The most frequent error in carousel implementation is exceeding the channel-specific limit for items per page. Facebook Messenger limits carousels to 10 cards. WhatsApp restricts it to 10 as well, but Webchat allows more depending on the SDK version. If you push 20 products into the elements array, the rendering engine will truncate the list silently or fail to render the message entirely. You must implement a filter logic in Architect to slice the array to a maximum of 10 items before constructing the final payload.

Architectural Reasoning: We use the slice expression function within Architect to enforce this limit safely. The expression {{api_response.body.products | slice(0, 10)}} ensures that only the first ten results are processed. This prevents memory bloat in the flow context and guarantees compatibility across all supported messaging channels without requiring channel-specific logic branching.

4. Channel-Specific Rendering Constraints

Different messaging platforms render rich cards with slight variations. Facebook Messenger prioritizes square images, while WhatsApp supports landscape ratios more flexibly. Webchat rendering is determined by the embedded SDK version on your website or application. You must account for these differences in your image asset management strategy.

Configure your product catalog API to return standard aspect ratios (1:1 or 3:2) and ensure image URLs resolve quickly. If an image fails to load, the card layout may break, causing text to overlap or buttons to disappear. You should implement a default fallback image URL in the rich_card_payload if the specific product image is unavailable.

The Trap: Using external CDNs that do not support CORS (Cross-Origin Resource Sharing) headers can cause images to load on mobile devices but fail on desktop Webchat clients due to browser security policies. If you host your own images, ensure the server sends Access-Control-Allow-Origin: * or the specific domain of your webchat embed. Without this header, the card will display a broken image icon, degrading the visual trust of the bot interaction.

Architectural Reasoning: We recommend implementing an image proxy or using a CDN that guarantees CORS headers. In Architect, you can validate the image URL format using a regex expression before including it in the payload. If the regex does not match a secure HTTPS pattern, substitute the variable with a hardcoded default fallback image URL. This ensures a consistent visual state even when upstream assets are misconfigured.

Validation, Edge Cases & Troubleshooting

Edge Case 1: Empty Product Results

The bot must handle scenarios where the search query returns no products. If the API returns an empty array, the elements list remains empty. A card with zero elements renders as a blank message or is ignored by some clients entirely. This confuses users who expect visual confirmation of their search.

Solution: Implement a conditional branch in Architect immediately after the HTTP Request action. Check if the length of the product array is greater than zero using the expression {{api_response.body.products.length > 0}}. If false, route to a standard text response block that states “No products found for your query” and offers navigation options like “Browse Categories”. This ensures the user receives feedback rather than silence.

Edge Case 2: API Latency and Timeouts

Users expect near-instantaneous responses on messaging channels. If the product catalog API is under heavy load, response times can exceed the 5-second handshake limit for Webchat. This results in a connection drop or a generic error message from Genesys Cloud CX.

Solution: Implement a caching layer. Store recent search results in Genesys Cloud Data Objects (Key-Value store) with a short TTL (Time To Live) of 60 seconds. Before calling the external API, check if the data exists in the cache using an HTTP Request to Genesys Cloud Data Objects. If cached, return it immediately. This reduces latency from hundreds of milliseconds to single-digit milliseconds. In Architect, use the Data Object action block to read and write these values alongside the HTTP Request logic.

Edge Case 3: Deep Link Security

When users click “Purchase Now” or “View Details” on a card, they are often redirected to a specific URL. If this URL is constructed dynamically from user input without validation, it becomes vulnerable to Open Redirect attacks. An attacker could manipulate the product ID parameter to redirect users to phishing sites.

Solution: Do not pass raw IDs directly into deep link URLs. Use an internal routing mechanism or a whitelist of allowed domains. In the button_value field, use a tokenized action type rather than a raw URL. For example, set button_value to action_product_view_{{productId}}. Then configure the client-side Webchat SDK handler to map this value to a pre-defined internal route before redirecting to the external site. This ensures that only known, safe destinations are ever reached by the user.

Official References