← Back to KPIs

Multi-Item Cart Rate

Conversioncart buildingcross-sellproduct discoveryE-commerceRetail

Percentage of carts with successful product additions that receive at least two distinct products during the reporting period. It helps assess cross-sell and cart-building effectiveness.

Business Use Case

1️⃣ Merchandising teams compare cross-sell changes before expanding product recommendations. 2️⃣ Product teams investigate declines before changing product discovery or cart-building experiences.

Business Criticality

Medium

Journey / Navigation Area

Cart

Owning Function

Merchandising

Scope

Event

Measurement Channels

Web, Mobile App, Backend / API

Formula

(Carts with two or more distinct products added / Carts with at least one product added) × 100

Calculation Notes

1️⃣ Include successful additions with nonempty cart and product IDs from reporting start to before reporting end. 2️⃣ Recount distinct product IDs per cart each interval; retries and extra units do not increase the count. 3️⃣ Count only products added in the interval, regardless of later removal or purchase. 4️⃣ Use stable Cart IDs as supplied; document cart reuse, replacement, and merging before integration. 5️⃣ Return null when no carts have a qualifying addition.

Technical Details

Measure TypePercentage
Aggregation WindowSelected Reporting Period

Events

PlatformEvent
Google Analytics 4add_to_cart — records successful product additions to carts
Adobecommerce.productListAdds — records successful product additions to carts

Data Mappings

W3 Data Layer
{
  "digitalData": {
    "event": [
      {
        "eventInfo": {
          "eventName": "add_to_cart",
          "timeStamp": "2026-10-29T12:00:00Z"
        },
        "attributes": {
          "event_id": "cart-add-A123"
        }
      }
    ],
    "cart": {
      "cartID": "C123",
      "item": [
        {
          "productInfo": {
            "productID": "SKU123"
          },
          "quantity": 2
        },
        {
          "productInfo": {
            "productID": "SKU456"
          },
          "quantity": 1
        }
      ]
    }
  }
}
GA4 Data Layer
[
  {
    "event": "add_to_cart",
    "event_id": "cart-add-A123",
    "cart_id": "C123",
    "ecommerce": {
      "items": [
        {
          "item_id": "SKU123",
          "quantity": 2
        },
        {
          "item_id": "SKU456",
          "quantity": 1
        }
      ]
    }
  }
]
Adobe Client Data Layer
[
  {
    "event": "commerce.productListAdds",
    "eventInfo": {
      "eventId": "cart-add-A123",
      "timestamp": "2026-10-29T12:00:00Z"
    },
    "commerce": {
      "productListAdds": {
        "value": 1
      },
      "cart": {
        "cartID": "C123"
      }
    },
    "productListItems": [
      {
        "SKU": "SKU123",
        "quantity": 2
      },
      {
        "SKU": "SKU456",
        "quantity": 1
      }
    ]
  }
]
XDM Mapping
[
  {
    "_id": "cart-add-A123",
    "timestamp": "2026-10-29T12:00:00Z",
    "eventType": "commerce.productListAdds",
    "commerce": {
      "productListAdds": {
        "value": 1
      },
      "cart": {
        "cartID": "C123"
      }
    },
    "productListItems": [
      {
        "SKU": "SKU123",
        "quantity": 2
      },
      {
        "SKU": "SKU456",
        "quantity": 1
      }
    ]
  }
]

SQL Queries

Google Analytics 4 (BigQuery)
-- Input: configured events_* export; @report_start and @report_end are UTC TIMESTAMP bounds.
-- event_timestamp is addition occurrence time; suffix pruning buffers property-timezone dates.
WITH cart_products AS (
  SELECT a.cart_id, COUNT(DISTINCT item.item_id) AS product_count
  FROM (
    SELECT
      (SELECT p.value.string_value FROM UNNEST(event_params) AS p
       WHERE p.key = 'cart_id') AS cart_id,
      items
    FROM `{{GA4_PROJECT}}.{{GA4_DATASET}}.events_*`
    WHERE event_name = 'add_to_cart'
      AND _TABLE_SUFFIX BETWEEN
        FORMAT_DATE('%Y%m%d', DATE_SUB(DATE(@report_start), INTERVAL 1 DAY))
        AND FORMAT_DATE('%Y%m%d', DATE_ADD(DATE(@report_end), INTERVAL 1 DAY))
      AND event_timestamp >= UNIX_MICROS(@report_start)
      AND event_timestamp < UNIX_MICROS(@report_end)
  ) AS a
  CROSS JOIN UNNEST(a.items) AS item
  WHERE a.cart_id IS NOT NULL AND a.cart_id != ''
    AND item.item_id IS NOT NULL AND item.item_id != ''
  GROUP BY a.cart_id
)
SELECT 100.0 * SAFE_DIVIDE(COUNTIF(product_count >= 2), COUNT(*)) AS multi_item_cart_rate
FROM cart_products;
Adobe Experience Platform (AEP Query Service)
-- Input: REPORT_START_UTC and REPORT_END_UTC match the GA4 UTC reporting bounds.
-- timestamp represents the successful addition occurrence.
WITH cart_products AS (
  SELECT expanded.cart_id, COUNT(DISTINCT expanded.item.SKU) AS product_count
  FROM (
    SELECT commerce.cart.cartID AS cart_id, explode(productListItems) AS item
    FROM {{AEP_EXPERIENCE_EVENT_DATASET}}
    WHERE eventType = 'commerce.productListAdds'
      AND timestamp >= CAST('{{REPORT_START_UTC}}' AS TIMESTAMP)
      AND timestamp < CAST('{{REPORT_END_UTC}}' AS TIMESTAMP)
  ) AS expanded
  WHERE expanded.cart_id IS NOT NULL AND expanded.cart_id <> ''
    AND expanded.item.SKU IS NOT NULL AND expanded.item.SKU <> ''
  GROUP BY expanded.cart_id
)
SELECT 100.0 * SUM(CASE WHEN product_count >= 2 THEN 1 ELSE 0 END)
       / NULLIF(COUNT(*), 0) AS multi_item_cart_rate
FROM cart_products;

Source Data

Digital Analytics, Commerce Platform

Dependencies

Prerequisite: List the dependencies required for this KPI

Events:

add-to-cart

Dimensions:

cart-id

Report Attributes

Cart ID

Recommended Reporting Views

Views
Cart Building PerformanceCross-Sell Effectiveness

Segment Eligibility

Cart ID EXISTS AND Item ID EXISTS

Governance

Data SensitivityInternal

Governance

Created bydevyendarm
Created on10/29/2026
Last modified bydevyendarm
Last modified on10/31/2026
StatusPUBLISHED

GitHub

View related Pull Requestcatalog/kpis/multi-item-cart-rate.yml

Community Discussion