Shopify Builds>Capabilities>Product recommendations and cross-sell

Product Recommendations and Cross-Sell on Shopify

Definition

Product recommendations and cross-sell rails on a Shopify storefront, built two ways: computed, where the theme asks Shopify's Product Recommendations API for products related or complementary to one anchor product; and curated, where a merchandiser's chosen set lives in product-list metafields, block settings or metaobject rules and the theme renders it with live prices and a working add-to-cart. Includes cross-sell on the product page, in the cart and on content pages.

The Evidence

  • Evidence strength: 10 live, Deploi-attributed builds across 3 Shopify storefronts.
  • Split by storefront: LUS Brands 4, Nudestix 3, Three Ships 3.
  • Split by attribution: 6 Deploi-authored, 4 modifications of vendor theme code — disclosed as such on each build page.
  • Evidence quality: five carry code plus client working records. Five are documented from the code; no client-side record of the decision survives.
  • Confidence: 5 strong, 5 moderate.
  • Surfaces: product pages, the cart drawer, content and landing pages, home.
  • Status: Live, verified 2026-09-07.
  • Four of the 10 have published build pages.

Read the four before you read the number. One calls Shopify's Product Recommendations API; the other three render sets a person chose. That split is the finding on this page, and a better buy-vs-build argument than any comparison of recommendation apps.

How It's Actually Built

Two data sources feed this capability, and they share one rendering rule.

Computed: one anchor, one endpoint. recommendations/products.json takes a product_id, a limit and an intent. complementary returns the products a merchandiser has paired with that one in the Search & Discovery app; related returns what the algorithm associates with it. The endpoint is per product, so anything that wants recommendations against a cart has to choose which line speaks for it. On Nudestix, Liquid walks cart.items on every drawer render, picks the first paid, non-gift line as the anchor, writes it and every cart product id onto a [data-cart-cross-sell] container, and the theme's cart.js does the rest: complementary first, related if that comes back empty, everything already in the cart dropped, up to four cards, the whole row hidden when nothing survives. Because the drawer is thrown away and re-rendered through the Section Rendering API on every mutation, each fetch is memoised in a Map keyed by product, limit and intent — a rebuilt drawer with the same anchor renders from memory.

Curated: the set is product data. On LUS Brands, product.metafields.custom.bundle_and_save is a product-list metafield, and bundle_and_save.liquid renders one card per entry — the theme's own price snippet called with the explicit variant, a supporting line read from custom.bundle_sub_text on the recommended product, and a real <product-form> with a unique id, so five cards are five forms that add through Dawn's own path. On Three Ships, the cross-sell lives at the end of an ingredient entry: two product pickers on the block, a subtitle from the product's my_fields.target metafield, and a price compared against compare_at_price in Liquid so a sale set this morning is on the card this afternoon. And on the LUS quiz, the mapping from answers to products is 34 priority-ordered rules held in metaobjects — required, any and blocked option lists — matched in the browser against product cards Liquid already rendered into hidden <template> elements.

The rule they share. Whatever chose the product, the card is honest about it. The price is the theme's price snippet or a Liquid comparison against the live catalog, never a number copied into a second system. The add is the theme's add — Dawn's <product-form>, or a /cart/add.js post followed by the same section refresh every other cart mutation uses. None of these builds reimplements money or the cart.

The Buy-vs-Build Position

The corpus's own verdict, restated here with the vendor in a neutral role rather than quoted as written: on two storefronts, Shopify's native endpoint plus curated metafield rails covered the need; the third runs Rebuy alongside the theme's own rails and still needed placement work in the theme.

We'd put it more sharply. A recommendation-app comparison answers which vendor's algorithm is better; these builds answer a different question. The real fork is whether your cross-sell is a data problem or a merchandising opinion. "People who bought this also bought" is data, and Shopify already computes it for you at an endpoint you don't pay extra for; a merchandiser can curate the complementary side in Search & Discovery without touching the theme. "This cleanser, this conditioner and this styler are the routine that goes with this product, and here's why" is an opinion with copy attached, and no algorithm will produce it. That one belongs in product data the merchandiser owns, rendered by the theme. The framework is in Product recommendations: buy or build?

The Builds

LUS Brands — Dawn 15.4.1

Nudestix — Dawn 6.0.2

Three Ships — Palo Alto 5.8.0 by Presidio Creative

Four of the remaining six count toward the evidence above and have no published page yet; the other two are folded into build pages already published here. Among the four are the vendor-derived recommendation carousels on Nudestix and Three Ships — the theme's own lazy-fetch recommendations element kept, with local carousel markup and styling around it — and a collection-driven product rail on Three Ships landing pages that reuses the vendor's recommendation shell with a merchandiser-picked collection as its source. That is the algorithmic side of this capability, and most of it is the theme vendor's; the curated side is mostly ours.

What This Rests On

  • Liquid section schema and settings — the block that hosts a rail, the pickers and labels a merchandiser edits, and the switch that renders it.
  • Metafields — the product-list field that is a curated set, and the per-product line of copy that travels with a recommended product wherever it appears.
  • Cart AJAX API — every card adds through it, whether via Dawn's product form or a direct post.
  • Section Rendering API — the drawer refresh a cart rail has to survive, and the fetch behind the vendor-derived product-page carousels.
  • Custom elements — the lazy-fetch and carousel components on the vendor-derived rails.
  • Theme blocks and theme sections — the glossary's per-entry authoring, split across section instances to clear the block cap.
  • Metaobjects — the quiz rule set: recommendation logic as data the brand team edits.
  • Product Recommendations API — in one build in this set, and the whole of its computed half.

The primitive the capability is named for sits last, and appears once in the primitive record — though both vendor-derived carousels fetch the same endpoint. Most of this work rests on the same authoring primitives as the rest of the product page.

What Varies by Storefront

What sells together, and who decides, sets the shape on each storefront.

LUS Brands runs Dawn 15.4.1, and curl care sells as a routine — a cleanser, a conditioner, a styler that belong together in an order a person chose. So the builds here are curation: product-page rails read from product-list metafields inside our own product section, and the quiz's rule set in metaobjects. The relationship data arrived from the client as a mapping and became product fields. Nothing on this storefront asks an algorithm what goes with what.

Nudestix runs Dawn 6.0.2, sells shade-led color cosmetics, and its three builds lean the other way. The cart drawer asks Shopify's endpoint, with the merchandiser curating the complementary side in Search & Discovery rather than in the theme, and the product page keeps a Dawn-derived recommendations carousel. The third build indexed here is product-page content architecture — accordions and tabs — rather than a rail, and we'd read the Nudestix count as two rails and one neighbor.

Three Ships runs Palo Alto 5.8.0 by Presidio Creative, a paid premium theme, and carries the largest installed stack of the three, including Rebuy in the cart. The vendor theme ships its own recommendation and recently-viewed sections; those are theme-vendor code and aren't counted here. What is counted is the work around them — a viewport-triggered recommendations section and a collection-driven rail, both extensions of vendor sections — and the one fully authored build, which moved curated cross-sell off the product page and onto an ingredient glossary.

Where This Gets Hard

One product has to speak for a whole cart. The endpoint is per product. A cart cross-sell anchors on one line and lives with the answer being about that line — a mixed cart is represented by whichever paid product comes first, and adding a recommended product can change which product anchors the next set. Cart-wide apps exist because this limit does.

Curation has a maintenance bill, and it's per product. A set held in a product's metafield is that product's set. A newly launched product appears in no rail until someone edits every product that should carry it. A merchandising team that won't keep sets current is better served by the endpoint, which they can curate once in Search & Discovery.

A curated rail shows a saving; it doesn't make one. The price on a card is the product's own compare-at. If the set needs a price that only exists when the items are bought together, none of these builds produces it — that's a discount engine, and it's the half of this problem that is genuinely worth renting.

Rendering isn't free either way. A curated set of five is five complete product forms in the server HTML of a page that already has one. A computed row is script-rendered, appears a beat after the drawer does, and leaves the theme owning every failure state an app would have handled.

So there are cases where we say don't build. If you need bundle-only pricing, testing on which sets convert, or rules that reason across the whole cart, buy that and let the theme render around it. If your cross-sell is "people also bought," use the endpoint — it's already yours. Build when the recommendation is an opinion your merchandisers already hold, because an opinion belongs in product data, not in a vendor's dashboard.

Related Capabilities

Answers to Help You Make Smart Decisions

Do I need a recommendations app on Shopify?

Not for the basic case. Shopify's Product Recommendations API already returns related products for any product, and complementary products once a merchandiser pairs them in the Search & Discovery app. A theme can render that at no extra subscription. Apps earn their fee on what the endpoint doesn't do: rules across the whole cart, bundle-only pricing, testing and reporting on what converted.

What's the difference between related and complementary recommendations?

Both come from the same endpoint, keyed by intent. Related is computed — products the algorithm associates with the one you asked about. Complementary is curated — products a merchandiser paired with it in the Search & Discovery app. The cart build here asks for complementary first and falls back to related, so an uncurated product still gets a row.

Can a curated cross-sell rail add to cart directly from the card?

Yes, and it's the part worth doing properly. On the product-page rail here each card is a real product form with its own id, posting through Dawn's own <product-form> element, so a bundle card adds exactly the way the main buy button does and the drawer refreshes through the same path. The trade is weight: a set of five is five forms in the page's HTML.

How do I recommend products against a whole cart, not one product?

Shopify's endpoint takes one product id, so a cart rail has to pick an anchor. The build here chooses the first paid, non-gift line, asks for its complementary products, and filters out everything already in the cart. If you need reasoning across every line at once — "these three together suggest this fourth" — that's what cart cross-sell apps sell, and it's a fair reason to buy one.

Ready to Decide Whether Your Cross-Sell Is Data or an Opinion?

If it's data, you already own the endpoint. If it's an opinion, it belongs in your product fields, on the page, with a real price and a real add button. Contact us today and we'll tell you which one you have.

Builds