Liquid drops reference — catalog
On this page
This article covers the Liquid drops for StoreConnect’s catalog domain: products, pricing, categories, brands, variants, and traits.
- For global/store drops, see Liquid drops — global context.
- For cart, order, and checkout drops, see Liquid drops — cart and order.
- For content, account, and location drops, see Liquid drops — content and accounts.
ProductDrop
The primary product object. Available as current_product on product detail pages, and as individual items in all_products or category product collections.
| Property | Type | Description |
|---|---|---|
id |
String | Product ID |
name |
String | Product name |
identifier |
String | Product identifier (alias for slug) |
slug |
String | URL slug |
path |
String | URL path |
url |
String | Full URL |
product_code |
String | Product/SKU code |
upc |
String | Universal Product Code (used as GTIN in structured data) |
condition |
String | Product condition: "new" or "used" |
summary_content |
String | Short summary HTML |
search_description |
String | Description used in search results and merchant feeds |
meta_title |
String | SEO title |
meta_description |
String | SEO description |
meta_keywords |
String | SEO keywords |
social_image |
ImageDrop | Social media sharing image |
pricing |
ProductPricingDrop | Pricing information |
can_purchase? |
Boolean | Can be purchased (accounts for stock, restrictions, availability) |
can_add_to_cart? |
Boolean | Can be added to cart |
out_of_stock? |
Boolean | Is out of stock |
out_of_stock_text |
String | Out of stock message |
unavailable_text |
String | Unavailable message |
discontinued? |
Boolean | Is discontinued |
track_inventory? |
Boolean | Tracks stock levels |
total_available_to_sell |
Number | Available quantity |
restricted? |
Boolean | Requires approval to purchase |
restricted_text |
String | Restriction message |
is_bundle? |
Boolean | Is a bundle product |
bundle_lead? |
Boolean | Is a CPQ bundle lead |
available_only_in_bundle? |
Boolean | Only purchasable in a bundle |
image |
ImageDrop | Primary image |
images |
Collection | All images |
media |
Collection | All media (images and videos) |
videos |
Collection | Product videos |
brand |
BrandDrop | Product brand |
categories |
Collection | Product categories |
tags |
Collection | Tags |
variants |
Paginated | Variant products (for master products) |
variant_types |
Collection | Variant type definitions |
variant_options |
Collection | Variant options |
variant_choices |
Collection | Variant choices |
variant_images |
Collection | Variant-specific images |
variant? |
Boolean | Is a variant (not a master) |
master? |
Boolean | Is a master product |
master |
ProductDrop | Master product (for variants) |
traits |
Collection | Product traits |
trait_groups |
Collection | Trait groups |
related_products |
Collection | Related products |
contained_in_bundles |
Collection | Bundles that contain this product |
custom_forms |
Collection | Associated custom forms |
documents |
Collection | Downloadable documents |
features_content |
String | Features HTML |
features_label |
String | Features section label |
specifications_content |
String | Specifications HTML |
specifications_label |
String | Specifications section label |
support_content |
String | Support HTML |
support_label |
String | Support section label |
warranty_content |
String | Warranty HTML |
warranty_label |
String | Warranty section label |
downloads_content |
String | Downloads HTML |
downloads_label |
String | Downloads section label |
add_to_cart_text |
String | Add to cart button text |
buy_it_now_text |
String | Buy it now button text |
maximum_quantity |
Number | Maximum quantity per order |
subscription? |
Boolean | Is a subscription product |
bookable? |
Boolean | Is bookable |
can_ship? |
Boolean | Can be shipped |
can_pickup? |
Boolean | Available for click & collect |
pricebook_entry |
PricebookEntryDrop | Pricebook entry for this product |
location_groups |
Collection | Location groups |
data |
Hash | Custom data fields |
ProductPricingDrop
Detailed pricing information. Accessed via product.pricing.
| Property | Type | Description |
|---|---|---|
price |
Number | Current price (sale price if on sale, otherwise original) |
original_price |
Number | Original (non-sale) price |
sale_price |
Number | Current sale price |
price_excl_tax |
Number | Price excluding tax (only when tax-exclusive pricing is active) |
sale_price_excl_tax |
Number | Sale price excluding tax |
price_range |
List | [min, max] price range for master products with variants |
checkout_price |
Number | Amount required at checkout |
has_price? |
Boolean | Has a price set |
hide_price? |
Boolean | Price should be hidden |
hide_price_text |
String | Text to display when price is hidden |
on_sale? |
Boolean | Currently on sale |
has_sale_price? |
Boolean | Has a sale price |
tax_inclusive? |
Boolean | Price includes tax |
points |
Number | Current points price |
original_points |
Number | Original (non-sale) points price |
has_sale_points? |
Boolean | Has a points sale price |
subscription? |
Boolean | Is a subscription price |
```liquid
{% if product.pricing.on_sale? %} {{ product.pricing.original_price | money }} {{ product.pricing.price | money }} {% else %} {{ product.pricing.price | money }} {% endif %} ```
ProductCategoryDrop
A product category. Available as current_product_category on category pages.
| Property | Type | Description |
|---|---|---|
id |
String | Category ID |
name |
String | Category name |
title |
String | Category title |
subtitle |
String | Category subtitle |
identifier |
String | Identifier |
path |
String | URL path |
url |
String | Full URL |
position |
Number | Position in category list |
image |
ImageDrop | Category image |
social_image |
ImageDrop | Social media sharing image |
meta_title |
String | SEO title |
meta_description |
String | SEO description |
meta_keywords |
String | SEO keywords |
google_product_category |
String | Google product category taxonomy ID |
introduction_content |
String | Introduction HTML |
information_content |
String | Information HTML |
products |
Paginated | Products in this category |
children |
Collection | Child categories |
navigation_children |
Collection | Child categories visible in navigation |
ancestors |
Collection | Ancestor categories (full parent chain) |
hidden? |
Boolean | Hidden from navigation |
data |
Hash | Custom data fields |
BrandDrop
A product brand.
| Property | Type | Description |
|---|---|---|
name |
String | Brand name |
path |
String | URL path |
Variant drops
StoreConnect uses an n-ary variant system — products can have any number of variant types (Color, Size, Material, etc.).
VariantTypeDrop
A variant dimension (e.g., “Color”, “Size”).
| Property | Type | Description |
|---|---|---|
name |
String | Type name (e.g., "Color") |
position |
Number | Sort order |
options |
Collection | Available options for this type |
VariantOptionDrop
A specific value for a variant type (e.g., “Red”, “Large”).
| Property | Type | Description |
|---|---|---|
name |
String | Option name (e.g., "Red") |
variant_type |
VariantTypeDrop | Parent variant type |
position |
Number | Sort order |
VariantChoiceDrop
Links a variant option to a specific product variant.
| Property | Type | Description |
|---|---|---|
variant_option |
VariantOptionDrop | The selected option |
product |
ProductDrop | The variant product |
Rendering a variant selector:
```liquid
{% for type in current_product.variant_types %}
{% endfor %} ```
Trait drops
TraitDrop
A product attribute/characteristic.
| Property | Type | Description |
|---|---|---|
name |
String | Trait name |
value |
String | Trait value |
trait_type |
TraitTypeDrop | Trait type definition |
TraitTypeDrop
A trait type definition.
| Property | Type | Description |
|---|---|---|
name |
String | Type name |
trait_group |
TraitGroupDrop | Parent group |
TraitGroupDrop
A group of related traits.
| Property | Type | Description |
|---|---|---|
name |
String | Group name |
trait_types |
Collection | Trait types in this group |
TraitCategoryDrop
A category organizing trait groups.
| Property | Type | Description |
|---|---|---|
name |
String | Category name |
trait_groups |
Collection | Groups in this category |
Rendering traits:
```liquid
{% for group in product.trait_groups %}
{{ group.name }}
-
{% for trait in product.traits %}
{% if trait.trait_type.trait_group.name == group.name %}
- {{ trait.name }}
- {{ trait.value }} {% endif %} {% endfor %}
{% endfor %} ```
Or use the built-in filter for the default rendering:
```liquid
{{ current_product | show_traits }} ```
Common patterns
Accessing products
```liquid
{{ current_product.name }}
{% for product in all_products %} {{ product.name }} {% endfor %}
{{ all_products.my-product-slug.name }}
{% for product in current_product_category.products %} {{ product.name }} {% endfor %} ```
Product card
A minimal product card covering image, brand, name, pricing, and availability:
```liquid
{{ product.name }}
{% unless product.pricing.hide_price? %} {% if product.pricing.on_sale? %} {{ product.pricing.original_price | money }} {{ product.pricing.price | money }} {% else %} {{ product.pricing.price | money }} {% endif %} {% else %} {{ product.pricing.hide_price_text }} {% endunless %} {% if product.out_of_stock? %} {{ product.out_of_stock_text | default: "Out of stock" }} {% endif %}```
Image gallery
```liquid
{% if product.images.size > 0 %}
{% endif %} ```
Add to cart
```liquid
{% if product.can_add_to_cart? %} {% form “add-to-cart”, product: product %} {% if product.variant_types.size > 0 %} {% render “products/variant_selector”, product: product %} {% endif %}
<input type="number"
name="{{ form.fields["quantity"].name }}"
value="1"
min="1"
{% if product.maximum_quantity > 0 %}max="{{ product.maximum_quantity }}"{% endif %}>
<button type="submit">{{ product.add_to_cart_text | default: "Add to cart" }}</button> {% endform %} {% elsif product.out_of_stock? %}
{{ product.out_of_stock_text }}
{% elsif product.restricted? %}
{{ product.restricted_text }}
{% endif %} ```
Variant selector
StoreConnect uses an n-ary variant system — products can have any number of variant types (Color, Size, Material, etc.), with each type having its own options.
Product (master)
├── VariantType: "Color" → VariantOptions: Red, Blue, Green
├── VariantType: "Size" → VariantOptions: Small, Medium, Large
└── Variants (ProductDrops)
├── "Red / Small" ← VariantChoices link options to this variant
├── "Red / Medium"
└── ...
```liquid
{% if product.variant_types.size > 0 %}
{% endif %} ```
Variant resolution in JavaScript
Each variant is its own Product with its own page, and the add-to-cart form posts to whichever product it was given. There is no variant field on the form. Selecting options therefore navigates to the matching variant’s path, and the form on that page is already bound to it.
The standard pattern uses JavaScript to:
- Capture the customer’s selections, one choice per variant type.
- Find the entry whose choices match every selection.
- Navigate to that variant’s
path, which re-renders the price, availability, and add-to-cart form for the variant.
To expose variant data to JavaScript, serialize product.variant_options in a <script> tag. Each entry pairs a variant’s path with the form_value of its choice for each type:
```liquid
```
Theme variables for variant selectors
| Key | Default | Description |
|---|---|---|
product.variants.selector.buttons.maximum |
5 |
Max options shown as buttons before switching to a dropdown |
Trait rendering
Quick rendering using the built-in filter:
```liquid
{{ product | show_traits }} ```
Custom rendering grouped by category and group:
```liquid
{% if product.trait_category %} {% for group in product.trait_category.trait_groups %} <section> <h4>{{ group.name }}</h4> <dl> {% for type in group.trait_types %} {% for trait in product.traits %} {% if trait.trait_type.name == type.name %} <dt>{{ trait.name }}</dt> <dd>{{ trait.value }}</dd> {% endif %} {% endfor %} {% endfor %} </dl> </section> {% endfor %} {% endif %} ```
Related products
```liquid
{% if product.related_products.size > 0 %}
{% endif %} ```
Product content sections
Rich content sections (features, specifications, support, warranty, downloads) are accessible as rendered HTML:
```liquid
{% if product.features_content %}
{{ product.features_label | default: "Features" }}
{{ product.features_content }}{% endif %}
{% if product.specifications_content %}
{{ product.specifications_label | default: "Specifications" }}
{{ product.specifications_content }}{% endif %} ```
Or use the typed content block filters:
```liquid
{{ product | features_content_blocks }} {{ product | specifications_content_blocks }} {{ product | downloads_content_blocks }} ```
Bundle products
```liquid
{% if product.is_bundle? %}
This product is a bundle
{% endif %}
{% if product.available_only_in_bundle? %}
Available only as part of a bundle
{% for bundle in product.contained_in_bundles %} {{ bundle.name }} {% endfor %} {% endif %} ```
Was this article helpful?
Thanks for your feedback! It helps us improve our docs.