Blog

Cart Upsell Analytics: Attach Rate, CTR, and Holdouts

cart upsell analytics

Quick answer: Cart upsell analytics is five numbers: offer impressions, CTR, upsell attach rate (orders containing the offer ÷ orders from sessions that saw it), upsell revenue, and checkout conversion with the offer on versus off. Judge an offer on margin per session against a holdout, not on AOV or pre/post charts.

You turned on a cart offer. AOV went up $3. Conversion went down 0.4 points. Are you richer? You do not know until you run the five-number scorecard and stop mixing seats.

Last checked October 11, 2026: Shopify's customer-event and Liquid docs, the Growth Suite and Cartylabs benchmarks quoted below, and Oxify's App Store listing. Written from Oxify Analytics V2, not from a generic "10 metrics every brand needs" list.

Key Takeaways

  • Five numbers: impressions, CTR, attach, upsell revenue, checkout conversion (holdout).
  • Holdout > pre/post. Season, ads, and shipping tests will fake a win.
  • Split by seat. Cart vs PDP vs checkout vs post-purchase. Same SKU in two seats is not "2× performance."
  • Check the denominator. A published "12% acceptance" (offers accepted ÷ offers shown) and a "5–10% attach" (orders with the add-on ÷ orders) are different meters.
  • AJAX needs pixels. Drawer adds are not always a new page. Subscribe to product_added_to_cart, and read line properties from the order side.
  • Oxify does not ship an A/B lab. We report attributed revenue by placement. You still design the off group.

What Is Upsell Attach Rate?

The attach rate formula: orders that include the offer ÷ orders from sessions that saw the offer. It is not CTR. It is not "AOV went up." A $4 wrap that 12% of seeing carts keep to purchase is a different business than a $29 warranty that 12% click and then remove.

Worked example: 2,000 sessions open the drawer and the offer renders. 380 of those sessions convert to orders. 34 of those orders contain the offer line. Attach rate = 34 ÷ 380 = 8.9%. Not 34 ÷ 2,000 (that is orders-with-offer per impression, a different number), and not clicks ÷ impressions (that is CTR).

Attach vs Take Rate vs Acceptance vs CTR

Vendors use these interchangeably. They are not the same number, and comparing your attach to someone's published "acceptance rate" is comparing meters.

TermDenominatorWhat it tells you
CTRImpressionsDid the creative get a tap? Says nothing about money
Acceptance / take rateOffers shown (or offers clicked, depending on the vendor — check)Did they say yes at the moment of offer? Common in post-purchase, where one click = accepted
Attach rateOrders from sessions that saw the offerDid the yes survive to a paid order line? The one to run the business on

Post-purchase "take rate" and cart-drawer "attach" are different meters too, so a 6% post-purchase acceptance rate and a 6% drawer attach rate are not the same result. A post-purchase offer is a one-tap order edit with payment already captured; a drawer offer has to survive to a paid order line. That is a funnel position difference, not app quality.

Benchmarks by Placement: What Two Vendors Published

We only print benchmarks that name their source and say what they divide by. Two do, and they divide by different things, which is the point of the table above. Both come from upsell vendors, neither is audited, and neither is a target for your store.

SourceWhat it measuresWhat it reports
Growth Suite, January to June 2026 (66 million offer impressions, 250 Shopify stores)Acceptance: offers accepted ÷ offers shownCart drawer 12%, checkout 9% (Shopify Plus only, 28 stores, about 500,000 impressions), product page 7%, post-purchase 6%. Individual stores ranged from under 2% to over 20% at the same placement
Cartylabs upsell revenue calculator, read October 11, 2026Attach: orders with the add-on ÷ ordersGeneric add-ons 2–4%, relevant cart upsells often 5–10%, strong bundles or replenishment add-ons can exceed 10%. These are modelling assumptions, not measured data

Growth Suite's cart drawer accepted more offers (12%) than its post-purchase placement (6%), so do not assume the one-tap placement wins on rate. Its session data also shows acceptance by position in a session: 5% for the first offer, 8% for the second, 6% for the third and 1% for the fourth. That is a reason to cap offers per session before you read any placement average. Growth Suite itself notes that acceptance does not prove the buyer would not have bought the item anyway, which is the job of the holdout below.

Use these as a sanity band, not a target. A cart drawer upsell conversion rate of 2% on a $60 add-on can out-earn 6% on a $6 one. Which brings us to the number that actually compares offers:

Incremental Revenue per 100 Sessions

(Upsell revenue ÷ sessions that saw the offer) × 100. It collapses CTR, attach, conversion, and price into one comparable figure. Illustrative numbers, reusing the worked example above (380 orders from 2,000 sessions, so 100 sessions ≈ 19 orders):

  • Offer A: 5% attach × 19 orders × $6 wrap = $5.70 per 100 sessions
  • Offer B: 2% attach × 19 orders × $45 bundle = $17.10 per 100 sessions

B "converts worse" and makes 3× the money. Then take one more step: margin, not revenue. If the $45 bundle is 25% margin and the $6 wrap is 80%, B nets $4.28 per hundred sessions and A nets $4.56 — suddenly a coin flip. Judge offers on gross-margin uplift per session. A revenue-only scoreboard will keep a money-losing hero offer alive for months.

The 5-Number Scorecard

NumberFormulaWhat a bad reading means
ImpressionsSessions (or drawer opens) that actually rendered the offerYou are judging a widget nobody saw (below the fold, hidden collection, app off on mobile)
CTRTaps on the offer / impressionsCreative or price is dead. Do not "optimize CTR" by making the whole drawer a button
Attach rateOrders containing the offer / orders from sessions that saw itThey tap, then remove. Or checkout strips the line. CTR was a lie
Upsell revenueSum of that line (and only that line) on those ordersYou counted the whole order as "upsell revenue"
Checkout conversionPurchases / sessions, offer-on vs holdoutThe only number that tells you if the widget is a tax

Add revenue per impression (upsell revenue / impressions) when CTR and attach argue. A low CTR with high revenue per impression can still be a good quiet offer (warranty). A high CTR with tiny revenue per impression is a cheap click.

Treat every published range as the publisher's rule of thumb, including the 5–10% attach assumption in the Cartylabs calculator above. If your $9 wrap attaches at 4% on a $200 cart, that can still be fine. If your $40 widget attaches at 4% and checkout conversion is down, it is not fine.

We do not publish a universal "healthy CTR." Thumbnail shops and warranty toggles do not share a CTR planet.

Holdout, Not Vibes

Pre/post ("we installed Tuesday, AOV rose Thursday") fails when:

  • You also launched ads, a new collection, or free shipping
  • The week includes a payday or a holiday
  • You compare 7 days to 30 days

Holdout: keep the offer off for a random slice of traffic, or for one device type, or for one week in four — whatever you can actually operationalize without an A/B tool. Oxify's compare table flags built-in A/B testing: no. Rebuy-class tools include tests. If you need a lab, that is a reason to pay for one. If you need honest directional data, a time-split plus the five numbers is enough for most stores under mid-seven-figures.

Minimum sample: we like ~200 sessions that saw the offer before even reading CTR and attach. Below that you are reading noise. That is our operating rule for the early metrics, not a statistics textbook.

How Many Orders Before You Can Trust an AOV Lift?

More than you think. The textbook sizing for a two-group comparison is Lehr's rule of thumb (1992): roughly 16 × (CV ÷ lift)² orders per group (80% power, 5% significance, equal groups), where CV is your order-value coefficient of variation — standard deviation of order value divided by AOV. Compute yours from an order export; the figures below assume 0.75.

  • Detecting a 5% AOV lift at CV 0.75: 16 × (0.75 ÷ 0.05)² ≈ 3,600 orders per group, about 7,200 in total at a 50/50 split. At a 90/10 split (a 10% holdout) the same test needs about 20,000 orders in total, only about 2,000 of them in the holdout. A store doing 1,000 orders a month needs around 20 months.
  • Detecting a 10% lift, same CV: ≈ 900 per group, about 1,800 in total at 50/50 or about 5,000 at 90/10 (five months at 1,000 orders a month).
  • Checkout conversion is a noisier scoreboard than it looks, because most sessions do not buy. Using the 19% session-to-order rate from the worked example, spotting a 5% relative drop in conversion takes about 27,000 sessions per group, while a 20% relative drop takes about 1,700. The holdout is a guardrail against big losses, not a way to certify small gains.

Practical reading: if your upsell's honest effect is a 2–3% AOV bump, most stores under ~1,000 orders/month can never statistically confirm it. That is fine. Judge the offer on attach × margin per session (a directly measured number, no inference needed) and use the holdout to check conversion did not tank — a big conversion drop shows up long before a small AOV lift does. To work out how much conversion an AOV lift can afford to lose, use the break-even test in do upsells hurt conversion rate.

Three holdout designs, ranked by honesty:

  1. Random traffic split (best): 90% see the offer, 10% do not, assigned at session start. Needs a tool or a theme-level coin flip. Cleanest read.
  2. Time split: offer off every Wednesday, or off one week in four. Cheap, no tooling. Weakness: weekday mix and campaigns differ — run at least four cycles before deciding.
  3. Segment split: off for one device type or one market. Weakest — mobile buyers are not desktop buyers — but still beats pre/post.

Whichever you pick, compare the same three numbers in both groups: checkout conversion, net revenue per session, and refund rate. If conversion in the offer-on group is down more than the upsell revenue covers, the widget is a tax. Kill it or move it.

AOV Lift Is the Easiest Number to Fake

"AOV up 9% since install" is the headline every app wants you to screenshot. Four ways it lies:

  • Selection: the app counts only orders that touched an offer. Big carts see more offers. The app is taking credit for whales it did not create.
  • Season: installed November 1, AOV up by December. That is Q4, not the widget.
  • Mix shift: you launched a bundle SKU the same month. AOV rises with zero upsell contribution.
  • Survivorship: conversion fell, small-basket buyers left, the average of the remaining orders rose. Higher AOV, less money.

The fix is always the same: holdout, net revenue per session, margin. Never the AOV chart alone.

Do Not Double-Count Seats

The 4-seat rule is also an analytics rule. If the travel bottle is in the drawer and on the thank-you page, one order can show "two upsells." Attribute the line to the last seat that added it, or to the seat you decided owns that SKU.

Replenhair (UK hair, Oxify Analytics V2): £8,742 cart drawer, £4,136 product page, £2,573 post-purchase — £15,451. Three seats, one total, app-attributed since install and read on July 31, 2026. Case study.

Crossword: drawer-only in the same dashboard (PDP / post-purchase / thank-you at ₹0), ₹340,639 drawer-attributed since install (also read July 31, 2026), +20% additional revenue they reported vs baseline. That is how you prove a cart widget without mixing a checkout app into the screenshot.

Cannibalization: Did the Upsell Replace a Sale?

Did the upsell replace a product they would have bought anyway?

Signs:

  • Items per order flat, AOV up only because they swapped to the suggested SKU
  • The "upsell" is a cheaper variant of the hero product
  • Gift-with-purchase pulls a paid SKU out of the bag

Fix: exclude parent collections from recommending children that are already the intent. Do not recommend the $12 travel size next to a $12 travel size already in the cart. Read how we add cart upsells for the offer setup; this page is the scoreboard.

How to Track AJAX Cart Adds

Cart drawers do not reload a page, and about half of the stores we looked at show drawer markup: in our October 2026 check of 475 live Shopify stores, 243 (51.2%) showed cart-drawer markup or a drawer setting in their theme on October 11, 2026. That is a hand-picked sample of well-known brands, so it describes those stores, not Shopify as a whole. If your pixel only fires on page_viewed, you will under-count adds and over-trust checkout.

  1. Use Shopify's customer events / Web Pixel. Subscribe to product_added_to_cart (and product_removed_from_cart if you care about take-backs). Per Shopify's developer docs (read October 11, 2026), the add event carries data.cartLine: the line's cost, the variant (id, SKU, title, price, product) and the quantity. It has no field for line item properties.
  2. Stamp the widget's lines with a line item property, for example _upsell_seat = cart_drawer. Shopify's Liquid docs say a property name that starts with an underscore is hidden from customers at checkout, so a plain key such as upsell_seat would show on their order. Because the add event cannot see properties, split organic from widget lines on the order side: checkout_completed exposes checkout.lineItems[].properties (Checkout Extensibility shops only, per the docs), and the Admin API returns them as LineItem.customAttributes. Place one test order and confirm your key arrives before you build a report on it.
  3. Do not use "orders with SKU X" as impressions. That hides everyone who saw X and said no.

Google Analytics 4: mark the add as an event with item id + a custom param for placement. Shopify's own reports will not know "this add was the warranty toggle."

A 30-Day Cadence

  1. Days 1–3: confirm impressions > 0 on mobile, and check them by device, before you judge anything. A widget that never rendered has no CTR to read.
  2. Days 4–14: read CTR and attach. If attach is near zero, change price or product, not the button color.
  3. Days 15–30: read checkout conversion vs holdout. Keep or kill. Do not add a second offer until the first has a verdict.

Warranty, donation, and wrap each get their own scorecard. One blended "upsell revenue" number hides a gift wrap that works and a warranty that scares people. See warranty and donation.

Frequently Asked Questions

What is a good cart upsell attach rate?

There is no single healthy number. The Cartylabs calculator (read October 11, 2026) assumes 2–4% for generic add-ons and 5–10% for relevant cart upsells, which is a vendor's modelling assumption, not measured data. A $4 wrap on a $40 cart should attach more often than a $29 warranty on an $80 cart. If attach is near zero after two weeks, change the price, product or placement.

What is the average upsell take rate by placement?

One vendor dataset states its method: Growth Suite measured 66 million offer impressions across 250 Shopify stores (January to June 2026) and reported acceptance of 12% for cart drawer offers, 9% for checkout (Shopify Plus only, 28 stores), 7% for product page and 6% for post-purchase. That is offers accepted ÷ offers shown, not attach, and it is unaudited vendor data. Compare your own offers on margin per 100 sessions.

How many orders do I need to detect an AOV lift?

Lehr's rule of thumb is 16 × (CV ÷ lift)² orders per group at 80% power. With an order-value CV of 0.75 (compute yours from an order export), a 5% AOV lift needs about 3,600 orders in each group and a 10% lift about 900. A 90/10 holdout needs about 20,000 orders in total for the 5% case, so smaller stores should judge offers on attach × margin per session and use the holdout only to confirm conversion held.

Should I use pre/post or a holdout?

Holdout. Pre/post mixes ads, season, and shipping tests into the same chart. Keep a slice of traffic (or a repeating off week) without the offer, and compare checkout conversion and net revenue, not only AOV. A random 10% traffic split is the cleanest design; a time split or device split is weaker but still beats pre/post.

Does Oxify have A/B testing?

No built-in A/B lab. Analytics V2 reports app-attributed revenue by placement (cart, product page, post-purchase, thank-you). That is how we published Replenhair's £15,451 split and Crossword's drawer-only ₹340,639. You still design the off group yourself, for example with a time split or a theme-level coin flip.

Why don't Shopify reports match the app?

Shopify counts orders and products. It does not know which line was a widget tap unless you stamp a line item property or use the app's attribution. Drawer adds also never load a new page, so a pixel that only listens to page views misses them. Subscribe to product_added_to_cart instead.

Can upsells raise AOV and still lose money?

Yes. If checkout conversion falls enough, extra dollars per order do not cover the lost orders, which is why conversion versus a holdout is on the scorecard. Watch refunds on warranty offers and the cost of goods on free gifts too, because both can turn a revenue win into a margin loss.

How do I split upsell revenue by placement?

Give each placement its own offer SKU or a line item property, and sum only the extra lines, not the whole order. Never credit the cart and the thank-you page for the same bottle: assign each SKU to the last seat that added it, or to the seat you decided owns it.

Can a Web Pixel see which cart line came from the upsell widget?

Not from the add event alone. Shopify's product_added_to_cart payload carries a cartLine with cost, variant and quantity but no line item properties (developer docs, read October 11, 2026). Read your marker property from checkout_completed, which exposes checkout.lineItems[].properties on Checkout Extensibility shops, or from the order's line items in the Admin API, and test it on one real order first.

What to Do Next

Write the five numbers on a sheet. Stamp the offer with an underscore-prefixed line item property. Turn the widget off one day a week or on 10% of traffic. Read conversion before you add a second offer.

If you want placement-level revenue without guessing, Oxify Cart Drawer & Upsells (our app; see the cart drawer upsell page) shows cart vs product page vs post-purchase vs thank-you in Analytics V2 (that is the Replenhair £15,451 split). Bring your own holdout — we did not ship an A/B lab, so skip Oxify if built-in experiments are a requirement. $9.99/mo for up to 100 monthly orders, 14-day trial, per its App Store listing on October 11, 2026.

Ask AI about Oxify App