# App Block Storefront Events

Retail Cloud Connect™ App Blocks emit browser events for storefront integrations that need to react to search, collection, product-card, or conversational UI activity.

Use these events for small client-side integrations such as analytics, theme UI updates, custom success messages, debugging, or coordinating another script with the rendered search grid. They are integration hooks; they should not replace Retail Cloud Connect cart, search, or chat logic.

<br/>

## Browser Events

| Event                                    | Target     | App Block                    | Fired when {.compact}                                                                                           |
| ---------------------------------------- | ---------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `retail-connect:products:load:start`     | `window`   | Search Results, Product Grid | A product search or collection request starts.                                                                  |
| `retail-connect:products:load:success`   | `window`   | Search Results, Product Grid | Product results and result metadata have loaded successfully.                                                   |
| `retail-connect:products:load:failure`   | `window`   | Search Results, Product Grid | Product results fail to load.                                                                                   |
| `retail-connect:search-grid:ready`       | `document` | Search Results, Product Grid | The product grid has rendered and reached the next animation frame.                                             |
| `retail-connect:add-to-cart:success`     | `window`   | Product cards                | Shopify accepts a product-card add-to-cart request.                                                             |
| `retail-connect:add-to-cart:failure`     | `window`   | Product cards                | Shopify rejects the add-to-cart request, the network request fails, or the cart mutation cannot complete.       |
| `retail-connect:conversation-engagement` | `window`   | Conversational embed         | A positive chat engagement signal is recorded, such as product click, add request, or successful approved cart. |

<br/>

## Search Result Events

`retail-connect:products:load:start`, `retail-connect:products:load:success`, and `retail-connect:products:load:failure` describe the Search Results and Product Grid result loading lifecycle.

The load-start event detail includes the request context:

| Field                  | Description {.compact}                                                   |
| ---------------------- | ------------------------------------------------------------------------ |
| `query`                | Search query. Empty on collection browsing unless a query is active.     |
| `currentPage`          | Requested page number.                                                   |
| `pageSize`             | Requested products per page.                                             |
| `orderField`           | Active sort field.                                                       |
| `filters`              | Filters sent to the Retail Cloud Connect storefront API.                 |
| `appliedCustomFilters` | Active custom filters.                                                   |
| `customFields`         | Additional fields requested for custom-filter checks.                    |
| `searchFiltersEnabled` | Whether search filters are enabled for the current App Block.            |
| `collectionId`         | Shopify collection id on Product Grid collection pages.                  |
| `collectionTags`       | Collection tags passed to the request, when present.                     |
| `loadMore`             | Whether the App Block is rendering multiple loaded pages.                |
| `storeKey`             | Search store key for this App Block instance.                            |
| `conversationId`       | Retail Cloud Connect search conversation id, when present.               |
| `autocompleteToken`    | Autocomplete attribution token, when the request came from autocomplete. |
| `autocompletePosition` | Autocomplete result position, when available.                            |

The load-success event includes the same request context plus result metadata:

| Field                | Description {.compact}                                                  |
| -------------------- | ----------------------------------------------------------------------- |
| `pagination`         | Current page, total pages, and total result count.                      |
| `facets`             | Visible facet metadata after custom-field-only facets are filtered out. |
| `checkedFacets`      | Facet metadata returned by the API for current filter relevance checks. |
| `products`           | Products currently loaded into the App Block.                           |
| `firstVisiblePage`   | First visible page in load-more mode.                                   |
| `loadedResultsCount` | Number of product cards currently rendered.                             |

The load-failure event includes the request context plus `error`, normalized to an object with at least `message` when possible.

<br/>

## Search Grid Ready

`retail-connect:search-grid:ready` is the public hook for scripts that need to run after the search or collection product grid has rendered. Listen on `document`.

```liquid
{%- if request.page_type == 'search' or request.page_type == 'collection' -%}
  <script>
    document.addEventListener('retail-connect:search-grid:ready', (event) => {
      const { pageType, resultCount, totalResultCount, gridElement } = event.detail;

      console.log('Retail Cloud Connect grid ready', {
        pageType,
        resultCount,
        totalResultCount,
        gridElement,
      });
    });
  </script>
{%- endif -%}
```

The event detail includes:

| Field              | Description {.compact}                                                  |
| ------------------ | ----------------------------------------------------------------------- |
| `blockId`          | Shopify App Block id, when available.                                   |
| `pageType`         | `search` or `collection`.                                               |
| `resultsPerRow`    | App Block grid column setting.                                          |
| `pageSize`         | Products requested per page.                                            |
| `resultCount`      | Number of products currently rendered.                                  |
| `totalResultCount` | Total products returned by the API for the current query or collection. |
| `loadMore`         | Whether the App Block is rendering multiple loaded pages.               |
| `rootElement`      | App Block root element, or `null`.                                      |
| `gridElement`      | Product grid element, or `null`.                                        |

Use this event instead of observing private product-grid selectors.

<br/>

## Product Card Add-to-Cart Events

`retail-connect:add-to-cart:success` and `retail-connect:add-to-cart:failure` fire when a product card includes an add-to-cart component, such as `ADD_TO_BASKET` or `ADD_TO_BASKET_MODAL`.

The event payload is available on `event.detail`:

| Field             | Event   | Description {.compact}                                                                   |
| ----------------- | ------- | ---------------------------------------------------------------------------------------- |
| `detail.response` | Success | Shopify Ajax cart response body returned by `cart/add.js`.                               |
| `detail.response` | Failure | Shopify Ajax error response body when Shopify returns one.                               |
| `detail.error`    | Failure | JavaScript error object when the request throws before a Shopify response can be parsed. |

When the success event fires, the App Block has already posted to Shopify's Ajax `cart/add.js` endpoint. Theme code should not add the item again.

Product cards can appear on several storefront templates, so install add-to-cart listeners globally unless the store deliberately limits them to known page types.

```liquid
<script>
  window.addEventListener('retail-connect:add-to-cart:success', (event) => {
    const response = event.detail?.response;
    const items = Array.isArray(response?.items)
      ? response.items
      : response
        ? [response]
        : [];

    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({
      event: 'retail_connect_add_to_cart',
      source: 'retail_connect_product_card',
      ecommerce: {
        items: items.map((item) => ({
          item_id: item.product_id,
          item_variant: item.variant_id || item.id,
          item_name: item.product_title || item.title,
          quantity: item.quantity || 1,
        })),
      },
    });
  });
</script>
```

Common uses include analytics, opening a theme cart drawer, updating a mini-cart badge, or showing a small success message.

<br/>

## Conversational Engagement Event

`retail-connect:conversation-engagement` fires when the conversational embed records a positive shopping engagement signal.

Current signal types are:

| Signal                    | Fired when {.compact}                                                                 |
| ------------------------- | ------------------------------------------------------------------------------------- |
| `product_clicked`         | A shopper clicks a product-card link from chat.                                       |
| `add_to_basket_requested` | A shopper clicks the chat product-card add button and asks the agent to add the item. |
| `add_to_cart_succeeded`   | The approved browser add-to-cart tool succeeds.                                       |

The event detail includes:

| Field     | Description {.compact}                                                                               |
| --------- | ---------------------------------------------------------------------------------------------------- |
| `source`  | Currently `conversation-ui`.                                                                         |
| `signal`  | Signal type, weight, and timestamp.                                                                  |
| `context` | Conversation, visitor, store, locale, currency, and page context values when available.              |
| `product` | Product id, variant id, title, price, currency, and product URL when the signal has product context. |

The conversational embed also publishes the same sanitized payload to Shopify analytics as `rcc:conversation_engagement` when `window.Shopify.analytics.publish` is available, and posts it to the storefront-agent engagement endpoint.

<br/>

## Coordination Events

Search App Blocks also dispatch these window events when their search store registers or is removed:

| Event                         | Target   | Purpose {.compact}                                                                              |
| ----------------------------- | -------- | ----------------------------------------------------------------------------------------------- |
| `rcc-search-store:registered` | `window` | Announces that a Search Results or Product Grid store is available in `window.RCCSearchStores`. |
| `rcc-search-store:removed`    | `window` | Announces that a store key has been removed from `window.RCCSearchStores`.                      |

These events exist so Retail Cloud Connect surfaces, such as the conversational embed, can coordinate with the visible search page. Use the documented `retail-connect:*` events above for normal storefront theme integrations.

<br/>

## Best Practices

- Add custom listeners in `snippets/nimstrata.liquid`; see [nimstrata.liquid Setup](/shopify/theme-installation/nimstrata-liquid/).
- Scope listeners to the page types that render the relevant App Blocks.
- Keep listeners idempotent so duplicate snippets do not send duplicate analytics events or open multiple UI layers.
- Treat event payloads as browser-visible data. Do not add customer identifiers, storefront tokens, or secrets to forwarded analytics payloads.
- Read `event.detail` defensively because Shopify Ajax and result response shapes can vary by request.
- Use failure events for diagnostics or carefully worded user messaging, but do not expose raw technical errors to shoppers.
