01TL;DR
USA Clean's biggest unmet lever is returning-buyer retention: 39% of sessions are returning visitors, but only ~1.61% include a login. B2B parts buying is overwhelmingly repeat consumable purchasing on a cadence — exactly the shape purchase history personalizes well.
One deduped list of what an account actually buys is the seed for almost every retention feature on the roadmap — auto-ship/subscriptions, the reorder pad, replenishment reminders, one-click saved lists, spend visibility, frequently-bought-together, and faster checkout. None need new data; they need this list surfaced.
Keep two surfaces distinct: Buy Again (re-buy items you actually purchased — works for any account with one past order, ships in Stencil) and "based on recent purchases" (recommendations inferred from history — the custom/Hawk-powered cross-page layer).
| Phase | What ships | Effort |
|---|---|---|
| Phase 1 Surface it | Account Buy Again view (deduped line-items across orders; reorder + qty + save-to-list), native BC Reorder, native recently-viewed + a guest sign-in bridge. Generalize the account framing beyond National Accounts. | Medium — Caster front-end on Storefront order data |
| Phase 2 Personalize | "Based on recent purchases" modules on home / PLP / PDP / cart; line-item aggregation + cadence ("bought 4× · ~every 6 wks · due now"); seed saved-lists and replenishment reminders from it. | Higher — custom aggregation + 4 surfaces |
| Phase 3 Predict | Predictive replenishment + auto-ship, fleet-aware ranking, FBT via Hawk Recommendations (already paid for). | Highest — Catalyst-replatform candidate |
02Current state
Purchase history exists, but it's locked inside individual orders:
- The only reorder affordance is a per-order "Reorder" link on each row of the orders list (account-orders.html). To re-buy one filter you bought last month you must remember which order it was in, open it, and reorder the whole thing.
- No aggregated "things you buy" view. Nothing dedupes line-items across orders into "here are the 23 SKUs this account purchases, ranked by how often."
- No purchase-derived recommendations anywhere. PLP, PDP, home and cart are identical for a 5-year customer and a first-time guest. The signed-in home has a frequency-based "Reorder your usuals" rail (index-signed-in.html) — a good start, but it is re-buy, not the recommendation layer, and lives only on the home page.
- Recently-viewed is cookie-only. BC tracks viewed products in a cookie, but it is anonymous and resets — it never becomes "what this account looked at," and is never positioned as the carrot to log in.
- The account framing assumes a National Account. account.html leads with "Type: National," 3 sites, 5 users, fleet, approvals. A single-location buyer with one machine and one past order — the majority of the 39% — sees none of themselves in it.
The data is already there. It just isn't surfaced, deduped, or generalized beyond the National-Account persona.
03References
Amazon Business — "Buy Again"
The category-defining pattern: a dedicated tab that dedupes everything you've ordered into a re-buyable grid, with "bought N times," reorder, and "add to list." The model to emulate — purchase history as a shopping surface, not an audit log.
Grainger — order history + reorder lists
Industrial-distribution benchmark. Reorder from any past order, persistent reorder lists, and a "frequently ordered" view scoped to the account. Confirms the B2B expectation: repeat buyers want their catalog narrowed to their parts.
Staples Business / Uline — replenishment
Consumable-cadence done well: "you usually reorder this every ~6 weeks," subscribe-and-save, and proactive "running low?" nudges from purchase intervals. The bridge from Buy Again (P1) to predictive replenishment (P3).
McMaster-Carr — order history as navigation
For repeat industrial buyers, order history is the navigation — fast, dense, re-orderable rows. Sets the bar for the account Buy Again list's information density.
Sweepscrub (cleaning-vertical peer)
Same catalog shape as USA Clean (parts by brand→machine), but no account-scoped reorder or purchase personalization — the exact gap this brief closes for the vertical.
04What BC Stencil gives us
- Native Reorder + order history. The stock account area (
templates/pages/account/orders.html/order.html) lists past orders and exposes a native "Reorder" action that re-adds an order's items to the cart. The Phase-1 floor — no custom code to repeat an order. - Storefront GraphQL
customer.orders→lineItems. The raw material for deduping: query the customer's orders and line items, then aggregate into the "things you buy" list (SKU, name, qty, order count, last-ordered date). REST Orders v2 is the equivalent server-side path. - B2B Edition: company orders + Shopping Lists. For B2B-Edition companies, order history spans the whole company (all buyers/sites), and native Shopping Lists give a persistence target for "save these as a list" — the durable home for a curated Buy Again set (shared with saved-cart Phase 2).
- Native recently-viewed. Stencil exposes recently-viewed products (cookie-based
recently_viewed) renderable in any theme template — the honest, no-login basis for the guest surface. - Product
compatible_models[]custom field. The same field powering model-landing and search lets the PDP "you bought a compatible part" callout and fleet-aware ranking intersect history with machine fit. - Storefront Cart API for the add / add-all / qty actions every module needs.
05Stencil limitations
- No cross-page "based on recent purchases" module. Native BC has no merchandised recommendation surface driven by this customer's purchase history. Stock "Related products" are catalog-relationship based, not personalized. The home/PLP/PDP/cart modules are custom.
- No line-item dedupe / aggregation across orders. "Reorder" works per order; nothing rolls all orders up into a deduped, frequency-ranked SKU list. That aggregation is a custom query + transform.
- No consumable-cadence logic. "Bought every ~6 weeks · due now" requires computing inter-purchase intervals — no native field or report produces it.
- No merchandised Buy-Again rail. Surfacing reorder candidates outside the account (a home rail, a cart nudge) is theme + data work; BC ships no such component.
- Recently-viewed is cookie-scoped, not account-scoped. It knows what a browser viewed, never what an account bought, and doesn't survive a device switch. Honest copy must never imply we know a signed-out visitor's purchases.
- No fleet-aware ranking. Ordering reorder candidates by "what your registered machines consume" needs the fleet ↔
compatible_models[]↔ purchase-history join — custom, and best on a headless data layer.
06App marketplace shortlist
| Option | What it is | Verdict |
|---|---|---|
| Native BC Reorder + order history | Stock per-order reorder action. | ✓ Phase-1 floor |
| Custom purchase-history aggregation | One-time build: query orders, dedupe line-items, rank by frequency/recency, render in Caster. | ✓ Phase 1–2 path |
| Hawk Recommendations (already deployed) | HawkSearch's recommendations product; the theme already wires WEBPACK_HAWKSEARCH_RECOMMENDATIONS_URL. | ✓ Phase-3 recs engine |
| Personalization apps (Nosto, Rebuy, LimeSpot, Searchspring) | Third-party recommendation/personalization engines. | Skip — duplicate engine, Caster-foreign |
| Replenishment / subscription apps | Bolt-on subscribe-and-save. | ⏳ Evaluate at Phase 3 |
The Buy Again view and the cross-page modules are one-time builds against data we already store and an engine (Hawk) we already pay for. Any net-new personalization subscription (~$300–1,000+/mo) layers a recurring cost on top of capabilities we own — passing the one-time custom build inside ~12–18 months — and adds a Caster-foreign UI to maintain. It fails the amortization test for the recommendation job.
07Caster impact
Reused as-is: .scroll-row (the existing horizontal rail from index-signed-in.html), .product-card, .reorder-list / .reorder-row (the reorder pattern from shop-parts.html), .section-header (+ __label / __desc / __link), .pill, .stock-badge, .btn, .qty-stepper, .acct-tabs, .filter-rail.
New patterns, inline-scoped in v2/ first (Rule #7):
.reorder-row__freq— a frequency / cadence hint line on a reorder row ("bought 4× · last May 2 · ~every 6 wks · due now"). The atom that makes a reorder list feel personalized rather than historical..buy-again-callout— the PDP "you bought a compatible part" inset (.pill pill-accent+.btn btn-outline)..cart-reorder-nudge— the cart "add your usual consumables" block (a.reorder-listvariant with.qty-stepper)..guest-bridge— the signed-out "sign in to see everything you've bought" carrot card.
Promotion (done in v0.16.3): .scroll-row and .reorder-list / .reorder-row each hit their second consumer here, so they graduated from inline to components.css with showcase pages (layout/scroll-row.html, composites/reorder-row.html) and decisions.md entries D26/D27. The four feature-specific classes stay inline until a second consumer appears.
08Phased recommendation
Make purchase history a shopping surface, and generalize the account beyond National Accounts.
- Account "Buy Again" view — a deduped, line-item list aggregated across orders (not order-by-order), filterable by machine / category / site, each row with reorder +
.qty-stepper+ save-to-list. New tab in the account strip. - Lean on native Reorder for the per-order path; the new view aggregates over it.
- Generalize the framing — every Buy Again surface reads from raw line-items, so a single-site / single-machine buyer with one past order gets the full experience; National extras are additive.
- Guest bridge — native recently-viewed rail (honest: items viewed) + a "sign in to see everything you've bought" card targeting the 39%/1.61% gap.
What "winning" looks like: reorder rate from the account climbs, login rate among returning visitors rises (guest-bridge conversion), and repeat-order time-to-cart drops.
Take the deduped purchase list cross-page and add cadence:
- "Based on recent purchases" modules on home (recs rail), PLP ("you've bought from this category before"), PDP ("you bought a compatible part"), cart ("add your usual consumables").
- Aggregation + cadence service — compute frequency and inter-purchase interval per SKU to drive
.reorder-row__freqand "due now" sorting. - Seed downstream features — pre-fill saved-lists (saved-cart P2) and replenishment reminders from the same list.
Trigger: Phase 1 is live and reorder rate confirms demand; merch has begun populating compatible_models[] (shared with model-landing / search).
- Predictive replenishment + auto-ship from purchase cadence.
- Fleet-aware ranking — reorder candidates ordered by what the account's registered machines consume (fleet ↔
compatible_models[]↔ history). - FBT / "based on recent purchases" ranking via Hawk Recommendations (already deployed).
Catalyst-replatform candidate — see below.
09Implementation notes
Data sources
The whole feature reads from order line-items: Storefront GraphQL customer.orders.lineItems (or REST Orders v2) → dedupe by product/variant → aggregate { sku, name, orderCount, lastOrdered, intervalDays }. For B2B-Edition companies, query at the company scope so the list spans buyers/sites. compatible_models[] joins history to machine fit for the PDP callout and fleet ranking.
Auth / role gating
Buy Again and all "based on purchases" modules require a signed-in customer (or B2B company context); they render nothing for guests except the recently-viewed + bridge. In B2B Edition, respect role visibility — a junior buyer sees their own / their site's purchases per the account's permission model.
All-accounts generalization
Default copy is account-neutral (no "National," "fleet," or "sites" framing) so the experience fits a one-location buyer. National-only affordances (company-wide purchases, per-site filter, fleet ranking) are additive and degrade gracefully — absent data simply hides the control.
Accessibility
.scroll-row rails are keyboard-scrollable with visible focus and aria-label; reorder rows are a list with per-row actions labeled ("Add HEPA filter to cart"); qty steppers follow the existing .qty-stepper spinbutton semantics; the guest-bridge card is a labeled region, not an interstitial.
Analytics
- Buy Again CTR and reorder rate (added-to-cart from a reorder surface ÷ views).
- Guest-bridge login conversion (the retention metric — moves the 1.61%).
- Cadence accuracy: predicted-due vs. actual reorder, to tune Phase 3.
- Module attribution: cart adds sourced from home rail / PLP / PDP / cart nudge.
Mobile behavior
.scroll-row rails are already horizontal-scroll (native on touch); .reorder-list rows reflow to stacked on narrow widths; the account filter rail collapses above the list (matching account-orders.html's mobile pattern). 37% of traffic is mobile.
10Catalyst / replatform candidacy
Phase 1 + Phase 2 ship in Stencil. Aggregating order line-items via the Storefront/REST APIs and rendering Caster modules is Stencil-native — the account view, the four storefront modules, and the guest bridge need no replatform.
Phase 3 is the Catalyst case. Predictive replenishment, fleet-aware result ranking, and rendering Hawk Recommendations as first-class components all want a server-side data layer and React rendering that Stencil expresses awkwardly — the same forcing function as search P3 and model-landing P3. Personalization is the through-line that, across these three briefs, justifies the headless move — but none of them justify it alone, and Phases 1–2 deliver the retention win now.