Product
Display WooCommerce product data in your templates. Requires WooCommerce to be active.
The Product provider inherits all Post fields — title, link, excerpt, thumbnail, dates, author, custom fields, and everything else. Only product-specific fields are listed here.
In the WC admin UI, post fields are renamed: content is the product Description, excerpt is the product Short Description.
The Product provider only activates when WooCommerce is active. If WooCommerce is deactivated, product fields return empty values. Post fields (title, link, etc.) still work because products are a custom post type.
How It Works
When you loop over products with post_type: 'product', use any variable name — Unblock detects the post type from each WP_Post and exposes the matching product fields automatically:
{% for product in get_posts({post_type: 'product', posts_per_page: 6}) %}
{{ product.title }}
{{ product.price | currency }}
{% endfor %}
You still have access to every Post field — product.title, product.thumbnail, product.excerpt, product.link, etc.
All Fields
| Field | Arguments | Returns | Description |
|---|---|---|---|
sku | — | string | Product SKU |
product_type | — | string | simple, variable, grouped, or external |
category | — | Term | null | Primary product category (first product_cat term, comparable to a string) |
categories | — | Term[] | Product categories (product_cat taxonomy) |
tags | — | Term[] | Product tags (product_tag taxonomy) |
attributes | — | array | All product attributes (normalized: name, label, value, taxonomy, visible, variation) |
attribute | name | string | A single attribute formatted as a comma-separated string |
variations | limit | Product[] | Purchasable variations (variable products only) |
variation_attributes | — | array | Variation's attribute selection (variations only, {slug: value}) |
price | — | string | Effective price (sale price if on sale, regular otherwise) |
regular_price | — | string | Regular price |
sale_price | — | string | Sale price (empty if not on sale) |
is_on_sale | — | bool | Whether the product is currently on sale |
discount_percent | — | float | null | Discount percentage (null if not on sale) |
price_html | — | string | Full WooCommerce price HTML (includes <del> for sale) |
date_on_sale_from | format | string | null | Sale start date (null if not scheduled) |
date_on_sale_to | format | string | null | Sale end date (null if not scheduled) |
stock_quantity | — | int | null | Stock quantity (null if not tracked) |
stock_status | — | string | instock, outofstock, or onbackorder |
is_in_stock | — | bool | Whether the product is in stock |
is_on_backorder | — | bool | Whether currently on backorder |
is_virtual | — | bool | Whether virtual (no shipping) |
is_downloadable | — | bool | Whether downloadable |
is_featured | — | bool | Whether marked as featured |
is_purchasable | — | bool | Whether the product can be added to the cart |
min_purchase_quantity | — | int | Minimum purchase quantity |
max_purchase_quantity | — | int | Maximum purchase quantity (-1 if unlimited) |
weight | — | string | Product weight |
length | — | string | Product length |
width | — | string | Product width |
height | — | string | Product height |
dimensions | — | string | Formatted dimensions (L × W × H unit) |
shipping_class | — | string | Shipping class slug |
product_gallery | limit | Image[] | Gallery images (each is a full Image object) |
upsells | limit | Product[] | Upsell products (each is a full Product) |
cross_sells | limit | Product[] | Cross-sell products (each is a full Product) |
related | limit, exclude | Product[] | Related products auto-computed by WooCommerce. Default limit 5. Accepts positional args or a config object ({limit, exclude}). |
total_sales | — | int | Total units sold |
average_rating | — | string | Average rating (0–5, '0' by default) |
review_count | — | int | Number of reviews |
add_to_cart_url | — | string | Add to cart URL |
add_to_cart_text | — | string | Add to cart button text |
The currency filter
Formats a number as WooCommerce currency using wc_price(). Uses your store's configured currency symbol, thousand separator, and decimal settings.
{{ product.price | currency }} <!-- $29.99 -->
{{ product.regular_price | currency }} <!-- $39.99 -->
Without currency, you get the raw number. With it, you get the formatted output matching your WooCommerce settings.
Common Patterns
Sale badge
{% if product.is_on_sale %}
<s>{{ product.regular_price | currency }}</s> -{{ product.discount_percent }}%
{% endif %}
{{ product.price | currency }}
Stock status
{% if product.is_in_stock %}In stock{% endif %}
{% if not product.is_in_stock %}Out of stock{% endif %}
Product gallery
{% for image in product.product_gallery %}
{{ image.src('thumbnail') }}
{{ image.alt }}
{% endfor %}
Upsells section
{% for upsell in product.upsells(4) %}
{{ upsell.thumbnail.src('medium') }}
{{ upsell.title }}
{{ upsell.price | currency }}
{% endfor %}
Don't forget the currency filter when displaying prices. Without it, product.price returns a raw number like 29.99 — no currency symbol, no formatting. Always use {{ product.price | currency }} to match your WooCommerce store settings.
Next Steps
- Post provider — All inherited fields available on products
- Image provider — Working with gallery images and thumbnails
- Loop — Query and loop over products with
get_posts