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

  1. Add the section and write the heading and intro under Content.
  2. Define your measures under Comparison rows. These become the rows and apply to every column, so pick measures every product can actually answer.
  3. 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.
  4. 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.
  5. For a fixed comparison, add one Formula block per product, up to four — each picks a product and answers each row.
  6. 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.
  7. 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.
  8. 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.
  9. Color scheme under Style defaults to Scheme 7 for newly added sections. Existing saved scheme selections remain in effect.
  10. 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.
  11. 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.

ModeWhat fills the columnsWhere to use it
Product picked in each formula block (default)The products you picked, the same on every pageHome page, a collection page, a dedicated comparison page
Product being viewed, plus the customer’s choiceThe product on the page, then products the customer picksProduct templates
Products in this set (Set contents metafield)The products listed in the set’s custom.set_contents metafieldThe 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:

  1. In Shopify admin, open Products, select a product, and find Metafields.
  2. Click Add definition. Alternatively, use Settings > Metafields and metaobjects > Products.
  3. Name the definition When to use and set its namespace and key to custom.when_to_use.
  4. Choose Single line text with One value. Add the description “Enter AM, PM, or AM, PM.” Save the definition.
  5. Open each product you want to compare, fill its When to use metafield, and save the product. Use AM for morning, PM for evening, or AM, PM for both.

Connect the metafield to the comparison row

  1. In the theme editor, open Formula comparison, then the Comparison row you want to fill.
  2. Set Heading to When to use.
  3. Set Value source to Custom product metafield.
  4. In Metafield namespace and key, type custom.when_to_use exactly. Enter the identifier as plain text; do not connect this setting to the page’s dynamic source.
  5. Set Value style to Time of day, then save. AM gets a sun icon, PM gets a moon icon, and AM, PM displays both badges.
  6. 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.
  7. 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

SettingWhat it does
Columns to compareHow many columns sit beside the product being viewed. 1–3.
Products customers can choose fromHow long each dropdown list is. 2–8.
Current product labelThe 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.

  1. Create a product metafield definition with type Single line text, such as custom.comparison_badge.
  2. Fill it on the products that should have a badge. Leave other products’ values empty.
  3. Enter custom.comparison_badge as 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 situationWhat a customer sees
The collection has plenty of productsThe full comparison, with dropdowns
The collection has fewer products than Columns to compareFewer columns, and the editor says how many it found
The collection has nothing to compare againstNothing — the section is hidden
The product being viewed has no collectionFalls back to the smallest collection it belongs to; hidden if there is none
The section sits where no product is being viewedYour formula blocks, as normal
A set has no products in its Set contents metafieldYour formula blocks, as normal
A row has no value sourceThat 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:

  1. 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.
  2. The attribute is empty on that product. Assigning a category creates the field; it does not fill it in.
  3. The row is still on Manual value. In this mode that row is hidden rather than filled.
  4. The category does not carry that attribute. A cleanser category will not offer SPF level.
  5. 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

  1. Open Formula comparison in the theme editor.
  2. Under Content, set Header content alignment to Left or Center. Center places the whole header and its text in the center of the section.
  3. 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.

Formula comparison design

100%

Use the zoom controls, then scroll to inspect the image. Press Escape to close.

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

EyebrowText
ID
eyebrow
Default
Formula comparison
HeadingText
ID
heading
Default
Compare the formulas
Heading sizeDropdown
ID
heading_size
Default
Large
  • Smallsmall
  • Mediummedium
  • Largelarge
SubheadingRich text
ID
subheading
Default
<p>Read two to four products across the same rows, so the right choice is easy to see.</p>
Header content alignmentDropdown
ID
content_alignment
Default
Left
  • Leftleft
  • Centercenter
Mobile header alignmentDropdown

Use Header content alignment to follow the main header setting, or override it on screens below 750px.

ID
mobile_header_alignment
Default
Use header content alignment
  • Use header content alignmentheader
  • Leftleft
  • Centercenter

Comparison columns

Column productsDropdown
ID
columns_source
Default
Product picked in each formula block (same on every page)
  • Product picked in each formula block (same on every page)blocks
  • Product being viewed, plus the customer's choiceproduct
  • Products in this set (Set contents metafield)set_contents
Collection customers compare withinCollection

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.

ID
comparison_collection
Current product labelText

Marks the first column as the product the customer is viewing. Leave blank to hide it.

ID
anchor_label
Default
You are viewing
Shown when
columns_source is 'product'
Badge metafieldText

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.

ID
badge_metafield
Shown when
columns_source is 'product'
Compare only products of the same typeCheckbox

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.

ID
match_product_type
Default
On
Shown when
columns_source is not 'blocks'
Columns to compareSlider

Appears beside the product being viewed. Fewer columns show if the collection holds fewer products.

ID
comparison_columns
Default
2
Range
1 to 3, in steps of 1
Shown when
columns_source is 'product'
Products customers can choose fromSlider

Sets the length of each column's list. The page prepares every choice, so a shorter list keeps the page lighter.

ID
pool_limit
Default
6
Range
2 to 8, in steps of 1
Shown when
columns_source is 'product'

Comparison rows

Label column titleText

Optional text shown at the top of the left column.

ID
label_column_title
Tags shown per cellSlider

Extra tags collapse behind a control that customers can expand. Applies to rows using the tags style.

ID
tag_limit
Default
3
Range
2 to 6, in steps of 1
Price row labelText
ID
price_label
Default
Price

Call to action

Show the View product buttonCheckbox
ID
show_view_product
Default
On
View product button labelText
ID
view_product_label
Default
View product
Shown when
show_view_product
Show Swipe up buttonCheckbox

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.

ID
show_current_product_scroll
Default
On

Style

Content widthDropdown

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.

ID
content_width
Default
Standard
  • Standardstandard
  • Widewide
Color schemeColor scheme
ID
color_scheme
Default
scheme-6
Label column widthSlider
ID
label_column_width
Default
200
Range
140px to 280px, in steps of 4px
Label illustrationDropdown

Show a decorative line illustration at the top of the label column.

ID
label_illustration
Default
Leaf
  • Nonenone
  • Botanical branchbotanical
  • Leafleaf
  • Mushroommushroom
  • Dropletsdroplets
  • Sunsun
  • Customcustom
Custom illustrationImage

400 x 720px .png recommended. Use a transparent line illustration.

ID
label_illustration_image
Shown when
label_illustration is 'custom'
Illustration rotationSlider
ID
label_illustration_rotation
Default
0
Range
-30° to 30°, in steps of 1°
Shown when
label_illustration is not 'none'
Illustration horizontal shiftSlider
ID
label_illustration_shift_x
Default
0
Range
-40% to 40%, in steps of 2%
Shown when
label_illustration is not 'none'
Illustration vertical shiftSlider
ID
label_illustration_shift
Default
0
Range
-40% to 40%, in steps of 2%
Shown when
label_illustration is not 'none'
Image ratioDropdown

Applies on every screen size. Square keeps cards shortest on a phone.

ID
image_ratio
Default
Portrait
  • Portraitportrait
  • Squaresquare
  • Landscapelandscape
Space between cardsSlider
ID
column_gap
Default
20
Range
8px to 40px, in steps of 2px
Use custom corner radiusCheckbox
ID
use_custom_corner_radius
Default
Off
Corner radiusSlider
ID
corner_radius
Default
16
Range
0px to 32px, in steps of 2px
Shown when
use_custom_corner_radius
Animate on scrollCheckbox

Reveal the comparison as it scrolls into view. Respects the theme motion settings.

ID
enable_entrance_animation
Default
On

Padding

Top paddingSlider
ID
padding_top
Default
64
Range
0px to 120px, in steps of 4px
Bottom paddingSlider
ID
padding_bottom
Default
64
Range
0px to 120px, in steps of 4px

Blocks

Blocks are added, reordered, duplicated, and removed inside the section. Each type has its own settings.

Comparison row row max 6

HeadingText

Names the row in the label column. Rows appear once you add a heading.

ID
heading
Default
Benefit
Value sourceDropdown

Fills this row from each product automatically. The typed value appears when a product has no data for the attribute.

ID
attribute
Default
Skin care effect
  • Manual value from each formula blockmanual
  • Custom product metafieldcustom_metafield
  • Skin typesuitable-for-skin-type
  • Skin care effectskin-care-effect
  • Skin care featuresskin-care-features
  • Active ingredientsactive-ingredient
  • Constitutive ingredientsconstitutive-ingredients
  • Cosmetic functioncosmetic-function
  • Ingredient originingredient-origin
  • Product formproduct-form
  • Moisturizer typemoisturizer-type
  • Texturetexture
  • pH levelph-level
  • Fragrance levelfragrance-level
  • SPF levelspf-level
  • UVA protection gradeuva-protection-grade
  • Certifications and standardsproduct-certifications-standards

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.

Metafield namespace and keyText

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.

ID
custom_metafield
Shown when
attribute is 'custom_metafield'
Value styleDropdown
ID
style
Default
Text
  • Texttext
  • Tagstags
  • Time of dayschedule
  • Strength meterstrength

Formula formula max 4

ProductProduct

Title, image, link, and price are read from this product.

ID
product
Highlight labelText

Feature this product with a short label, such as Most loved. Leave blank for none.

ID
highlight_label
Price noteText

Appears after the price, such as / 30 ml.

ID
price_note

Row values

Row 1 valueText
ID
value_1
Default
Brightening and even tone
Row 2 valueText
ID
value_2
Default
Normal, Combination
Row 3 valueText
ID
value_3
Default
Serum
Row 4 valueText
ID
value_4
Default
AM
Row 5 valueText
ID
value_5
Default
30 ml
Row 6 valueText
ID
value_6
Default
3/5 Gentle