Shopify Product Recommendations Not Working: Diagnose Missing, Empty, or Wrong Results
The fastest way to diagnose Shopify product recommendations is to separate the native candidate response from the storefront that renders it. If Shopify returns the expected product, inspect the theme. If Shopify returns no products, inspect intent, manual configuration, and eligibility. If the request fails, inspect the anchor and request itself.
This distinction prevents a common waste of time: changing Search & Discovery settings while a theme selector is broken, or editing theme code while every expected candidate is being filtered out correctly.
The guide covers native related and complementary recommendations in Search & Discovery, Online Store themes using the Ajax API, and headless storefronts using the Storefront API. A third-party recommendation app can resemble these surfaces, but its candidate and tracking rules must be verified against that app.
Evidence boundary
Shopify facts below are scoped to official Search & Discovery, theme, Ajax API, Storefront API, standard-metafield, and analytics documentation checked July 28, 2026. This article does not claim that a third-party app follows the same path. No live store was available for this rewrite, so runtime claims are framed as reader-run tests with observable outcomes.
Chapter 1 · Fast native proof
Ask Shopify for the candidates before changing the theme
For an Online Store theme, the native JSON endpoint is the cleanest dividing line. Replace YOUR_PRODUCT_ID with the numeric
anchor product ID from its Shopify admin URL, open the request on the storefront domain, and preserve
any locale prefix used by the storefront.
Reader-run request
/recommendations/products.json?product_id=YOUR_PRODUCT_ID&limit=4&intent=related Change related to complementary to test the second intent. Shopify
accepts a limit from 1 to 10.
200 · products
Native source works
Compare returned product IDs and URLs with the visible cards.
200 · empty
Request worked
Inspect intent, manual relationships, eligibility, and cart state.
404
Anchor rejected
The product ID does not exist or the anchor is not published to Online Store.
422
Request rejected
The product ID is missing or the intent is not related or complementary.
This visual separates four response states that look identical when a theme hides an empty or failed module. It does not test a headless storefront or a third-party recommendation app.
A successful empty response is useful evidence. It proves that the route, anchor, and intent were accepted, but no candidate survived for that request. A successful response containing products shifts the investigation downstream to section rendering, card projection, or tracking.
Do not use the section’s initial HTML as the same proof. Shopify documents that the recommendations Liquid object
is not populated on the initial render. Theme JavaScript retrieves the populated section asynchronously,
so an initially empty placeholder can be expected.
Chapter 2 · Symptom map
Use the visible symptom to choose the first checkpoint
Do not begin by adding more manual recommendations. First describe exactly what the shopper sees and where. The symptom narrows the possible owner before you touch configuration.
Use a clean browser session when cart state matters. Shopify excludes products that are already in the visitor’s cart, so the same anchor can produce a different candidate set after an add.
| Visible symptom | First checkpoint | Do not start with |
|---|---|---|
| The section is absent on every product | Theme support, product template, section or block placement, and enabled state | Manual product selection or automatic recommendation quality |
| The section appears on some products only | Template assignment, anchor publication, empty response handling, and anchor identifier | A site-wide theme rewrite |
| Related products show, complementary products do not | Intent, manual complementary selection, candidate inventory, and theme block support | Assuming both intents use the same rules |
| The module is present but empty | Anchor request, candidate response, eligibility exclusions, and empty-state renderer | Changing the heading or card design |
| Products appear but are not useful | Recommendation intent, candidate source, catalog evidence, and manual or automatic mode | Treating a relevance problem as a visibility problem |
| The right product has the wrong price, image, or URL | API response, variant selection, card projection, cache, and clicked destination | Replacing the recommendation source |
| The storefront looks correct but reports are empty | Tracking parameters, visible impression, click path, event scope, consent, and report range | Tuning candidates based on missing analytics |
Chapter 3 · The native path
Trace the anchor and candidate as separate identities
The anchor is the product the recommendation request is about. The candidate is a product that may be returned. An invalid anchor can prevent the request from succeeding. An ineligible candidate can produce a valid but empty result.
Preserve both identities through the test. “The boot page” and “the spray” are not enough when templates, duplicated products, variants, combined listings, or market-specific offers exist. Record the product IDs and the exact storefront context.
Native recommendation trace
Template
Section or block
Anchor
Product ID + intent
Eligibility
Candidate gates
Response
Products or HTML
Storefront
Card + tracking
Trace key: anchor ID · candidate ID · intent · template · locale · market · cart state · response · rendered URL
The same heading can conceal different systems. A “You may also like” row in an Online Store theme can use the Ajax endpoint, while a headless storefront can query Storefront API and a third-party app can use neither. Identify the surface before applying a fix.
| Surface | Its job | Evidence it provides | What it does not prove |
|---|---|---|---|
| Search & Discovery admin | Stores manual relationships and related-product display mode | The anchor has the intended related or complementary selections | That the active theme requests or renders them |
| Online Store theme | Requests recommendation HTML or JSON and renders the cards | Network response and the final DOM agree on product identity | That a headless or app-owned module uses the same path |
| Ajax Product Recommendations API | Returns native candidates or rendered section HTML | Status, intent, returned IDs, URLs, and section response | That theme JavaScript inserts the response correctly |
| Storefront API | Returns recommendation products to a headless storefront | The productRecommendations query returns the expected intent and products | That an Online Store theme uses Storefront API |
| Third-party recommendation app | Defines its own candidates, rendering, and tracking contract | The app request, response, and implementation documentation | Anything about Shopify’s native recommendation output |
Chapter 4 · Eligibility contract
Related and complementary products do not share every rule
Shopify evaluates product state before a recommendation appears. Check the candidate that you expected, not only the products that survived into the module.
The inventory distinction matters. Shopify currently allows a related product with zero inventory to display when “continue selling when out of stock” is enabled. Complementary products require inventory above zero. A product can therefore appear for one intent and disappear for the other without a theme bug. These and the other candidate gates are listed in Shopify’s recommendation requirements.
| Candidate rule | Related | Complementary | Storefront proof |
|---|---|---|---|
| Active status | Required | Required | Candidate product status in Shopify admin |
| Online Store publication | Required | Required | Candidate is published to the Online Store sales channel |
| Price above zero | Required | Required | Current product or relevant variant offer |
| Inventory | Can display at zero when continue selling is enabled | Inventory must be above zero | Inventory plus continue-selling policy for the relevant item |
| Unlisted or gift card | Excluded | Excluded | Product type and unlisted state |
| Already in visitor cart | Excluded | Excluded | Repeat the test in a clean session and after adding the candidate |
Cart state is part of the test context
If the candidate disappears after it is added to cart, that can be expected native behavior. Test once in a clean session and once after adding the candidate. Record both outcomes instead of calling the second response inconsistent.
Chapter 5 · Candidate source
Find the system that actually produced the visible row
A Shopify storefront can contain a native related-products section, a complementary-products block, manual Search & Discovery relationships, Shopify’s automatic related products, an Ajax or section request, and a third-party app at the same time.
Do not infer the source from the heading. Theme copy such as “You may also like” can sit above several different systems. Inspect the template code, request, or app block and record the source explicitly.
| Candidate source | Where it is controlled | Expected behavior | Inspect first |
|---|---|---|---|
| Manual related products | Search & Discovery or the related-products standard metafield | Up to 10 selected products in “only manual” or “ahead” mode | Selection, display mode, order, request limit, eligibility, and ownership |
| Manual complementary products | Search & Discovery or the complementary-products standard metafield | Up to 10 selected add-ons that pass complementary eligibility | Selection, stock above zero, active state, publication, price, and cart state |
| Automatic related products | Shopify-generated related recommendations | Output can use purchase history, product descriptions, or related collections | Native order history, English-storefront condition for descriptions, collections, and combined-listing settings |
| Ajax JSON or section response | Online Store theme or custom theme JavaScript | Related or complementary output for the supplied product ID and locale-aware route | Request parameters, status, payload or HTML, section ID, and tracking URL |
| Storefront API | Headless storefront | Up to 10 products for RELATED or COMPLEMENTARY intent | Product ID or handle, intent, returned product fields, card mapping, and analytics |
Related and complementary are not two labels for the same candidate set. Shopify generates related recommendations automatically and lets a merchant add manual related products. Complementary recommendations require manual configuration in Search & Discovery. A request using the wrong intent can therefore return a technically valid but empty set.
Manual relationships are stored in Shopify-reserved standard metafields. This matters when another app, Flow workflow, bulk editor, or migration changes the same values. The Search & Discovery screen is not a separate source of truth.
| Control | Reserved namespace and key | Type | Effect on recommendations |
|---|---|---|---|
| Related products | shopify--discovery--product_recommendation.related_products | list.product_reference | Stores the manually selected related products. It does not contain Shopify-generated products. |
| Related products display | shopify--discovery--product_recommendation.related_products_display | single_line_text_field | “only manual” returns the selected set only. “ahead” puts selected products before generated products. |
| Complementary products | shopify--discovery--product_recommendation.complementary_products | list.product_reference | Stores manually selected add-ons. Shopify does not auto-generate this intent. |
Only manual
Exact curated source
Only selected related products are considered. If every selected product becomes ineligible, the result can be empty.
The eligibility filter still runs
A configured relationship is not a promise that the candidate will display. Product state, stock rules, cart state, and the request limit can reduce the visible set.
Ahead
Manual first, generated after
Selected related products lead the set. Generated related products can provide coverage after them.
For generated related products, Shopify documents three inputs: products bought together, similar product descriptions, and related collections. Purchase history requires prior sales. Description-based recommendations are documented for English storefronts. Related collections are used when purchase-history and description recommendations are unavailable. Imported orders from another store or platform are not used by the theme recommendation algorithm.
Generated output is not a stable snapshot. Shopify says it changes frequently and can differ between Search & Discovery preview and storefront. Stores using Combined Listings also have a setting that controls whether generated recommendations show child products, parent products, or both. Before calling a result wrong, record that setting and judge the relationship, not exact preview parity.
The standard-metafield definitions document the exact keys above. Shopify’s theme recommendation guide documents the generated inputs, imported-order limitation, asynchronous rendering, and request pattern.
For a deeper explanation of candidate generation, cold start, eligibility, ranking, and set quality, use the product recommendations pillar.
Chapter 6 · Diagnostic procedure
Run the checks in an order that preserves fault isolation
Use one anchor, one expected candidate, one intent, and one storefront context through the entire procedure. If you change products halfway through, you can no longer compare the checkpoints.
Step 1
Freeze one reproducible test case
Choose one anchor product and one expected candidate. Copy both numeric product IDs. Record related or complementary intent, the assigned product template, locale, cart state, and why that candidate should appear.
Pass
The expected outcome is a named product, not a vague judgment such as “better recommendations.”
Failure
The anchor, candidate, intent, or storefront context changes between checks.
Step 2
Verify the exact product template and module
Open the theme editor from the anchor product so Shopify loads its assigned template. Confirm the related-products section or complementary-products block exists, is visible, and is not only present on Default product.
Pass
The intended module has a visible container on the exact template used by the anchor.
Failure
The module is absent, hidden, placed on another template, or unsupported by the theme.
Step 3
Request native JSON before judging the theme
On the storefront domain, open the locale-aware recommendations/products.json endpoint with the anchor ID, a limit, and the intended related or complementary intent. Save the status and returned product IDs.
Pass
A 200 response separates native candidate generation from theme rendering.
Failure
A 404 points to the anchor or Online Store publication. A 422 points to the request contract.
Step 4
Run every candidate through eligibility
Check active status, Online Store publication, price, unlisted state, gift-card state, intent-specific inventory, and whether the candidate is already in the visitor cart.
Pass
The candidate passes the rules for the current related or complementary intent.
Failure
The product is correctly excluded. Repair its state or choose another candidate.
Step 5
Identify the candidate source and intent
Record whether the set is manual related, generated related, manual complementary, Ajax, Storefront API, or another app. For manual related products, record whether display mode is “only manual” or “ahead.”
Pass
The team can explain where each visible candidate came from.
Failure
The visible row is being attributed to the wrong system or uses the wrong intent.
Step 6
Compare source output with the rendered card
Capture the returned product IDs and URLs, then compare them with the DOM. Verify product and variant identity, image, price, availability, destination, heading, and card order.
Pass
The storefront preserves the candidate and its current purchasable state.
Failure
The response is correct but the renderer changes, hides, caches, or misrepresents it.
Step 7
Verify the exposure and click path
Confirm the module was actually visible, click the known candidate, and inspect the destination and tracking context. Use a test cart or order only when the environment safely supports it.
Pass
The request, impression, click, candidate, position, and downstream item remain connected.
Failure
The module looks fixed but the report cannot observe the exposure or action.
Chapter 7 · API and rendering
A correct response and a correct card are separate checkpoints
Shopify’s Ajax API currently accepts a product ID, a related or complementary intent, and an optional limit from one to ten. Use locale-aware URLs. The endpoint can return product JSON or HTML rendered from a section, depending on the path. The two responses answer different questions.
Capture the request and response before reading the page. If the expected candidate is absent from the response, inspect source and eligibility. If it is present in the response and absent or wrong on the page, the failure is in rendering, filtering, caching, or card projection.
Test candidate generation
JSON endpoint
/recommendations/products.json?product_id=ID&limit=4&intent=related Use the returned product IDs, order, availability fields, and Shopify-provided URLs to establish what the native source produced.
Test the Liquid section
Rendered HTML endpoint
/recommendations/products?product_id=ID§ion_id=SECTION&limit=4&intent=related A 404 here can mean either the anchor product or the supplied section ID was not found. Compare it with the JSON request to isolate which identity failed.
In theme code, build the request from routes.product_recommendations_url or window.Shopify.routes.root instead of hard-coding a root path. Shopify requires locale-aware Ajax URLs. The rendered section
should check recommendations.performed? before it assumes the object was populated.
Shopify’s returned product URL carries pr_* query parameters used by
native recommendation reports. If a custom card rebuilds the URL from the handle, it can display
the right product while discarding that recommendation context. Preserve the returned URL unless
you have a tested replacement measurement contract.
| Observed response | What it establishes | Next checkpoint |
|---|---|---|
| Products returned | The native candidate response exists. | Compare returned IDs, order, URLs, and intent with the visible cards. |
| Successful empty response | The request worked but no eligible candidates survived. | Inspect manual selection, automatic evidence, eligibility, and cart state. |
| 404 product not found | The anchor does not exist for the endpoint or is not published to Online Store. | Verify anchor ID and publication before inspecting candidate relevance. |
| 422 invalid parameter | The request is missing the product ID or uses an unsupported intent. | Correct the request contract. Shopify currently accepts related or complementary. |
| Correct response, wrong storefront | The failure is after candidate generation. | Inspect section ID, DOM insertion, card projection, cache, variants, and URLs. |
Compare one identity across response and card
Record the candidate product ID, selected or default variant, returned URL, rendered URL, image, price, availability, position, and heading. If the response carries a useful product but the card selects an unavailable default variant, candidate generation is not the first fix.
Headless storefronts use another proof surface
The Storefront API productRecommendations query accepts a product ID or handle plus RELATED or COMPLEMENTARY intent and returns up to
10 products. Shopify documents that complementary output still requires manual Search & Discovery
configuration. Do not diagnose a headless row by testing only the Online Store Ajax route.
The exact Ajax parameters, errors, section response, and tracking URL are documented in Shopify’s Product Recommendations API reference.
Chapter 8 · Symptom playbooks
Match the observed evidence to the smallest responsible repair
The same blank rectangle can be caused by a missing section, no request, an empty candidate set, or a failed insertion. These playbooks start with evidence that can distinguish those causes.
Nothing appears on any product page
Proof to collect
Check the assigned templates, then look for the recommendation network request and browser error.
Interpretation
No section means placement or theme support. A section with no request means its JavaScript did not run. A request with products means insertion or rendering failed.
Smallest repair
Add or enable the native section, repair the section JavaScript, or restore the selector it expects.
The row appears on Default product but not another template
Proof to collect
Compare the anchor products’ template assignments and open each template in the theme editor.
Interpretation
Recommendation configuration is not the first difference. The two products are using different page compositions.
Smallest repair
Add the intended section or block to the missing template and verify it with the same anchor.
A manually selected related product is missing
Proof to collect
Check the selected list, related display mode, request limit, candidate eligibility, and native JSON response.
Interpretation
The selection can be filtered out by eligibility. In “ahead” mode, generated products can fill the remaining space. The theme can also request fewer products than you selected.
Smallest repair
Fix the candidate state, increase the justified display limit, or use “only manual” when exact curation is the actual requirement.
Related products show, but complementary products are empty
Proof to collect
Confirm complementary products are manually selected, the request uses complementary intent, and each candidate has inventory above zero.
Interpretation
Related output can be generated automatically. Complementary output requires manual configuration and has the stricter stock rule.
Smallest repair
Add complementary relationships, correct the intent, replace ineligible candidates, or add the compatible theme block.
Generated related products look wrong
Proof to collect
Record whether the output came from purchase history, description similarity, or related collections; inspect imported-order history, language, collections, and combined listings.
Interpretation
The preview is not a fixed ranking contract. Shopify documents that generated output changes and can differ between Search & Discovery and the storefront.
Smallest repair
Use defensible manual relationships for important anchors, improve catalog grouping, and review the parent or child combined-listing setting.
JSON is correct, but the storefront row is empty
Proof to collect
Compare the JSON response with the section request, returned HTML, target container, selector, and browser console.
Interpretation
Candidate generation worked. A section ID, DOM selector, insertion condition, JavaScript error, or cache is dropping the result.
Smallest repair
Repair the rendering boundary without changing recommendation data.
The product is right, but the image, price, variant, or link is wrong
Proof to collect
Compare product and variant fields in the response with the final card and clicked URL.
Interpretation
The card is projecting a different variant or stale product state. This is not evidence that the candidate source is wrong.
Smallest repair
Use the current response fields, choose the intended available variant, and preserve Shopify’s returned product URL.
The storefront works, but recommendation reports look empty
Proof to collect
Confirm the card preserves the pr_* parameters in Shopify’s returned URL, then check the report scope and date range.
Interpretation
Search & Discovery shows recommendation click rate, purchase rate, and low-engagement reporting for the last 30 days. A live page check and a reporting window are different evidence.
Smallest repair
Restore the returned tracking URL, verify the tested surface is native, and evaluate the appropriate report range before changing candidates.
Chapter 9 · Verification
Prove the repair at the same layer that failed
A theme repair is complete when the intended module renders on the intended templates. An eligibility repair is complete when the known candidate survives the native rules. A source repair is complete when the expected relationship appears in the response. A rendering repair is complete when response and card agree. A measurement repair is complete when the card preserves the native recommendation URL and the appropriate report can attribute the outcome.
Repeat the test on desktop and mobile, in a clean session and with the candidate in the cart when relevant. Then sample another anchor that uses the same template and intent. One passing product proves the controlled case, not the entire catalog.
Keep this evidence packet
Anchor and candidate IDs, intent, template, locale, market, cart state, eligibility states, candidate source, request, response, rendered card, clicked URL, report scope, owner, change, and post-fix result.
Search & Discovery currently exposes recommendation click rate, purchase rate, and products with low engagement. The in-app metrics cover the last 30 days; Shopify directs other ranges to Analytics reports. Do not treat a report as a real-time request debugger. First prove the request and link, then evaluate the documented reporting window. Shopify’s recommendation-report documentation defines the available views.
If candidates are visible and technically correct but still unhelpful, the problem has moved from delivery to recommendation quality. Use the recommendation-system guide to review shopper job, candidate generation, ranking, and set constraints. If the module is in the wrong moment, use the placement guide. If the report is the weak layer, use the recommendation analytics guide.
Chapter 10 · Where ParticleSearch fits
ParticleSearch solves the recommendation system when the native module is the limitation
If the diagnostic proves that the theme is rendering correctly but the native candidate set, placement controls, or evidence are too limited, ParticleSearch is a direct replacement for that recommendation job. It can serve managed recommendation shelves on product and cart surfaces from the same search-ready catalogue used by the storefront search experience.
The merchant chooses the job rather than accepting one unexplained “you may also like” list. Current strategies include similar products, frequently bought together, complete the look, cart cross-sell, trending products, best sellers, and new arrivals. The shelf can have its own title and product limit, and ParticleSearch excludes the anchor or other context products so the module does not recommend the item the shopper is already considering.
Eligibility still follows store policy. Recommendations use the eligible catalogue, respect the configured sold-out and discontinued-product behaviour, and preserve the product or variant context through the shared storefront card. ParticleSearch does not make a draft product public, repair a wrong price, or decide that two products belong together when the catalogue and observed evidence do not support that relationship.
One configured surface
Product and cart placements use the same catalogue eligibility, product-card behaviour, and shopper context as the rest of ParticleSearch.
Observable outcomes
Views, clicks, empty shelves, and errors are recorded with placement and strategy context, so a weak shelf becomes evidence rather than a silent blank module.
A testable decision
Recommendation strategies can be compared on the recommendation surface, while verified order attribution remains separate from a claim of causal lift.
What the merchant no longer has to assemble
After a verified ParticleSearch launch, the team should not need one system to choose products, another card implementation to render them, and a third report to guess whether the shelf was seen. The merchant still chooses the placement, strategy, guardrails, and business interpretation. ParticleSearch owns the connected recommendation delivery and evidence path. Read the recommendation-system guide for the strategy decision and the analytics guide for the evidence contract.
Follow-up questions
Questions that should not restart the investigation
- How long should I wait for Shopify product recommendations to update?
- Shopify documents that generated related recommendations change frequently, but it does not publish a universal update SLA on the sources used here. Test the current API response and storefront instead of waiting an arbitrary number of hours.
- Can Shopify remove a product I selected manually?
- The relationship can remain configured while the candidate is filtered from the storefront because it is inactive, unpublished, unlisted, free, a gift card, out of stock under the applicable intent, or already in the visitor’s cart.
- Why does the Search & Discovery preview differ from the product page?
- Shopify explicitly documents that generated related recommendations can change and that the preview often differs from the storefront. Use a manual recommendation when a specific relationship must be stable.
- Does an empty HTML placeholder prove recommendations failed?
- No. Shopify theme recommendations are loaded asynchronously. The recommendations object is not populated during the initial section render, so the meaningful evidence is the later recommendation request and the returned section content.
- Should I clear the theme cache first?
- Only after the native response is correct and the storefront still shows stale output. Cache clearing cannot repair an invalid anchor, an empty eligible set, the wrong intent, or missing manual relationships.
Primary references
- Shopify: product recommendation requirements and customization
- Shopify: Ajax Product Recommendations API
- Shopify: implement related products in a theme
- Shopify: standard recommendation metafield definitions
- Shopify: Storefront API productRecommendations query
- Shopify: recommendation performance reports