> For the complete documentation index, see [llms.txt](https://help.dollarlabs.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.dollarlabs.io/dollarlabs-b2b-custom-pricing/show-final-prices-on/collection-page.md).

# Collection page

Correct prices on collection pages, search results and anywhere products render as cards — automatically on most themes, with a snippet for the rest.

Product cards are drawn by your theme, so they show Shopify's catalog price by default. The **Collection Pricing** app embed fixes that on collection pages, search results, featured-product sections and any other card surface.

## Step 1: enable the app embed

1. **Online Store → Themes → Customize**.
2. Open **App embeds** in the sidebar.
3. Enable **Collection Pricing**.
4. **Save**.

{% hint style="danger" %}
Nothing on this page works until the embed is on. If you follow the snippet route below without enabling it, you will remove your theme's price and get nothing in its place.
{% endhint %}

## Step 2: pick an approach

There are two, and most stores need only the first.

### Automatic — most themes

The embed's **Rewrite standard theme cards** setting is **on by default**. It finds product cards in your theme, locates the price element, and replaces it with the buyer's price.

For most themes that is all you need. Enable the embed, load a collection page as a tagged customer, and check the prices.

<table><thead><tr><th width="290">Setting</th><th>What it does</th><th width="120">Default</th></tr></thead><tbody><tr><td><strong>Rewrite standard theme cards</strong></td><td>Show B2B prices on collection and search cards for themes without an explicit price hook.</td><td>on</td></tr></tbody></table>

Because it works by inspecting your theme's markup, it is best-effort. Heavily customised themes, unusual card layouts or price markup that does not look like a price can defeat it. If some cards update and others do not, use the snippet.

### Explicit — the snippet hook

The reliable route: tell us exactly where the price goes, instead of letting us find it.

#### 1. Create the snippet

Create `snippets/dollarlabs-collection-price.liquid` in your theme and paste this in:

{% code title="snippets/dollarlabs-collection-price.liquid" %}

```liquid
{%- comment -%}
  Dollarlabs Price Display
  Renders an empty container; the app embed fills in the price.
{%- endcomment -%}

{%- liquid
  assign current_variant = product.selected_or_first_available_variant
  assign original_price = current_variant.price
  assign variant_id = current_variant.id
  assign show_original_price = show_original_price | default: false
  assign show_compare_at_price_for_non_discounted = show_compare_at_price_for_non_discounted | default: false
-%}

<div
  class="dollarlabs_pricelist--product_price"
  id="dollarlabs_pricelist--product_price-{{ section.id }}-{{ variant_id }}"
  data-variant-id="{{ variant_id }}"
  data-original-price="{{ original_price }}"
  data-show-original-price="{{ show_original_price }}"
  data-show-compare-at-price="{{ show_compare_at_price_for_non_discounted }}"
  data-compare-at-price="{{ current_variant.compare_at_price | default: 0 }}"
  data-show-currency-code="false"
  data-currency-code-position="left"
  data-custom-price-js
>
  {%- comment -%}Content will be populated by JavaScript{%- endcomment -%}
  <span class="dollarlabs_pricelist--loading"></span>
</div>
```

{% endcode %}

#### 2. Render it instead of your theme's price

Find where your theme draws a card price — usually `price.liquid`, `product-card.liquid`, `card-product.liquid` or similar — and **replace** that price markup with:

```liquid
{% render 'dollarlabs-collection-price', product: product %}
```

{% hint style="warning" %}
Replace, don't add. Leaving the theme's own price in place is what produces two prices or a flicker.
{% endhint %}

#### What the attributes do

The container is empty on purpose — the app embed finds it and fills it in. `data-custom-price-js` is what marks it as ours; the rest configure the display:

| Attribute                     | Purpose                                                                 |
| ----------------------------- | ----------------------------------------------------------------------- |
| `data-custom-price-js`        | Marks the container as ours to fill. **Required.**                      |
| `data-variant-id`             | The variant to price.                                                   |
| `data-original-price`         | The catalog price, in cents.                                            |
| `data-compare-at-price`       | The compare-at price, in cents.                                         |
| `data-show-original-price`    | `true` / `false` — strike through the original when discounted.         |
| `data-show-compare-at-price`  | `true` / `false` — strike through compare-at when there is no discount. |
| `data-show-currency-code`     | `true` / `false`.                                                       |
| `data-currency-code-position` | `left` or `right`.                                                      |

The snippet above ships with currency code **off** and position **left**. Change those two lines directly if you sell internationally.

You can also pass the display options in per render, which is useful when collection cards and search results should behave differently:

```liquid
{% render 'dollarlabs-collection-price', product: product, show_original_price: true %}
```

The embed only fills containers it has not already handled, so an explicit hook takes precedence over the automatic rewrite. You can use the snippet on templates that need it and leave the rest to the automatic path.

## Step 3: test

As a tagged customer, check:

* a collection page
* search results
* featured products or product carousels on the homepage
* related products on a product page

These often use different partials, so one can be right while another is wrong.

Then check as an untagged customer: retail prices everywhere, no flicker, no doubled prices.

## Common problems

**Prices don't change anywhere.**\
The app embed is off, or the price list is disabled.

**Some cards update, others don't.**\
The automatic rewrite could not find the price in those layouts. Add the snippet to the partial that draws them.

**Two prices show, or the price flickers.**\
Your theme's price is still rendering alongside ours. If you added the snippet, make sure you *replaced* the theme's price output rather than adding to it. Coming from another pricing app, check for [leftover theme code](/dollarlabs-b2b-custom-pricing/migrating-from-bold-custom-pricing.md#removing-bolds-theme-code).

**Prices are right on collections but wrong on the product page.**\
That is a different block — see [Product page](/dollarlabs-b2b-custom-pricing/show-final-prices-on/product-page.md).

## Why it works this way

Pricing is calculated by the app and rendered in the browser, so:

* your theme does not need updating when pricing logic changes
* prices stay correct through theme upgrades
* the same resolution runs on collection cards, product pages and checkout, so they agree
