StoBasket: Joint Upsell and Cross-Sell Optimization for Contribution Margin
Organizations: Tote AI United States
Abstract
Retail recommenders rank relevance, but retailers earn contribution margin: an upsell earns the margin difference over the item it replaces, whereas a cross-sell earns its full margin. We introduce joint stochastic basket editing, a formulation in which one policy selects replacement and addition offers for an existing basket, values them by expected incremental contribution margin, and couples them through displayed-offer, accepted-offer, and joint-acceptance response channels. To our knowledge, it is the first formulation in which upsell and cross-sell responses are coupled; prior separable treatments are its zero-coupling special case. In real-data-calibrated simulations on five public basket datasets, StoBasket captures essentially all attainable offer margin: within 0.5% in every default-price setting and within 0.7% when the true response lies outside its model family. Correct economic accounting is the broadest gain: margin-weighted popularity leaves up to 11% of attainable margin unrealized, and a published next-basket recommender leaves 11-52%. Joint selection adds 10.2% of attainable margin on Instacart, where premium tiers and add-ons are strongly linked. When offers pay only together, the best heuristics lose 64% while exact search stays within 0.5%. For a structured subclass, we characterize when staged policies fail and give an exact optimizer that solves every tested real basket in 0.13 ms median and at most 111 ms. Profit saturates long before prediction accuracy: a correctly structured predictor trained on 5,000 randomized sessions comes within 0.06% of perfect prediction, while a signal-free one loses 38%. The same estimates yield a decision-aware market-basket analysis whose cost does not grow with association order.
Figures & tables
| Symbol | Meaning (example) |
|---|---|
| Basket at decision time (regular patties, regular buns) | |
| Transaction context: prices, margins, inventory, store, time | |
| Offer set, or policy (premium patties and cheddar) | |
| Promotion terms; means ordinary prices | |
| Permitted offer sets under budgets, conflicts, and stock | |
| Random shopper response: which offers are accepted |
| Strategy | How it chooses offers | Strengths and weaknesses |
|---|---|---|
| 1. Independent | Picks upsells as if no cross-sell were shown (maximizes ) and cross-sells as if no upsell were shown (maximizes ). | Fastest; two small separate problems; optimal when offers do not interact. Ignores all cross-action coupling; largest gap when coupling is strong. |
| 2. Upsell-first | Keeps the independent upsells, then picks the best cross-sells given their summary . | Cheap; captures the effect of upsells on cross-sells. Upsells are chosen blind to cross-sells, and a poor first stage is never revised. |
| 3. Cross-sell-first | Keeps the independent cross-sells, then picks the best upsells given them. | Cheap; picks upsells that raise the value of the chosen cross-sells. Cross-sells are chosen blind to upsells; no revision. |
| 4. Alternating best response | Starts from the better of strategies 2 and 3, then alternates and until neither step improves. | Fast and usually near-exact; within 0.14% of exact on Carbo-Loading. Stops at a local optimum; can stay at “show nothing” in the trap; no worst-case guarantee. |
| 5. Greedy | Repeatedly adds the single offer with the largest positive gain until no offer helps. | Simple; needs no structure in the objective. Myopic: requires a profitable first step, so it fails in the trap and when pairs interact. |
| Exact ( StoBasket ) | Enumerates candidate cross-sell sets by score geometry and optimizes upsells by tree-decomposition dynamic programming (Proposition 4.1 ). | Certified global optimum; captures profitable sets with unattractive parts. Needs fixed and bounded treewidth; more compute (0.13 ms median, 111 ms maximum on real baskets). |
| Market | Economic-policy gain | Joint-selection gain | Exact-search premium |
| vs. margin-pop. (%) | vs. independent (%) | vs. portfolio (%) | |
| Complete Journey | 2.4 | 0.17 | |
| Ta Feng | 1.5 | ||
| Instacart | 11.4 | 10.2 | 63.8 † |
| Online Retail II | 1.0 | 0.34 | |
| Carbo-Loading | 4.7 | 0.73 |
| Data | Sim. | Oracle | Exact | Indep. | Upg.-first | Add-first | Greedy | Altern. | Margin-pop. | Assoc. |
|---|---|---|---|---|---|---|---|---|---|---|
| Complete Journey | S1 | 536 | 536 | +3.5 | +1.1 | +2.6 | +0.4 | +0.0 † | +12.6 | +534.2 |
| S2 | 509 | 507 | +5.8 | +1.3 | +5.8 | +2.1 | +0.1 | +13.2 | +493.6 | |
| S3 | 373 | 313 | +2.4 | +0.5 | +1.7 | +0.2 | +0.0 † | +7.9 | +308.3 | |
| Ta Feng | S1 | 20576 | 20570 | +71.3 | +25.8 | +46.2 | +10.0 | +0.3 | +300.7 | +10746.4 |
| S2 | 19523 | 19498 | +104.0 | +52.9 | +56.7 | +21.7 | +1.0 | +296.2 | +10651.8 | |
| S3 | 14346 | 12069 | +46.0 | +10.0 | +35.5 | +4.7 | -0.2 - | +170.2 | +6371.9 |
| StoBasket | TIFU-KNN | Margin- | Assoc. | ||||
|---|---|---|---|---|---|---|---|
| Dataset | + TIFU | anonymous | margin | relevance | popularity | rules | |
| Complete Journey | 0 | 99.9 | 99.9 | 88.7 | 10.8 | 97.6 | 2.3 |
| 0.5 | 99.7 | 99.6 | 88.8 | 10.1 | 97.3 | 1.7 | |
| 1 | 99.3 | 98.9 | 88.4 | 9.2 | 96.7 | 0.4 | |
| Ta Feng | 0 | 100.0 | 100.0 | 48.2 | 37.0 | 98.5 | 47.3 |
| 0.5 | 99.9 | 99.8 | 49.3 | 37.9 | 98.4 | 47.7 | |
| Prior work | What it already does | What StoBasket adds |
|---|---|---|
| Profit-aware recommendation ( De Biasio et al., 2024b ; Louca et al., 2019 ; De Biasio et al., 2024a ) | Scores or trains rankings of individual products using provider profit, relevance, or a tradeoff between them. | Optimizes a set of edits to a basket already in progress. An upsell replaces an incumbent and earns only the margin difference; a cross-sell adds an item and earns incremental margin; their values can interact. |
| Association rules and market-basket analysis ( Agrawal et al., 1993 ; Singh et al., 2006 ) | Finds products that co-occur, reports support/confidence/lift, and may rank upsell or cross-sell candidates by association, acceptance, revenue, or margin. | Uses the association report as an interpretable diagnostic, then adds signed premium-to-complement effects, shrinkage/placebos, action type, contribution margin, and a feasible joint offer decision. |
| Upgraded substitutes and co-purchases ( Ban et al., 2024 ) | Places substitute upgrades and co-purchases in one business problem; under the studied response assumptions, the component optimizations separate. | Makes the upsell decision change cross-sell response and value through displayed, accepted, and jointly accepted channels; proves when separation is safe and when it can fail arbitrarily. |
| Next-basket recommendation ( Hu et al., 2020 ; Li et al., 2023 ) | Forecasts which items a shopper will buy next from purchase history, with strong reproducible results on the dunnhumby, Ta Feng, and Instacart benchmarks. | Turns that forecast into margin by using it as a response feature, then deciding which replacement and addition offers to serve. On the same benchmarks it adds up to 6% as an input, whereas serving the forecast directly leaves 11–52% unrealized even after margin reranking (Table 5 ). |
| Exposure modeling ( Sato et al., 2020 ) | Separates whether a user becomes aware of an item from whether the user prefers or purchases it, and models recommendation influence on exposure. | Places displayed-offer, accepted-offer, and joint-acceptance effects inside one expected-margin policy over replacements and additions. |
| Cross-category basket retrieval ( Acar, 2026 ) | Retrieves complementary products for a checkout-adjacent recommendation surface and debiases transactional complement evidence. | Takes retrieved candidates as inputs, values displaced and incremental margin, and jointly chooses which replacement and addition offers to serve. |
Appendix figures & tables16 assets
Supplementary material from the paper’s appendix.
Appendix
| Test | Instances | Failures |
|---|---|---|
| Forest plus pair moments, | 320 | 0 |
| Nonempty interaction graph among those | 289 | – |
| Moment expansion vs. tree-joint law | 120 | 0 |
| Tree-decomposition DP vs. brute force | 300 | 0 |
| Treewidth solver, rational factors, | 240 | 0 |
| of which cyclic upgrade graphs | 216 | – |
| Complete Journey | Ta Feng | Instacart | |
|---|---|---|---|
| Source | 84.51° via completejourney , CC0 | Taiwanese supermarket, 2000–01 | 2017 public release |
| Train / test baskets | 102,604 / 37,434 | 88,527 / 31,051 | 400,000 (sample) / 131,209 |
| Split | weeks 1–39 / 40–53 | Nov–Jan / Feb | prior / final orders |
| Margin | assumed rates, 3 scenarios | real cost | imputed prices |
| Context | store, weekday, hour | residence area, weekday | weekday, hour |
| Premium tier | national vs. private label | price above subclass median | organic |
| Data | Setting | Oracle | Exact regret | Indep. | Upg.-first | Altern. |
|---|---|---|---|---|---|---|
| Complete Journey | 528 | 0.2 | -0.0 | -0.0 | -0.0 | |
| Complete Journey | 531 | 0.2 | 1.1 | 0.3 | 0.0 | |
| Complete Journey | 550 | 0.7 | 9.1 | 3.3 | 0.1 | |
| Ta Feng | 20022 | 4.9 | -1.0 | -0.9 | 0.0 | |
| Ta Feng | 20283 | 4.3 | 25.7 | 8.7 | 0.0 | |
| Ta Feng | 21217 | 12.4 | 185.3 | 76.1 | 2.0 |
| Data | Truth | Oracle | Exact regret | Indep. | Upg.-first | Altern. | Portfolio | Margin-pop. |
|---|---|---|---|---|---|---|---|---|
| Online Retail II | S1, | 6615 | 4.0 | 22.3 | 5.5 | 0.0 | 0.0 | 68.2 |
| Online Retail II | S2, | 5992 | 6.3 | 28.3 | 9.6 | 0.2 | 0.2 | 91.6 |
| Online Retail II | S3, | 4663 | 893.9 | 31.8 | 3.7 | 0.0 | -0.0 | 56.6 |
| Online Retail II | S1, | 6575 | 4.2 | -0.2 | -0.1 | 0.0 | 0.0 | 45.1 |
| Online Retail II | S1, | 6693 | 5.3 | 47.5 | 13.6 | 0.2 | 0.2 | 96.5 |
| Complete Journey | S1, Dominick’s margins | 439 | 0.3 | 2.5 | 0.6 | 0.0 | 0.0 | 9.8 |
| Data | Setting | Oracle | Upsell share | Coupling value | Exact independent | |
|---|---|---|---|---|---|---|
| per 1,000 | % of oracle | per 1,000 (% of oracle) | % of oracle | % of coupling value | ||
| Complete Journey | S1 | 536 | 88 | 11.2 (2) | 0.65 | 31 |
| Complete Journey | S2 | 509 | 84 | 28.4 (6) | 1.14 | 20 |
| Ta Feng | S1 | 20576 | 88 | 600.8 (3) | 0.35 | 12 |
| Ta Feng | S2 | 19523 | 85 | 1144.2 (6) | 0.53 | 9 |
| Instacart | S1 | 474 | 33 | 159.2 (34) | 11.28 | 34 |
| Data | Setting | Oracle | Exact regret | Indep. | Greedy | Altern. | Portfolio | Differs |
|---|---|---|---|---|---|---|---|---|
| per 1,000 | % of oracle margin | % baskets | ||||||
| Complete Journey | Separate budgets (batch 1) | 536 | 0.06 | 0.65 | 0.08 | 0.00 | – | 0.7 |
| Display cost | 525 | 0.06 | 0.66 | 0.08 | 0.01 | 0.01 | 0.9 | |
| Display cost | 513 | 0.07 | 0.70 | 0.06 | 0.00 | 0.00 | 0.5 | |
| Display cost | 492 | 0.07 | 0.89 | 0.05 | 0.01 | 0.01 | 0.8 | |
| Budgets | 582 | 0.06 | 0.57 | 0.04 | 0.00 | 0.00 | 0.5 | |
| Exact portfolio, % of oracle | Exact regret, % of oracle | |||||||
|---|---|---|---|---|---|---|---|---|
| Price assumption | ||||||||
| Organic (main) | 0.08 | 0.44 | 16.13 | 65.12 | 0.02 | 0.05 | 0.14 | 0.50 |
| Organic | 0.11 | 3.02 | 70.58 | 89.31 | 0.02 | 0.09 | 0.54 | 3.31 |
| Organic | 0.04 | 0.13 | 1.53 | 5.78 | 0.03 | 0.04 | 0.09 | 0.16 |
| Item price noise (s.d. 0.3) | 0.03 | 0.09 | 0.69 | 2.00 | 0.04 | 0.06 | 0.08 | 0.14 |
| Margin rate 18% | 0.05 | 0.44 | 16.13 | 65.12 | 0.02 | 0.05 | 0.14 | 0.50 |
| Data | Setting | Exact independent, per 1,000 | Exact portfolio/altern., % of oracle | ||
|---|---|---|---|---|---|
| fixed shrinkage | EB shrinkage | fixed | EB | ||
| Complete Journey | S1 | 3.5 | 0.9 | 0.00 | 0.00 |
| Complete Journey | S2 | 5.8 | 2.2 | 0.01 | 0.00 |
| Complete Journey | S3 | 2.4 | 0.9 | 0.01 | -0.00 |
| Complete Journey | S1, | 1.1 | 0.2 | 0.00 | -0.00 |
| Complete Journey | S1, | 9.1 | 2.8 | 0.02 | 0.00 |
| Complete Journey | Ta Feng | Instacart | |
| Bundle rebate: loss of rebate-blind exact, per 1,000 baskets | |||
| 0.0 | 0.8 | 1.5 | |
| 0.1 | 3.3 | 7.2 | |
| 0.6 | 19.9 | 34.0 | |
| Stress test: exact regret, % of oracle (base rich model) | |||
| cannibalization + fatigue | 17.5 0.10 | 17.3 0.08 | 10.6 0.08 |
| Data | Median | 90th pct. | Cyclic | Cyclic, | Width |
|---|---|---|---|---|---|
| Complete Journey | 6 | 22 | 50% | 94% | 66% |
| Ta Feng | 4 | 12 | 22% | 68% | 93% |
| Instacart | 4 | 8 | 68% | 100% | 54% |
| Data | DP = brute | DP time (median / p99) | DP faster | Greedy | Altern. | Portfolio | |||
|---|---|---|---|---|---|---|---|---|---|
| % baskets | checked | % baskets | % of oracle | ||||||
| Complete Journey | 2 | 0 | 34 | 887/887 | 3.2 ms / 33.2 s | 0.5 | 0.10 | 0.00 | 0.00 |
| Complete Journey | 4 | 0 | 34 | 887/887 | 3.1 ms / 38.3 s | 27.1 | 0.09 | -0.00 | -0.00 |
| Complete Journey | 4 | 1 | 34 | 887/887 | 3.0 ms / 37.8 s | 27.5 | 0.08 | 0.00 | -0.01 |
| Ta Feng | 2 | 0 | 23 | 900/900 | 1.8 ms / 0.5 s | 0.6 | 0.09 | 0.01 | 0.01 |
| Ta Feng | 4 | 0 | 23 | 900/900 | 2.1 ms / 0.5 s | 36.4 | 0.07 | 0.00 | 0.00 |
| Budget | Method | Median | 95th pct. | 99th pct. | Worst | 100 ms |
|---|---|---|---|---|---|---|
| Always enumerate | 0.4 ms | 10.2 ms | 16.0 ms | 29.6 ms | 100.0% | |
| Always tree-decomposition DP | 2.5 ms | 1.1 s | 57.8 s | 132.6 s | 87.9% | |
| Hybrid (predicted faster method) | 0.4 ms | 10.2 ms | 16.0 ms | 29.6 ms | 100.0% | |
| Best of both per basket | 0.4 ms | 10.2 ms | 16.0 ms | 29.6 ms | 100.0% | |
| Vectorized enumeration (E15c) | 0.1 ms | 0.2 ms | 0.2 ms | 0.4 ms | 100.0% | |
| Always enumerate | 0.9 ms | 1.1 s | 2.0 s | 3.0 s | 85.8% |
| Predictor | Value RMSE | Oracle-policy | Margin regret | Regret per 1,000 |
|---|---|---|---|---|
| % oracle | agreement | % oracle | baskets | |
| Oracle truth | 0.00 | 100.0% | 0.000 | 0.00 |
| Learned, | 17.20 | 54.8% | 4.627 | 21.31 |
| Learned, | 11.27 | 75.3% | 1.106 | 5.09 |
| Learned, | 6.34 | 83.9% | 0.371 | 1.71 |
| Learned, k | 5.09 | 84.8% | 0.299 | 1.38 |
| Premium anchor | Cross-sell receipt cell | Premium | Regular | Policy effect | Relative rate |
|---|---|---|---|---|---|
| Pancake Mixes | syrups: Aunt Jemima | 11.3% | 3.3% | +8.0 pp | 3.43 |
| Pasta Sauce | pasta: Barilla | 8.2% | 4.8% | +3.5 pp | 1.73 |
| Pancake Mixes | syrups: Mrs Butterworth | 4.7% | 1.7% | +2.9 pp | 2.71 |
| Pancake Mixes | syrups: Private Label | 9.4% | 28.4% | -15.0 pp | 0.33 |
| Pasta Sauce | pasta: Private Label | 24.7% | 37.5% | -12.8 pp | 0.66 |
| Pancake Mixes | pasta: Private Label | 8.5% | 14.1% | -5.6 pp | 0.60 |
| Market | Quantity at baskets | |||
|---|---|---|---|---|
| Instacart | Classical candidate itemsets | |||
| Classical counting updates | ||||
| Typed contrasts estimated | 17,956 | 17,956 | 17,956 | |
| Typed counting updates | ||||
| Complete Journey | Classical candidate itemsets | |||
| Classical counting updates |
| Data | Setting | Comparison | Gap per 1,000 | Baskets/arm (offer log) | Baskets/arm (till) |
|---|---|---|---|---|---|
| Complete Journey | default | vs independent | 3.9 | 1.4M | 67.1M |
| Complete Journey | default | vs upgrade-first | 1.4 | 11.3M | 550.2M |
| Complete Journey | default | vs alternating | 0.0 | 30943.0M | 1497174.2M |
| Complete Journey | default | vs no offers | 530.5 | 37 | 3,510 |
| Complete Journey | shared budget | vs independent | 121.1 | 1,295 | 69k |
| Complete Journey | shared budget | vs upgrade-first | 9.1 | 266k | 12.2M |
Recommender Systems
Recommender systems predict and rank items for people using interaction histories, content, context, and feedback.
See all 516 papers