Shopify Liquid: Single = in {% if %} Always Evaluates True — = vs == Explained
Here is a bug that affects hundreds of Shopify themes and is almost impossible to spot by reading code: {% if product.type = 'Shirts' %} evaluates to true for every product, including shoes and bags. There is no error, no warning, no log entry — just wrong output on every page that uses the conditional. Liquid's parser silently treats single = as an assignment expression, which is always truthy. This guide explains exactly what happens and how to find every instance in your theme.
Why single = always evaluates to true in Liquid
Liquid treats = inside {% if %} as an assignment expression, not a comparison. Assignment expressions evaluate to the assigned value — any non-nil, non-false value is truthy. So {% if product.type = 'Shirts' %} assigns the string 'Shirts' and evaluates as truthy regardless of what product.type actually contains. Unlike JavaScript or Python where = in a conditional triggers a syntax error, Liquid silently accepts it and produces wrong output on every iteration.
How to find every occurrence in your theme
In VS Code, open global search (Cmd+Shift+F on Mac, Ctrl+Shift+F on Windows), enable regex mode, and search: \{%-?\s*(if|elsif)[^%]*[^=!<>]=[^=]. This matches any if or elsif containing = not preceded or followed by another = (which would be ==), not preceded by !, <, or > (which would be !=, <=, >=). Review every match. Theme Check's LiquidSyntaxError rule also catches some cases.
Liquid comparison operators — complete reference
Liquid supports six comparison operators: == (equal), != (not equal), > (greater than), < (less than), >= (greater than or equal), <= (less than or equal). For substring matching and array membership: contains. There is no single = comparison operator. Liquid comparisons are case-sensitive — 'shirts' == 'Shirts' is false.
Other silent comparison mistakes in Liquid
Two other comparison mistakes cause silent bugs. First: operator precedence — Liquid evaluates left to right without precedence, so {% if a == 1 or b == 2 and c == 3 %} evaluates as (a == 1 or b == 2) and c == 3, not what JavaScript developers expect. Second: comparing numbers stored as metafield strings — coerce with {{ metafield.value | plus: 0 }} before numeric comparison.
The fix: before and after
// CODE_COMPARISON
Frequently asked questions
- Does Liquid throw any visible error when I use = instead of ==?
No. Liquid silently treats = as a truthy assignment expression and renders the if-block for every element. No runtime error, no browser console warning, no Shopify admin notification. The only ways to detect it are code review, regex search, or Theme Check static analysis.
- Are there other Liquid operators I might confuse with ==?
The contains operator is frequently confused with ==. Use contains for substring matching (product.title contains 'Sale') or array membership (product.tags contains 'featured'). Use == only for exact equality. Liquid has no === operator — == covers type-aware equality.
- Can Theme Check catch this bug automatically?
Theme Check catches some instances via LiquidHTMLSyntaxError and SyntaxError rules but does not have a dedicated rule for the single-equals comparison pattern. A regex search across your theme is more reliable for finding this specific issue comprehensively.
// SCAN_YOUR_CODE
Does your theme have this bug?
Paste your code. Syphio automatically detects and fixes this error and hundreds of others — in seconds.
Validate my Liquid →