---
title: "How to build 'frequently bought together' from your own order data"
description: "A 'frequently bought together' block can be computed from your own orders with market-basket analysis: count how often two products appear in the same order and rank the pairs by lift, which says how much more often they sell together than chance would predict. We compute pairs per store over the last 180 days, from a source that holds almost every order, with minimum counts that keep rare products from producing absurd lifts. The method finds real pairs; turning them into bundles was harder than the maths."
date: 2026-10-11
lang: en
canonical: https://goingstellar.ro/methods/frequently-bought-together-from-order-data/
author: Going Stellar
publisher: GOING STELLAR S.R.L.
topic: E-commerce / Cross-sell
license: CC BY 4.0
alternate_ro: https://goingstellar.ro/ro/metode/cumparate-frecvent-impreuna-din-comenzi/
---

# How to build "frequently bought together" from your own order data

*A "frequently bought together" block can be computed from your own orders with market-basket analysis: count how often two products appear in the same order and rank the pairs by lift, which says how much more often they sell together than chance would predict. We compute pairs per store over the last 180 days, from a source that holds almost every order, with minimum counts that keep rare products from producing absurd lifts. The method finds real pairs; turning them into bundles was harder than the maths.*

> E-commerce · Cross-sell · 2026-10-11 · https://goingstellar.ro/methods/frequently-bought-together-from-order-data/

## Key points

- "Frequently bought together" can be computed from your own orders: count orders containing both products and rank pairs by lift = co-occurrences × total orders ÷ (orders with A × orders with B).
- A lift of 1 means two products meet only by chance; we treat a lift above 1.5 as a real association.
- Lift is unstable on small numbers, so require a minimum number of orders per product and per pair before trusting it; our defaults are 20 and 15 over 180 days.
- Baskets must come from a complete order source: an analytics copy that looks fresh can miss about 15% of orders for one store.
- Selling a high-lift pair as a bundle needs a bundle your checkout and warehouse both understand; a native bundle can fail when an external cash-on-delivery form creates the order.

## What "frequently bought together" means and how to compute it

"Frequently bought together" is a list of products that customers actually put in the same order, ranked by how much stronger the association is than chance. You can compute it from your own order data with **market-basket analysis**: for every pair of products, count the orders that contain both, then rank the pairs by **lift**. No recommendation service is needed, only the order lines with a product identifier.

Three numbers describe a pair of products A and B. **Support** (co-occurrence) is the number of orders that contain both. **Confidence** from A to B is the share of orders with A that also contain B: `co / orders_with_A`. **Lift** compares that with what chance would give: `lift = co × total_orders / (orders_with_A × orders_with_B)`. A lift of 1 means the two products meet as often as two random products would; we treat a lift above 1.5 as a real association.

Confidence is directional and lift is not. If a cheap accessory is in almost every order, every product will have high confidence towards it, but its lift will be close to 1. That is why we rank by lift and show confidence alongside it.

## Step 1: build the baskets from a complete source

**1. One row per product per order.** Expand every order into its line items and keep one row per distinct SKU per order. Quantity does not matter here: an order with several units of the same product is still one basket containing that product. Product names change and get translated, so pair on the SKU and look up the display title afterwards.

**2. Exclude cancelled orders.** A cancelled order never left the warehouse and often duplicates another order. We keep refused cash-on-delivery orders in this analysis, because the question is what customers choose together, not what they paid for. That is a deliberate difference from customer value analysis, where only delivered orders count.

**3. Use the most complete source you have.** Our first version read baskets from the analytics warehouse. For one store that warehouse was missing about 15% of orders compared with the live store, even though it looked fresh. We moved the default source to the delivery database, which holds about 99% of orders and answers instantly, and kept the warehouse only as a fallback.

## Step 2: set thresholds before you trust a lift

Lift is unstable on small numbers. Two products that each sold only a handful of times and happened to share an order can show an enormous lift. So we filter before ranking. Our defaults are: a window of 180 days, at least 20 orders per product before it is considered, at least 15 orders containing the pair, and a lift of at least 1.5.

The order of the filters matters. First drop products below the minimum order count, then compute the total number of orders *among the products that remain*, then count pairs. If the total includes orders made only of filtered-out products, every lift is inflated by the same factor and the ranking looks better than it is.

Very high lifts still appear, and they are usually true. On our perfume stores, two fragrances from the same range showed a lift of about 240, and another pair appeared together in 297 orders. A high lift between two mid-volume products typically means customers see them as a set. On a home and garden store the pairs were just as recognisable: storage shelving units bought together, variants of the same ceiling light, sets of storage boxes, and a bedside crib with a baby bath.

## Step 3: ask for one product's complements

The pair list is useful for a merchandiser; a product page needs the reverse question: given product A, what should we suggest? We filter the pairs that contain A and rank the other product by lift, showing the co-occurrence count and the confidence from A. The top three complements per hero product are what we would put in a "frequently bought together" block.

The same list feeds four uses. A block on the product page. A post-purchase email that suggests the complement of what was just bought. The choice of the free item in a buy-two-get-one promotion, picked from high-lift complements of what is in the cart. And bundle or "complete the set" offers.

## Where we were wrong: the bundle was the hard part

The first mistake was the source, described above: the warehouse looked complete and was not, and a recommender built on missing orders misses exactly the stores where the gap is largest.

The second lesson came when we tried to sell high-lift pairs as bundles. A native platform bundle, where the components reduce stock automatically, can be created through the admin API without a separate bundles app; we converted 15 kits that way on one store. But on stores where a cash-on-delivery form app creates the order on the server instead of through the normal checkout, the platform rejected the bundle variant, and one store had already dropped native bundles for that reason.

For those stores we built kits as plain products picked at order time, with the list of components stored on our side. The same function unpacks a kit into its components in every place that needs it: the scanner in the warehouse, order ingestion, stock reservations and the stock deduction at shipping. A kit known only to the store and not to the warehouse would ship as one unknown item.

The improvement we planned and have not built is ranking pairs by lift multiplied by the real profit per SKU, so that we push the complements that make money and not only the frequent ones. Until then, the list says what sells together, not what is worth promoting.

## Limits

Market-basket analysis only sees what customers already buy together. A product that is never shown next to another cannot form a pair, so the method reinforces existing habits rather than discovering new ones.

Stores where most orders contain a single product produce very few pairs. Lower the minimum pair count or widen the window, and accept that the result is weaker.

Our query does not separate a free gift line from a paid line. If a promotion adds a fixed gift to every order, that gift will pair with everything, and you should exclude it before reading the list.

Correlation is not cause. A high lift says two products are chosen together, not that suggesting one will sell the other. Test the block on the page before assuming it works.

## A short checklist

Pair on SKUs, one row per product per order, cancelled orders excluded. Read baskets from the most complete order source and check its coverage against the live store. Filter products and pairs by minimum counts before computing lift, and compute the total from the remaining products. Rank by lift above 1.5 and show co-occurrence and confidence beside it. Remove fixed gift lines. Before selling a pair as a bundle, confirm the bundle survives your checkout path and your warehouse can see its components.

## Questions and answers

### How do I calculate frequently bought together products from Shopify orders?

Export order lines with SKU and order number, keep one row per SKU per order and drop cancelled orders. For each pair of SKUs, count orders containing both. Compute lift as co-occurrences times total orders divided by orders with A times orders with B. Keep pairs with enough orders and a lift above 1.5, then show the top complements of each product.

### What is lift in market-basket analysis?

Lift measures how much more often two products appear in the same order than they would if customers chose them independently. It is co-occurrences multiplied by total orders, divided by the product of each item's order count. A lift of 1 means no association, above 1 means they go together, and we treat 1.5 or more as a real signal worth acting on.

### What is the difference between confidence and lift?

Confidence from A to B is the share of orders with A that also contain B, so it depends on how popular B is. Lift divides out that popularity. A best-selling product gets high confidence from almost everything, but its lift stays near 1. Rank complements by lift and use confidence to judge how many customers a suggestion would reach.

### How many orders do I need for cross-sell analysis?

Enough that each product and each pair is seen several times. We require at least 20 orders per product and 15 orders containing the pair, over a window of 180 days. With fewer orders lift jumps around and rare pairs dominate. Stores where most orders contain one product need a longer window or lower thresholds, with a weaker result.

### Why do my product bundles fail with a cash-on-delivery form app?

Some cash-on-delivery form apps create the order on the server instead of through the normal checkout, and in our case the platform rejected the native bundle variant on that path. We switched those stores to kits sold as plain products, with the component list stored on our side and unpacked by the warehouse at picking and shipping.

## How to cite

**Cite this as:** Going Stellar (2026). *How to build "frequently bought together" from your own order data*. GOING STELLAR S.R.L.. https://goingstellar.ro/methods/frequently-bought-together-from-order-data/

```bibtex
@misc{goingstellar2026frequently,
  title  = {How to build "frequently bought together" from your own order data},
  author = {{Going Stellar}},
  year   = {2026},
  url    = {https://goingstellar.ro/methods/frequently-bought-together-from-order-data/},
  note   = {2026-10-11}
}
```

Licence. Free to quote with attribution.

## Also available

- This page as HTML: https://goingstellar.ro/methods/frequently-bought-together-from-order-data/
- Same article in Romanian: https://goingstellar.ro/ro/metode/cumparate-frecvent-impreuna-din-comenzi/
