Formula comparison
A comparison across up to four products, measured on rows you define — strength, texture, frequency, pairing, or anything else. On a product template it leads with the product being viewed and lets the customer choose what to compare it against.
- Merchant-addable
- Yes
- Settings
- 47
- Block types
- 2
- Max blocks
- 10
- File
sections/formula-comparison.liquid
Used by default on: Product, Product (set)
When to use it
When customers ask "which one is right for me" and the answer depends on more than price. Works as a fixed comparison on a collection or landing page, and as a per-product comparison on a product template.
Setting it up
- Add the section and write the heading and intro under Content.
- Define your measures under Comparison rows. These become the rows and apply to every column, so pick measures every product can actually answer.
- Give each row a Value source so it fills from each product's category attributes rather than typed text. The first three rows ship pointed at real attributes already. See Per-product content.
- Decide where the columns come from with Column products under Comparison columns. Leave it on formula blocks for a fixed comparison; switch it to the product being viewed on a product template.
- For a fixed comparison, add one Formula block per product, up to four — each picks a product and answers each row.
- For a per-product comparison, set Collection customers compare within and size it with Columns to compare. Every row then needs a value source, because a product the customer swaps in has no block to type into.
- The collection is chosen before Product type is filtered. Leaving the collection blank uses each product’s smallest collection with at least two products, so comparisons can differ between pages. The same-type filter searches only that collection; if no other product matches, the section is hidden. Select a shared collection explicitly for consistent comparisons across product templates.
- Optionally set Badge metafield to a single-line text product metafield such as
custom.comparison_badge. Enter its namespace and key as plain text. Each product supplies its own badge, including after a customer swaps columns; empty values show no badge. Manual formula blocks keep their Highlight label. - Color scheme under Style defaults to Scheme 7 for newly added sections. Existing saved scheme selections remain in effect.
- Under Style, Content width defaults to Standard, which caps the comparison at 1200px, matching Proof ledger. Wide uses the theme page width. Both retain the full-width background and mobile swipeable cards.
- Pick an Image ratio and check it on a phone — the comparison becomes a swipeable deck, one product per slide.
Where the content comes from
Product references, images, and prices come from Shopify product data. Optional product metafields own per-product badges in product mode. The measures are section content, and in the fixed mode each product's answers are block content, because they are specific to this comparison rather than facts on the product record.
Notes and cautions
- Four columns is the maximum and three is usually better. A comparison a customer cannot hold in their head does not help them decide.
- On a product template, two columns beside the product being viewed is the practical desktop maximum — the row labels plus four product columns need about 1140px and scroll sideways below that.
- Rows still on Manual value are hidden once the columns come from the product, rather than showing an empty cell in every column. The editor names them.
- It is not an HTML table. Each column is its own card so it can carry its own shadow, and every value carries a hidden row label, so screen readers still hear "Best for: dry, sensitive" without a table to navigate.
Two ways to fill the columns
A comparison built from product pickers has one problem on a product template: the template is shared. Pick three serums in the blocks and every product page in your store shows those same three serums — including the pages of the serums themselves.
So the section reads its columns from one of three places, set by Column products under Comparison columns.
| Mode | What fills the columns | Where to use it |
|---|---|---|
| Product picked in each formula block (default) | The products you picked, the same on every page | Home page, a collection page, a dedicated comparison page |
| Product being viewed, plus the customer’s choice | The product on the page, then products the customer picks | Product templates |
| Products in this set (Set contents metafield) | The products listed in the set’s custom.set_contents metafield | The set product template |
The second mode does two things at once: it puts the product being viewed in the first column automatically, and it lets the customer choose what to compare it against from a dropdown on each of the other columns.
It needs a product on the page. On a home page there is nothing being viewed, so the section falls back to your formula blocks and the theme editor tells you so.
The full walkthrough
Step 1 — switch the source
On your product template, open the section and set Column products to Product being viewed, plus the customer’s choice.
The formula blocks stop being used at this point. They are not deleted — switching back restores them — but hiding or reordering them changes nothing while this mode is on, and the editor says as much.
Step 2 — choose what customers compare within
Collection customers compare within sets the pool the dropdowns offer.
Pick a shared collection containing the products customers should compare. Products are offered in that collection’s sort order, excluding the product being viewed.
When this setting is blank, the section chooses the smallest collection the current product belongs to that contains at least two products. It makes this choice separately on each product page, so two products with the same product type can use different comparison collections.
The collection is chosen first. Product type is filtered second. Compare only products of the same type checks Shopify’s Product type field within that collection only. It does not search the whole store, combine collections, or try another collection if no matching product remains. The filter is ignored when the current product has no product type. If no other matching product remains, the section is hidden from customers.
For example, Night Serum and Retinal Serum can both have product type Serum and belong to Daily Ritual. If Retinal Serum also belongs to a smaller collection that contains no other serums, its comparison is hidden even though Night Serum’s comparison includes it.
For consistent comparisons across product pages, select the same shared collection explicitly on their product templates, include all the intended products, and keep their Product type values identical. If products use different templates, check the section settings on each template.
Step 3 — give every row a source
This is the step that catches people out. A product the customer swaps in has no block to type a value into, so every row you want visible needs a Value source under Comparison rows.
Rows left on Manual value are hidden in this mode. They are not shown as empty — an empty comparison row is worse than no row — and the editor lists exactly which rows dropped and why.
See Per-product content for how value sources work and which attributes exist.
Custom rows without a matching value source
Manual value from each formula block works only with products picked manually in formula blocks. Enter the matching row value separately in each Formula block. This row is hidden when Column products is set to Product being viewed, plus the customer’s choice.
For a row such as When to use, choose Custom product metafield to read a different value from each product. This works with manually picked products and collection-based comparison, including products customers swap into a column.
Store a custom value in a product metafield
A custom product metafield lets you store reusable information when Shopify’s category attributes do not cover it. For When to use, set it up as follows:
- In Shopify admin, open Products, select a product, and find Metafields.
- Click Add definition. Alternatively, use Settings > Metafields and metaobjects > Products.
- Name the definition When to use and set its namespace and key to
custom.when_to_use. - Choose Single line text with One value. Add the description “Enter AM, PM, or AM, PM.” Save the definition.
- Open each product you want to compare, fill its When to use metafield, and save the product.
Use
AMfor morning,PMfor evening, orAM, PMfor both.
Connect the metafield to the comparison row
- In the theme editor, open Formula comparison, then the Comparison row you want to fill.
- Set Heading to When to use.
- Set Value source to Custom product metafield.
- In Metafield namespace and key, type
custom.when_to_useexactly. Enter the identifier as plain text; do not connect this setting to the page’s dynamic source. - Set Value style to Time of day, then save.
AMgets a sun icon,PMgets a moon icon, andAM, PMdisplays both badges. - For collection-based comparison, set Column products to Product being viewed, plus the customer’s choice and select Collection customers compare within. Check the product-type filter if you want only matching Shopify product types.
- Preview two products with different values, then swap a comparison product. Each card should show its own metafield value, including the first card for the product being viewed.
Creating a definition does not add its name as a separate dropdown option. Select Custom product metafield and enter its namespace and key instead. The section reads that identifier from each card’s product, so it does not reuse the current page’s value across all columns.
For another custom row, repeat these steps with its own definition, heading, identifier (for
example, custom.routine_step), and value style. Supported metafield types are single-line text,
multi-line text, integer, decimal, boolean, and lists of single-line text, integers, or decimals.
Lists become comma-separated values; use Tags to show individual items as chips. Rich text,
files, references, JSON, and other types are not supported by this source.
If a product’s field is missing, empty, or unsupported, manually picked formula blocks use their matching typed row value as a fallback. Collection-based columns show a dash; the product remains in the comparison. A blank namespace-and-key setting hides the row in collection mode. If you see dashes unexpectedly, check the identifier, metafield type, and saved values on each product.
Custom metafields are optional. You can still use category attributes or manually picked formula
blocks without creating any custom definitions. For a manual When to use row, enter AM, PM,
or AM, PM in each formula block’s matching row value and select Time of day.
Shopify’s custom metafield setup guide provides further details about definitions and validation.
Step 4 — size the comparison
| Setting | What it does |
|---|---|
| Columns to compare | How many columns sit beside the product being viewed. 1–3. |
| Products customers can choose from | How long each dropdown list is. 2–8. |
| Current product label | The wording on the first column’s chip. Blank hides it. |
Two columns is the practical maximum on a desktop. The row-label column plus the product being viewed plus three more needs about 1140px, so three columns is permanently scrolled sideways at normal page widths.
Compare the products in a set
On the set template, the section compares the products a kit contains rather than the kit against other products. Set Column products to Products in this set (Set contents metafield).
The columns come from the set product’s custom.set_contents metafield, a List of products
metafield. Evidence cards and Product routine read the same list, so you fill it once per set. The
first six products in the list show, in the order saved there. The set itself is not a column,
there are no dropdowns, and the formula blocks and collection are not used.
As with the product-viewed mode, every row needs a category attribute or a custom product metafield, because the included products have no block to type a value into. A row without a source is hidden, and the theme editor lists which ones. When the set has no products in its Set contents metafield, the section falls back to the products picked in the formula blocks, and the editor explains why.
Add product badges
In Product being viewed, plus the customer’s choice or Products in this set mode, use Badge metafield under Comparison columns to show a label such as “Most loved” above individual product cards.
- Create a product metafield definition with type Single line text, such as
custom.comparison_badge. - Fill it on the products that should have a badge. Leave other products’ values empty.
- Enter
custom.comparison_badgeas plain text in Badge metafield, without connecting a dynamic source.
Each card reads its own product’s value, including the current product and products selected through the dropdown. The badge and highlighted styling follow the selected product. Empty, missing, or malformed references show no badge. Leaving the setting blank disables product badges. The default is blank, so existing comparisons keep their appearance.
In manual formula-block mode, Highlight label still owns each card’s badge. On pages without an in-scope product, the section falls back to those manual blocks and their labels.
What the customer sees
The first column is the product they are already looking at, marked with the label from Current product label and given a quiet ring so it reads as theirs.
Every other column carries a dropdown naming the product in it. Opening it lists the pool, where:
- the column’s own product is ticked
- a product already shown in another column is greyed out with a dash, because two columns showing the same product is not a comparison
- choosing one swaps that column, and only that column
Nothing reloads. Every choice is rendered with the page and swapped in place, so the comparison changes instantly and no images are fetched until a choice is actually made.
What renders in each situation
| The situation | What a customer sees |
|---|---|
| The collection has plenty of products | The full comparison, with dropdowns |
| The collection has fewer products than Columns to compare | Fewer columns, and the editor says how many it found |
| The collection has nothing to compare against | Nothing — the section is hidden |
| The product being viewed has no collection | Falls back to the smallest collection it belongs to; hidden if there is none |
| The section sits where no product is being viewed | Your formula blocks, as normal |
| A set has no products in its Set contents metafield | Your formula blocks, as normal |
| A row has no value source | That row is hidden, in every column |
A product with nothing comparable hides the section rather than showing a one-column table. Every one of these states explains itself in the theme editor — if the section looks short or empty while editing, read the note under it.
How the choices are ordered
The dropdown offers the first products in the collection’s own sort order, skipping the product being viewed and anything filtered out by product type.
That means the collection’s sort order in Shopify admin is the ranking. There is no relevance scoring. If you want a particular product to be the default comparison, sort that collection manually and put it first.
Two things it deliberately does not do: it does not exclude sold-out products, because a comparison is still informative for something out of stock, and it does not narrow by tag or price.
Choose the content width
Under Style, set Content width to Standard or Wide.
- Standard is the default. It caps the header and comparison at 1200px, matching Proof ledger, so cards keep their proportions on large screens. A narrower theme page width still takes priority.
- Wide uses the theme page width for additional space across more columns.
The section background stays full width in both modes. On phones, the comparison keeps its swipeable card layout. Existing sections without a saved width use Standard.
Keeping the cards aligned
Rows only read as a comparison when they line up across the columns, so the section holds the media and the titles to a fixed shape:
- Image ratio — Portrait, Square, or Landscape — applies at every screen size, so every column’s image uses the same compact thumbnail shape. Thumbnails are capped at about 200px tall, with images cropped to fill the frame. On a phone the comparison becomes a swipeable deck one card at a time.
- Two lines are always reserved for a product title, so a short name and a long one do not offset the rows beneath them. Titles are never truncated. On mobile, the headers and corresponding rows match the tallest live card, so long names and wrapped values keep subsequent row headings aligned. Heights update after resizing, font loading, and product swaps. Desktop uses shared grid rows.
Using it well
- Two columns beside the product, not three. A comparison a customer cannot see at once does not help them decide.
- Point every row at an attribute before switching modes. Otherwise the comparison arrives three rows shorter than you designed it.
- Keep the choice list short. Every option is prepared with the page, so eight choices is more page weight than four for a list most customers never open.
- Set Product type on your products. It is what keeps a wax out of a serum comparison.
- Test on two products — one with row attributes filled in, and one without. Missing values show dashes in collection mode; they do not exclude a product. Also test a product with no other matching products in its collection: that is when the section hides itself.
When a column shows dashes
Work down this list:
- The product has no category. Value sources read category attributes, and those do not exist until the product has a category. This is the cause most of the time.
- The attribute is empty on that product. Assigning a category creates the field; it does not fill it in.
- The row is still on Manual value. In this mode that row is hidden rather than filled.
- The category does not carry that attribute. A cleanser category will not offer SPF level.
- You are looking at a product outside the collection. The comparison is built from the collection pool, and the product being viewed is always the first column regardless.
The fastest check is the product in Shopify admin. If the value is blank there, the theme has nothing to show.
Return to the current product
On a product page, the card for the product being viewed omits its View product link. Enable Show Swipe up button under Call to action to show a compact Swipe up button with an upward chevron instead. It scrolls to the nearest Product chapters or Product stage section above the comparison. Other comparison products keep their View product links when enabled.
The button has its own toggle, so it can remain enabled when Show the View product button is off. It stays hidden when neither product section exists above the comparison, or JavaScript is unavailable. Reduced motion and the theme’s No motion setting use immediate scrolling.
Align the mobile header
- Open Formula comparison in the theme editor.
- Under Content, set Header content alignment to Left or Center. Center places the whole header and its text in the center of the section.
- Preview at a phone width and save.
Mobile header alignment defaults to Use header content alignment, so the eyebrow, heading, and supporting text follow the main header setting on phones too. Select Left or Center there to override mobile independently. Existing saved mobile choices remain in effect. Both alignments use the shared page gutters. Product cards and row labels keep their own alignment.
Comparison artwork
Custom artwork uses Shopify-responsive image candidates. Bundled botanical art also supplies 160px, 320px and original-size candidates; no merchant asset is needed. Use a transparent .png or .svg for custom illustrations.
Section settings
Every setting on the section itself, in the order it appears in the theme editor. Group headings match the editor's own grouping.
Content
Use Header content alignment to follow the main header setting, or override it on screens below 750px.
Comparison columns
Applies in product mode. Leave blank to use each product's smallest collection with at least two products; comparisons can differ between pages. Select a shared collection for consistent comparisons. Products follow collection sort order, excluding the current product.
Marks the first column as the product the customer is viewing. Leave blank to hide it.
Optional. Enter a single-line text product metafield's full namespace and key, such as custom.comparison_badge. Each product supplies its own badge text. Leave blank to hide badges. Enter plain text, without a dynamic source.
Filters only within the selected or automatically chosen collection, using Shopify Product type. It does not search other collections. The section appears for customers only when another product matches. Products without a product type skip this filter.
Appears beside the product being viewed. Fewer columns show if the collection holds fewer products.
Sets the length of each column's list. The page prepares every choice, so a shorter list keeps the page lighter.
Comparison rows
Optional text shown at the top of the left column.
Extra tags collapse behind a control that customers can expand. Applies to rows using the tags style.
Call to action
On product pages, replaces the current product's View product link with a button that scrolls to Product chapters or Product stage above this section. Hidden when neither section is available. Other products keep their View product links.
Style
Standard limits the comparison to 1200px on wide screens, matching Proof ledger. Wide fills the theme page width. Both keep the section background full width.
Show a decorative line illustration at the top of the label column.
400 x 720px .png recommended. Use a transparent line illustration.
Applies on every screen size. Square keeps cards shortest on a phone.
Reveal the comparison as it scrolls into view. Respects the theme motion settings.
Padding
Blocks
Blocks are added, reordered, duplicated, and removed inside the section. Each type has its own settings.
Comparison row row max 6
Names the row in the label column. Rows appear once you add a heading.
Fills this row from each product automatically. The typed value appears when a product has no data for the attribute.
This row works only with products picked manually in formula blocks. Enter its value in each formula block. Choosing the current product plus the customer's choice for Column products hides this row.
Enter a product metafield identifier, such as custom.when_to_use. Each comparison product supplies its own value. Supports text, numbers, true/false, and lists of text or numbers. Missing or unsupported values use the formula block's typed value, or show a dash when no fallback is available.
Formula formula max 4
Title, image, link, and price are read from this product.
Feature this product with a short label, such as Most loved. Leave blank for none.
Appears after the price, such as / 30 ml.