The Shopify Storefront Audit Checklist: 20 Issues to Check Before Writing Custom Code

Picture a message from a merchant: one product page has stopped showing its size selector. The first instinct is to open the theme code and look for the cause. That instinct is understandable, and it is often wrong.
The selector might be missing because the variant data changed, because the product uses a different template than the one you are editing, because an app embed was switched off during a theme change, or because a script error stopped the page's JavaScript halfway through. The symptom is identical in every case: something is not on the screen. The causes live in different places, and only some of them are fixed by editing Liquid, CSS or JavaScript.
This is a working Shopify storefront audit checklist for telling those causes apart. The principle behind it is short:
Diagnose the source first. Check configuration second. Write custom code only when the evidence supports it.
You will get 20 checks in four groups, a decision tree you can follow when something breaks, a section on when custom code is actually justified, and a worksheet you can copy into a ticket or a notes file. It is written for merchants, theme developers, support engineers and freelancers doing Shopify theme troubleshooting.
Two notes on scope. This is a method, not a case report: every example below is illustrative, none of them is a diagnosis of a particular store, and not every check applies to every problem. And Shopify's interface changes, so treat the menu names here as a guide and confirm them in your own admin. Platform behavior is taken from Shopify's documentation, linked where it matters.
The order of investigation
- Reproduce it
- Which browser, device, theme, template
- Console and network evidence
- Theme settings
- Product and store data
- App embeds and app blocks
- Only with evidence
- Smallest change, tested on a copy
- Verified, with a way back
Code is the last layer to reach, not the first. The checks below are grouped by area of the store, not strictly in this order.
Before you begin: build a reproducible problem
Every check below assumes you can make the problem happen on demand. If you cannot, you are guessing, and a fix you cannot verify is not a fix. Spend five minutes writing the problem down before touching anything.
A useful problem record has these parts:
- The exact page and product. The full URL, not "the product page". Note the product handle or title, because the issue may only affect one product.
- Expected versus actual behavior. One sentence each. The expected sentence also defines what "fixed" means.
- Steps that reliably reproduce it. Numbered, starting from a fresh page load. Include which options were selected and in which order.
- Browser, device and viewport. For example "Safari on an iPhone, portrait" or "Chrome on a laptop at 1440 px wide".
- Who is affected. Everyone, only mobile visitors, only logged-in customers, only one country or currency, or only one product.
- Recent changes. A theme update, an app installed or updated, a settings change, a code edit, a product import. Even a rough date helps.
- Evidence. Screenshots or a short screen recording, timestamps, and any error message copied as text.
Page / product:
Expected:
Actual:
Steps to reproduce:
Browser / device / viewport:
Who is affected:
Recent changes:
Evidence (screenshots, timestamps, console messages):
Why this comes first. Each change you make before you understand the problem adds a variable. After an hour of edits you no longer know which one did what, and you may have fixed the symptom on your own screen while the visitor who reported it still sees the bug. A reproducible problem gives you a test you can run before the change and again after it.
Keep testing safe. Do not use a real customer's name, email or card. Do not place real orders on a live store while testing; stop before payment. Blur names, emails and addresses in screenshots. Console output, network requests and exported HAR files can contain cart tokens, cookies or customer identifiers, so redact them before sharing them in a ticket or a public forum.
How the checklist is organized
The checks run from broad to specific. Groups 1 and 2 separate environment, theme and data problems from app problems. Group 3 looks inside the cart and the browser. Group 4 covers performance, accessibility and how to ship a fix safely. Each check says what to look for, how to investigate, why it matters and when custom code may be justified.
Group 1: Storefront and theme fundamentals
1. Reproduce the issue across browsers and devices
- What to look for: Whether the problem appears in a second browser, in a private window, on a phone and on a different network, or only in one setup.
- How to investigate: Open the exact page in a private window first, then in a different browser, then on a real phone using mobile data. Shopify's own troubleshooting guide starts with the same local causes: stale cache and cookies, an outdated browser, blocked cookies, and a VPN or firewall. Browser extensions are a frequent culprit, so confirm whether your private window really runs without them. Record which combinations fail and which pass.
- Why it matters: A single test proves little in either direction. One failure on one laptop may be that laptop's extension. One pass does not mean the visitor who reported it is wrong. A comparison table of passes and failures shows whether you have a store-wide problem or an environment problem.
- Custom code may be justified when: the failure is consistent across clean environments, or it is tied to one browser engine in a way you can reproduce, such as a layout bug that only appears in Safari. Even then, start from the reproduction, not from the fix.
2. Compare desktop and mobile layouts
- What to look for: Elements that overflow the screen, controls that are hidden at some widths, content that overlaps (a sticky bar covering a button is common), and interactions that only work with a mouse hover.
- How to investigate: Use your browser's device toolbar and test several widths, not only one phone preset, especially around the width where the theme switches layouts. Then confirm on a real device, because emulation approximates touch but not the real browser toolbars that change the visible height, the on-screen keyboard or the device's performance. In the theme editor, use the mobile preview and read the mobile-specific settings in the section. Inspect the missing element: if it is present in the page but hidden, the Styles panel shows which rule hides it.
- Why it matters: Viewport size and theme settings can produce misleading symptoms. A button that seems missing may only be hidden at one width by a section setting. A "broken" cart button may only be covered by another fixed element.
- Custom code may be justified when: the overlap or overflow persists after you have checked the section settings, and the cause is a theme rule at a specific breakpoint. A scoped media query is a small, reviewable fix.
3. Verify the active theme and page template
- What to look for: Whether you are testing the published theme, an unpublished copy or a preview. Which template the product or page actually uses. Whether the theme editor is showing a market-specific view.
- How to investigate: In Online Store > Themes, note which theme is live. Load the storefront URL in a private window without any preview bar to see what visitors see. On the product in the admin, check its assigned theme template. Shopify's troubleshooting guide also points out that the theme editor has a market selector, and you may be editing a market-specific override without realizing it. Remember that customizations in one theme copy do not exist in another.
- Why it matters: It is easy to spend an hour editing a theme that visitors never see, or a template the product does not use. Shopify's help page on app blocks and embeds also notes that after you publish a different theme, apps are not active in it by default and must be reactivated.
- Custom code may be justified when: you have confirmed the code lives in the template that is actually rendered, for example a template-specific customization that never made it into a newer theme version and needs to be ported.
4. Review theme settings before editing CSS
- What to look for: Color schemes, button styles, typography, spacing, show and hide toggles, block order, and any per-section or mobile-specific settings that relate to the symptom.
- How to investigate: Open the affected section in the theme editor and read every setting in it. Change one, observe, and undo it. Compare with a similar section that looks correct. Shopify's guide gives a plain example: if you have not edited the code, review your theme settings, such as whether button colors contrast enough with the background.
- Why it matters: A setting change is supported, easy to reverse in the editor and survives theme updates better than custom CSS. Custom CSS written over a misconfigured setting hides the real problem and creates a second source of truth that the next person has to discover.
- Custom code may be justified when: the setting genuinely does not exist and the design requirement is clearly defined, such as a swatch style the theme does not offer. If the theme has a custom CSS field, keep the change small and comment why it exists.
5. Verify product, collection and content availability
- What to look for: Product status (active, draft or archived), whether the product is available to the Online Store sales channel, collection membership and conditions, whether the collection is published, changed URL handles, navigation links, and the template assigned to the page.
- How to investigate: Open the product in the admin and check status and sales channel availability. For a collection, check its conditions and whether the product matches. Check the navigation menu points at the right collection. These are the same product and collection checks Shopify lists in its troubleshooting guide. Then separate two cases: is the content absent from the page, or present but not visible? View the page source or inspect the DOM and search for the product title or the text in question.
- Why it matters: If the data is never delivered to the page, no amount of CSS will make it appear. If it is delivered and hidden, the data is fine and you are looking at rendering. Mixing these up is the most common reason fixes do not hold.
- Custom code may be justified when: the data is correct and present in the page, and the template simply does not render a field the merchant filled in.
Group 2: Product pages and app functionality
6. Test product variants and availability
- What to look for: Does selecting a variant update the price, availability, SKU, URL and media? Are unavailable combinations shown as sold out? Does the add to cart button reflect the selected variant?
- How to investigate: Reproduce on at least three variants and on more than one product, including a sold-out variant and a product with only one variant. In most themes the
?variant=value in the URL changes when you pick a variant, so watch it. In the admin, compare the variant's price, inventory settings, whether the product continues selling when out of stock, and which image is assigned to the variant. - Why it matters: If only one product fails, suspect that product's data, for example an option name that differs from the others. If every product fails, suspect the theme or a script. This is the quickest way to find out which of the two you are dealing with, and it is central to most Shopify product page issues.
- Custom code may be justified when: the variant data is correct everywhere and the theme's own variant script fails on all products, or when a clearly defined behavior (such as a specific message for an unavailable combination) is something the theme cannot be configured to do.
7. Inspect product options and conditional fields
- What to look for: Required inputs, fields that appear or disappear based on another choice, option dependencies, values that vanish when the variant changes or the page re-renders, and validation messages.
- How to investigate: First decide what kind of option you are looking at. Native variants are Shopify's own options (such as size or color), each combination having its own price, inventory and SKU. Custom product options are extra inputs such as engraving text or an uploaded file, supplied by theme code or an app. They are usually passed to the cart as line item properties, and they are not variants unless a tool deliberately creates variants. Fill the fields in different orders, change the variant after filling them, and refresh. Inspect the input: it must sit inside the product form, or be tied to it with the
formattribute, otherwise its value is not submitted with the add to cart. Line item properties are normally named likeproperties[Engraving]. Then verify the value in the cart (check 12). If an app provides the fields, check how it decides which products receive them, because apps assign options in different ways. - Why it matters: The wrong mental model produces the wrong fix. Debugging inventory for something that is really a text property wastes time, and the reverse is just as bad.
- Custom code may be justified when: the options come from your own theme code, or the app's documented integration expects a theme change for your particular theme.
8. Verify app embeds and app blocks
- What to look for: Whether the feature is an app block or an app embed, whether it is enabled in the theme you are actually testing, and whether it is placed on the right template.
- How to investigate: Per Shopify's help page on apps in the theme editor, an app block is app content placed inside a section or added as its own section, and an app embed is something that floats over the page or adds code without being visible, such as a chat bubble or a tracking script. For an app block, open the correct template, choose Add block and look in the Apps group. For an app embed, open the App embeds tab in the theme editor, find the app and toggle it on. In both cases, click Save and then check the storefront, not just the editor preview. Read the app's own documentation for which page types its block supports.
- Why it matters: Not every section supports app blocks, and Shopify's developer documentation explains that a section hosts app blocks only when its schema includes an
@appblock type. App embeds, according to the help page, work with any theme version. A missing feature is very often a disabled embed or a block that was never added to the new theme, not a bug. - Custom code may be justified when: the app's documentation says it needs a manual theme integration, or your section cannot host app blocks and a developer needs to add support. Some apps ask merchants to paste code into theme files or a Custom Liquid section; that is an app instruction, not a diagnosis.
Where app features live in the theme editor
- 1App embeds are switched on or off in the App embeds tab. They may render nothing visible.
- 2App blocks are added to a section with Add block, under Apps, and only appear in sections that support them.
- 3Nothing is live until you save. Then check the storefront in a private window.
A simplified schematic for explanation, not a screenshot of Shopify's interface. Labels vary by theme and over time.
9. Investigate theme and app conflicts
- What to look for: Two apps doing the same job (two review widgets, two cart drawers, two currency tools), scripts that modify the same element, CSS selectors broad enough to restyle something they should not, and handlers that fire twice, such as one click adding two items.
- How to investigate: Use controlled isolation on a duplicate theme (check 20), not on the live store. Disable one app embed at a time, repeat your reproduction steps and record the result after each step. Compare against an unmodified copy of the theme, which is also what Shopify's guide suggests to find out whether a problem belongs to your customizations or to the theme itself. In DevTools, the Styles panel shows which rule from which file wins, and the Network panel shows which scripts load and from where. Shopify's guide also lists temporarily uninstalling recently installed or updated storefront apps. In production, think first: uninstalling can remove app-side settings and data, may affect billing, and some apps place code in theme files that is not guaranteed to be cleaned up. Prefer disabling an embed in a copy, and read the app's uninstall instructions before removing it from a live store.
- Why it matters: Randomly uninstalling apps destroys evidence and can cause new problems. A methodical comparison tells you whether the conflict is between two apps, between an app and the theme, or between an app and your own custom code.
- Custom code may be justified when: the conflict is with your own customization, for example a selector that is too broad, and you can scope it. If the conflict is inside an app, send the app developer your reproduction steps and evidence before patching around it.
10. Check product-specific content and metafields
- What to look for: The same content appearing on every product that uses a template, content missing on some products, and blocks that are bound to a metafield versus blocks with fixed text.
- How to investigate: In the theme editor, open the block or section setting and look for the dynamic source option. Shopify's guide recommends dynamic sources such as product metafields so that each product shows its own content on a shared template. Then open two products in the admin and compare the metafield values. Check that the metafield definition's type matches what the theme can display. To tell data from rendering, search the page source for the metafield's text: if the text is there, the binding works and something is hiding it; if it is not, the binding or the data is the problem.
- Why it matters: A shared template with fixed text shows identical content everywhere, and that is configuration, not a bug. A bound block with an empty metafield shows nothing, and that is data, not CSS.
- Custom code may be justified when: the metafield exists with the right value, but no theme setting can display its type. A small snippet is reasonable then:
{%- comment -%}
Placeholders: use your own
metafield namespace and key.
{%- endcomment -%}
{%- if product.metafields.custom.size_guide != blank -%}
<div class="size-guide">{{ product.metafields.custom.size_guide }}</div>
{%- endif -%}
Group 3: Cart, JavaScript and integrations
11. Test add-to-cart behavior and quantity updates
- What to look for: Does the right variant and quantity reach the cart? Does the button work on the first click, after a variant change and on a double click? Do the cart drawer and the full cart page agree?
- How to investigate: Add a product, then open
/cart.json your store in a new tab. It returns the current cart as JSON, as described in Shopify's Ajax cart reference. Compare thevariant_idandquantityof each item with what you chose, then compare the cart drawer and the cart page with that JSON. In the Network panel, watch the add-to-cart request when you click (often listed asadd.js). Per the same reference, adding a sold-out variant or more than the available stock returns a 422 response with a description, which tells you the rejection came from inventory, not from broken JavaScript. - Why it matters: The cart interface and the cart state are related but distinct. The drawer is a picture of the cart, drawn by theme code. It can be stale or wrong while the cart itself is correct, and the reverse is also possible. Knowing which one is wrong halves the search.
- Custom code may be justified when:
/cart.jsis correct but the drawer or page does not refresh, or when your own add-to-cart script sends the wrong variant or quantity.
12. Verify cart properties and line-item information
- What to look for: Personalization text, selected designs or other custom values arriving in each line item's
properties, and surviving into the cart page, the checkout and the order. - How to investigate: Fill the custom fields, add to cart and read
/cart.js. Check the key names, the values and that each line carries its own properties. Two lines with the same variant but different properties are separate lines. Then check the cart page, the checkout and, in a test setup, the order in the admin. Verify at each step instead of trusting the screen: a drawer can display a value held in the browser that was never sent to the cart. Also know the convention that a property name starting with an underscore is hidden from the customer at checkout, while remaining visible on the order in the admin, and that whether the cart page hides it depends on your theme. - Why it matters: Data can be lost at several points: an input outside the form, a script that posts to the cart without the properties, or a cart template that never prints them. Checking each step tells you which one.
- Custom code may be justified when: the properties are in
/cart.jsbut the theme's cart template does not display them. A standard loop prints them and skips hidden underscore properties:
{%- for property in item.properties -%}
{%- assign first_char = property.first | slice: 0 -%}
{%- if first_char != '_' and property.last != blank -%}
<div>{{ property.first }}: {{ property.last }}</div>
{%- endif -%}
{%- endfor -%}
13. Inspect browser console errors
- What to look for: Red errors, failed initialization messages, scripts that failed to load, and warnings that appear at the moment the problem occurs.
- How to investigate: Open the Console in your browser's developer tools, enable Preserve log, reload and repeat your reproduction steps. Read the first error, not the last, because later errors often cascade from it. Click the file and line to open it in the Sources panel and see who owns it: your theme, an app, or a third party. Messages that mention
chrome-extension://come from a browser extension, not the store; retest in a clean window. See the figure below for how to read a few typical lines. For the general debugging approach around theme code, see the companion guide, How to Debug Shopify Theme Issues. - Why it matters: Not every console error causes a visible problem, and not every visible problem has a console error. An error is evidence when it lines up in time with the symptom and comes from code involved in the broken feature. A script that throws can stop the rest of that script from running, which is how one error produces several missing features.
- Custom code may be justified when: the error comes from a specific custom script of your own and you can identify the cause. Fix it at the source. Wrapping it in
try/catchto silence it, or adding another script to work around it, leaves the actual fault in place.
14. Inspect network requests and failed responses
- What to look for: Requests that fail (4xx or 5xx), are blocked, are cancelled or are slow, and the opposite case: a request that should have fired when you clicked, but did not.
- How to investigate: Open the Network panel, turn on Preserve log, filter by Fetch/XHR and repeat the action. Use Disable cache to behave like a first-time visitor and the throttling menu to see how the page behaves on a slow connection. Open a failing request and read its headers, payload and response. If nothing appears when you click, the click handler never ran, which points back to the console. A request marked as blocked is often a privacy or content blocker, so retest in a clean window. See the figure below.
- Why it matters: Do not assume every failed request is a Shopify platform problem, and do not treat every failure as actionable. A blocked analytics request on a visitor's browser is normal. What counts is the request tied to the broken feature, at the moment it breaks.
- Custom code may be justified when: the request payload built by theme or custom code is wrong, such as a missing variant ID, or a request goes to a script from an app that was removed long ago. Removing a stale reference to a deleted app is a legitimate small code change, as long as you have a backup.
Reading console and network evidence
- 1A script error from a file served by this store (the name is made up). Worth investigating if its timing matches the symptom.
- 2Blocked by the visitor's browser or an extension. Usually not the cause. Check whether it relates to the broken feature.
- 3From a browser extension, not the store. Retest in a clean window.
- 4A rejected request. Open the response: it explains why (for example, not enough stock).
- 5A script that no longer exists. Ask which app or theme setting still points at it.
An illustrative schematic with made-up file names, not output from a real store.
15. Verify currency, price updates and cart synchronization
- What to look for: Disagreement between the product page price, any displayed add-on price, the selected variant, the cart line prices and the totals, after a variant change, a quantity change or a switch of currency.
- How to investigate: Test the currency and market combinations that your store actually sells in, the way a visitor would select them, because stores differ in how pricing is configured and you should not assume yours matches another store's. Note the selected currency, then change the variant, add to cart and compare against
/cart.js, which reports the cart'scurrencyalong with line and total prices. Check the format of those numbers against the Ajax cart reference rather than assuming it. Ask where a displayed add-on price comes from: a real variant or line item, or a number computed in the browser. A number that is only displayed will not be in the cart total. Test discounts as a separate pass. What the customer finally pays is what checkout shows, so compare against that. - Why it matters: Mismatched prices are the kind of Shopify cart issue that damages trust fastest, and they often come from one layer displaying a calculation while another layer holds the real number. Avoid claims about how a particular app or Shopify Markets setup computes prices unless you have verified them in that store.
- Custom code may be justified when: the price shown comes from custom theme JavaScript that does not match the cart, and the right fix is to compute it from the same data the cart uses, using Shopify's money formatting instead of hard-coded currency symbols.
Group 4: Performance, accessibility and safe changes
16. Identify unnecessary scripts and oversized assets
- What to look for: Large or unscaled images, many third-party scripts, duplicate integrations (two analytics tags, two widgets doing the same thing), and scripts left behind by apps that were removed.
- How to investigate: Measure before you optimize. In the Network panel, sort by size and filter by images and scripts, then work out which theme or app owns each large item. Take a baseline with the Performance panel or PageSpeed Insights, and run it more than once, since results vary. Treat a Lighthouse score as one lab measurement of one page under simulated conditions, not a complete measure of storefront quality. For images, check that the theme requests an appropriate size using Liquid's
image_urlandimage_tagfilters, which can generate responsive images, instead of a fixed oversized file. - Why it matters: Heavy or duplicated assets can slow loading and responsiveness, which also makes scripts look broken when they are merely late. But removing something blindly can break a feature, so know what each item does before you cut it. No checklist can promise a particular speed result.
- Custom code may be justified when: a template outputs an oversized fixed-size image without responsive attributes, or you own a script that can safely be deferred. Do not remove an app's script by hand without understanding what depends on it.
17. Test keyboard navigation and focus behavior
- What to look for: Can every interactive control be reached with the Tab key and operated with the keyboard? Is the focus indicator visible? When a drawer or dialog opens, does focus move into it, does Escape close it, and does focus return to the control that opened it? Is there any place where focus gets trapped or lost?
- How to investigate: Put the mouse aside and work through the product page: Tab to the variant picker, change an option, add to cart, open the cart drawer, change a quantity and close it. Watch where the focus ring goes. In DevTools, inspect the control's
:focus-visiblestyles and look foroutline: nonewithout a replacement. - Why it matters: Keyboard access is a basic requirement for many visitors (see WCAG's keyboard and focus visible criteria). It also exposes real script problems: a control built from a non-interactive element, or a drawer that never manages focus, often shows up as a functional bug elsewhere.
- Custom code may be justified when: a custom control is built from elements that cannot take focus, or an outline was removed with nothing in its place. Prefer a native
buttonorinputover adding roles and handlers to adiv.
18. Review labels, contrast and accessible controls
- What to look for: Form fields with real labels (not only placeholder text), icon-only buttons such as the cart, close and quantity controls with an accessible name, error messages that are connected to their fields and not conveyed by color alone, text and control contrast, and the right element for the job: links navigate, buttons act.
- How to investigate: The Accessibility tab in DevTools shows the computed name and role of an element. The color picker in the Styles panel shows the contrast ratio, and WCAG's contrast criteria ask for at least 4.5:1 for normal text and 3:1 for large text and user interface components. Automated audits such as Lighthouse catch only a subset of problems, so also try the main purchase flow with a screen reader, such as VoiceOver on macOS or NVDA on Windows.
- Why it matters: An interface that looks right can still be hard or impossible to use. This also loops back to check 4: contrast problems frequently come from theme color settings, which is a configuration fix.
- Custom code may be justified when: a custom component has no accessible name or role, or an error message is not tied to its field. Add an
aria-labelto an icon-only button, or use the correct element, in the smallest change that works.
19. Review recent changes and isolate the likely cause
- What to look for: Whether the issue began after a theme update, an app being installed, updated or removed, a settings change, a code edit, a product import or a theme switch.
- How to investigate: Write down the date the problem was first reported and line it up with what changed. In Online Store > Themes > Edit code, the code editor's Timeline view lets you browse and restore earlier versions of a file. Shopify's troubleshooting guide notes that restoring a previous version replaces the whole file, so copy your current contents first. Compare an older theme copy with the current one: if the older one passes your reproduction steps, the cause is in the difference. If you use the Shopify CLI, pulling both versions into Git makes that comparison a normal diff. Change one thing at a time and retest after each.
- Why it matters: Knowing when it started cuts the search from hundreds of files and settings down to a handful. It also protects you from blaming a recent change that is actually unrelated.
- Custom code may be justified when: the comparison points to a specific code change that caused the regression. Then the right fix is usually to correct or revert that change, not to layer new code on top of it.
20. Test the smallest safe fix before publishing
- What to look for: The smallest single change that addresses the cause you identified, and a safe place to try it.
- How to investigate: Work in a duplicate theme, not on the live one. In Online Store > Themes, open the theme's menu and choose Duplicate, as described in Shopify's help page on duplicating themes. The copy appears in your theme list, and a store can hold up to 20 themes, so you may need to delete an old copy first. Make one change, preview it and run your reproduction steps. Two cautions: a duplicate is not a sandbox for the rest of the store, because products, apps and customers are shared, so do not complete real orders; and do not assume app embeds and blocks behave identically in the copy, so check them.
- Why it matters: Experimenting on a live storefront means visitors see every half-finished attempt, and you cannot easily tell which change caused what.
- Custom code may be justified when: the earlier checks all point to it. Before publishing, run through this list:
Verification checklist for a fix
- The original reproduction steps now pass, in the browsers and devices where it failed.
- It works on a second product and a second variant, not only the one you fixed.
- Mobile and desktop layouts both look right at several widths.
- Add to cart, quantity changes, removal, cart drawer and cart page all still work, and the properties and prices in
/cart.jsare correct. - Keyboard navigation still works, and the console shows no new errors.
- Other templates and sections that share the file you edited are unaffected.
- Rollback plan: keep the previous theme version available, know how to republish it, note the file's Timeline entry, and re-test on the live store with a non-purchase check right after publishing.
A practical troubleshooting decision tree
Follow the questions in order. Each answer either sends you to a check or lets you continue. At no point does the tree tell you to publish an untested change.
Troubleshooting decision tree
- 1. Can you reproduce the issue?
- NoCollect the page, steps, browser, device and a recording. Do not change anything yet.
- YesWrite the steps down and continue.
- 2. Does it happen across browsers and devices?
- Only oneSuspect an extension, cache, browser or device-specific layout. Checks 1 and 2.
- EverywhereIt is not a one-browser problem. Continue.
- 3. Does it still happen on an unmodified copy of the theme, or a clean default theme preview?
- NoSomething in your customizations or in how they interact is involved. Continue.
- YesSuspect product data, app configuration or the theme itself. Checks 5 to 10, then contact the theme or app developer with your evidence.
- 4. Is it connected to settings, app configuration, store data or a recent change?
- YesFix it there and re-run your steps. Checks 3, 4, 5, 8, 10 and 19.
- NoContinue.
- 5. Is there evidence pointing to code?
- NoKeep investigating. A hunch is not evidence. Checks 13 and 14.
- YesA console error from a specific file, a wrong request payload, a CSS rule that wins, or a diff that introduced it. Continue.
- 6. Can the smallest change fix it without regressions?
- YesMake it in a duplicate theme, run the verification checklist, then publish with a rollback plan. Check 20.
- NoRevert the attempt, narrow the change, or hand the evidence to the app or theme developer.
The same tree as plain text is below, for pasting into a ticket.
Plain-text version of the decision tree
1. Can you reproduce it?
No -> gather steps, browser, device, recording. Change nothing.
Yes -> continue
2. Does it happen across browsers and devices?
Only one -> extension, cache, browser, device layout (checks 1, 2)
All -> not a one-browser problem, continue
3. Does it still happen on an unmodified theme copy or clean preview?
Yes -> product data, app config, theme itself (checks 5-10); contact the developer with evidence
No -> continue
4. Linked to settings, app config, store data or a recent change?
Yes -> fix there, retest (checks 3, 4, 5, 8, 10, 19)
No -> continue
5. Is there evidence pointing to code?
No -> keep investigating (checks 13, 14)
Yes -> continue
6. Can the smallest change fix it without regressions?
Yes -> duplicate theme, verify, publish with rollback plan (check 20)
No -> revert, narrow the change, or escalate with evidenceWhen should you actually write custom code?
Custom code is the right tool when all of these are true:
- The expected behavior is clearly defined.
- The issue is reproducible.
- Relevant settings and supported configuration options have been checked.
- The evidence points toward a theme-level or integration-level limitation.
- A code change addresses the actual cause rather than hiding the symptom.
- The change can be tested and maintained safely.
If one of those is missing, you are not ready to write code yet. Custom code is also something you have to maintain: it can break on the next theme update, and the next person has to find and understand it. That cost is why any Shopify theme customization is worth justifying first.
Four short examples show the difference. They are illustrations of the reasoning, not diagnoses for any particular store.
| Situation | Start with | Code appropriate? |
|---|---|---|
| A button is invisible because its text and background colors are the same | Theme settings for the button and color scheme (check 4) | Not until the settings are ruled out |
| An app feature is absent because its app embed is disabled | Enable the embed, save, verify (check 8) | No. Verify the embed before editing theme files |
| A layout bug persists after relevant settings and compatibility checks | A targeted CSS change, tested in a duplicate theme (checks 2, 20) | Yes, if scoped and tested |
| A JavaScript error comes from a specific custom script | The code responsible for that error (check 13) | Fix that code. Do not add a second script to work around it |
A reusable storefront audit worksheet
Use one row per check you actually run. Statuses: Not checked, Passed, Failed (the check found a problem), Needs investigation (the result is unclear). The first three rows are examples only. They do not describe a real store.
| Check | Status | Evidence | Next action |
|---|---|---|---|
| 1. Reproduce across browsers | Failed | Fails in Chrome and Safari, passes on a phone (example only) | Move to check 2 |
| 8. App embeds and blocks | Needs investigation | Embed is on, block not found in the product template (example only) | Check which template the product uses |
| 13. Console errors | Not checked | Run after check 8 |
A blank copy, as a table and as plain Markdown you can paste:
| Check | Status | Evidence | Next action |
|---|---|---|---|
| Check number and name | Not checked | What you saw, with a date or timestamp | What you will do next |
| Check number and name | Not checked | What you saw, with a date or timestamp | What you will do next |
| Check number and name | Not checked | What you saw, with a date or timestamp | What you will do next |
| Check | Status | Evidence | Next action |
| --- | --- | --- | --- |
| 8. App embeds | Not checked | What you saw | Next step |
Conclusion
A structured investigation is not always the fastest first move. It is the one that makes the fix hold. By reproducing the issue, comparing environments, checking settings and data, reading the console and network evidence and only then writing a small, tested change, you end up fixing causes instead of symptoms, and you leave a written trail the next person can follow.
The rule to keep: identify the cause before you choose the fix. Sometimes the answer is a toggle, a template assignment or a metafield. Sometimes it is a few lines of code. The checklist is there to tell you which.
If this was useful, the guide on how to debug Shopify theme issues goes deeper on the code layer, and the about page and experience page explain the work behind these habits. For a quick automated look at speed, SEO and theme signals, the site also has a free store audit; it complements the manual checks here, it does not replace reproducing the problem.
Further reading
- Shopify Help Center: Troubleshooting theme issues
- Shopify Help Center: Apps in the theme editor (app blocks and embeds)
- Shopify Help Center: Duplicating themes
- Shopify.dev: App blocks in theme architecture
- Shopify.dev: Ajax Cart API reference
- Chrome DevTools: Network panel reference
- W3C: WCAG 2.2 quick reference
- Google Search Central: Creating helpful, reliable, people-first content