---
title: "Product Sample developer reference"
url: "https://kestrelwp.com/docs/product-sample-developer-reference/"
description: "Filters, actions and the Sample object for customizing Product Sample in code."
published: "2026-10-06T20:28:22+00:00"
modified: "2026-10-06T20:28:22+00:00"
---

Product Sample stores each sample as a set of settings on the real product, and represents it in code with a `Sample` object that works much like `WC_Product`. Its filters and actions let you change when the sample button shows, what it says, how samples are priced and stocked, and what the product editor shows. Add these snippets in a code snippets plugin or your child theme’s `functions.php`. Customizations like these aren’t covered by support, so test them on a staging site first.

For what the plugin does without any code, see [Get started with Product Sample](/docs/get-started-with-product-sample/).

## When you’d use this

- Hide the sample button for some products, such as those on sale.
- Change the sample price with your own rule.
- Change the sample button’s text or attributes for a theme or plugin.
- Move the listing button to a different hook.
- Run your own code when sample stock changes.

## The sample object

The `Sample` class extends WooCommerce’s `WC_Data`, the same base class as `WC_Product`, and copies many of `WC_Product`‘s properties and methods. A sample isn’t a separate post: its data is saved as `wsa_sample_*` custom fields on the product or variation it belongs to. So the class doesn’t use a WooCommerce data store; it reads, saves and deletes those custom fields itself.

Create a sample from a product object, or from a product ID (passing the object saves a `wc_get_product()` call):

```
global $product;
echo $product->get_price();
// output: 10

$sample = new Barn2\Plugin\WC_Product_Sample\Sample( $product );
echo $sample->get_price();
// output: 1
```

The class keeps the `Barn2\Plugin\WC_Product_Sample` namespace it was built with.

Getters such as `get_price()`, `get_tax_class()` and `get_shipping_class_id()` return the sample’s value in the `view` context, falling back to the parent product, category and store-wide settings when the sample has none. In the `edit` context they return only the values saved on the product (for a variation, on the variation or its parent product), without the category and store-wide fallback.

When a sample shares the product’s stock, the stock checks defer to the product: `is_in_stock()`, `has_enough_stock()`, `backorders_allowed()`, `is_on_backorder()`, `backorders_require_notification()`, `has_weight()`, `has_dimensions()` and `get_availability()`. The plain getters, such as `get_stock()` and `get_weight()`, still return the sample’s own saved values.

### The product behind a sample

`get_product()` returns the product (or variation) the sample belongs to, so you can use any `WC_Product` method that the sample doesn’t copy. For a variation, `get_parent_product()` returns the variable product. Methods the `Sample` class doesn’t define are passed on to the product.

This snippet hides the sample button for products on sale:

```
add_filter( 'wsa_sample_should_add_button', function( $is_button_visible, $sample ) {
	$product = $sample->get_product();
	return $is_button_visible && ! $product->is_on_sale();
}, 10, 2 );
```

### Hooks that mirror WooCommerce

Many hooks match their `WC_Product` counterparts. For example, `wsa_sample_get_{$prop}` filters a sample property the way `woocommerce_product_get_{$prop}` filters a product property. This snippet adds 2 to the price of samples of physical products, so $5 becomes $7:

```
add_filter( 'wsa_sample_get_price', function( $price, $sample ) {
	if ( ! $sample->is_virtual() ) {
		$price += 2;
	}
	return $price;
}, 10, 2 );
```

## Filters

### wsa\_sample\_add\_to\_cart\_description

Filters the sample button’s description in product listings, used as its `aria-label`. Receives the description and the sample.

### wsa\_sample\_add\_to\_cart\_text

Filters the sample button text in product listings. Receives the text and the sample. For the button on product pages, use [wsa\_sample\_single\_add\_to\_cart\_text](#wsa-sample-single-add-to-cart-text).

```
add_filter( 'wsa_sample_add_to_cart_text', function( $button_text, $sample ) {
	if ( 0 == $sample->get_price() ) {
		$button_text = __( 'Get a free sample!', 'my-text-domain' );
	}
	return $button_text;
}, 10, 2 );
```

### wsa\_sample\_add\_to\_cart\_url

Filters the URL of the listing button, which adds the sample to the cart (or links to the product when the sample can’t be bought). Receives the URL and the sample.

### wsa\_sample\_backorders\_allowed

Filters whether the sample allows backorders, when it has its own stock. Receives the result, the product ID and the sample.

```
add_filter( 'wsa_sample_backorders_allowed', function( $backorders_allowed, $product_id, $sample ) {
	return $backorders_allowed;
}, 10, 3 );
```

### wsa\_sample\_backorders\_require\_notification

Filters whether backorders of a sample with its own stock notify the customer. Receives the result and the sample.

### wsa\_sample\_downloadable\_file\_permission

Filters the `WC_Customer_Download` object created for a sample file. Receives the download, the sample, the order, the quantity and the order item.

### wsa\_sample\_file

Filters the sample file for a download ID. Receives the file (or `false`), the sample and the download ID.

### wsa\_sample\_file\_download\_path

Filters the path of a sample file. Receives the path, the sample and the download ID.

### wsa\_sample\_get\_{$prop}

Filters a sample property in the `view` context. Replace `{$prop}` with one of `status`, `price`, `tax_status`, `tax_class`, `use_product_stock`, `stock_status`, `manage_stock`, `stock`, `backorders`, `low_stock_amount`, `weight`, `length`, `width`, `height`, `shipping_class_id`, `downloads`, `download_limit`, `download_expiry` or `image_id`. Receives the value and the sample.

### wsa\_sample\_get\_availability

Filters the sample’s availability array (`availability` and `class`). Receives the array and the sample.

### wsa\_sample\_get\_availability\_class

Filters the CSS class of the availability text for a sample with its own stock. Receives the class and the sample.

### wsa\_sample\_get\_availability\_text

Filters the availability text for a sample with its own stock. Receives the text and the sample.

### wsa\_sample\_get\_dimensions

Filters the sample’s formatted dimensions. Receives the dimensions and the sample.

### wsa\_sample\_get\_image

Filters the sample’s image markup. Receives the markup, the sample, the image size, the image attributes and whether a placeholder was allowed.

```
add_filter( 'wsa_sample_get_image', function( $image, $sample, $size, $attr, $placeholder ) {
	return $image;
}, 10, 5 );
```

### wsa\_sample\_get\_price\_html

Filters the sample’s price HTML. Receives the HTML and the sample.

### wsa\_sample\_get\_price\_suffix

Filters the price suffix shown after a taxable sample’s price. Receives the suffix markup, the sample, the price and the quantity.

### wsa\_sample\_is\_in\_stock

Filters whether a sample with its own stock is in stock. Receives the result and the sample.

### wsa\_sample\_is\_taxable

Filters whether the sample is taxable. Receives the result and the sample.

### wsa\_sample\_loop\_add\_to\_cart\_args

Filters the listing button’s arguments (`quantity`, `class` and `attributes`). Receives the arguments and the sample.

### wsa\_sample\_loop\_add\_to\_cart\_hook

Filters where the listing button is printed. Receives an array with `hook` (default `woocommerce_after_template_part`), `priority` (default 11) and `function` (`add_action` or `add_filter`). The plugin uses it to move the button for some themes.

### wsa\_sample\_maximum\_quantity\_description

Filters the description under **Maximum sample quantity** on the settings screen. Receives the description.

### wsa\_sample\_quantity\_setting\_attributes

Filters the HTML attributes of the **Maximum sample quantity** field. Receives the attributes array.

### wsa\_sample\_should\_add\_button

Filters whether the sample button shows. Receives the result and the sample. See the on-sale example under [the product behind a sample](#the-product-behind-a-sample).

### wsa\_sample\_single\_add\_to\_cart\_attributes

Filters the attributes of the sample button on product pages. Receives the attributes, the sample and the product.

### wsa\_sample\_single\_add\_to\_cart\_text

Filters the sample button text on product pages, after the `{price}` and `{currency}` placeholders are replaced. Receives the text and the sample. For listings, use [wsa\_sample\_add\_to\_cart\_text](#wsa-sample-add-to-cart-text).

### wsa\_sample\_supports

Filters whether the sample supports a WooCommerce product feature, such as `ajax_add_to_cart`. Receives the result, the feature name and the sample.

### wsa\_sample\_update\_sample\_stock\_query

Filters the SQL that updates a sample’s own stock after an order. Receives the SQL, the product ID, the new stock and the operation.

## Actions

### wsa\_sample\_before\_general\_sample\_data

Runs before the sample fields on a product’s **General** tab.

### wsa\_sample\_before\_inventory\_sample\_data and wsa\_sample\_after\_inventory\_sample\_data

Run before and after the sample fields on a product’s **Inventory** tab.

### wsa\_sample\_before\_shipping\_sample\_data and wsa\_sample\_after\_shipping\_sample\_data

Run before and after the sample fields on a product’s **Shipping** tab.

### wsa\_sample\_cat\_add\_after\_sample\_price

Runs after **Sample price** on the add category form. Receives the taxonomy.

### wsa\_sample\_cat\_edit\_after\_sample\_price

Runs after **Sample price** on the edit category form. Receives the term and the taxonomy.

### wsa\_sample\_before\_loop\_add\_to\_cart and wsa\_sample\_after\_loop\_add\_to\_cart

Run before and after the sample button in product listings.

### wsa\_sample\_read\_product\_data

Runs after a sample’s data is read. Receives the product ID.

### wsa\_sample\_delete\_product\_data

Runs after a sample’s data is deleted, such as when a product switches back to the global or category settings. Receives the product ID.

### wsa\_sample\_updated\_sample\_stock

Runs after a sample’s own stock is updated directly in the database. Receives the product ID.

## Keep learning

- [Get started with Product Sample](/docs/get-started-with-product-sample/) (settings, the follow-up email and what customers see)
- [Product Sample category, product and variation settings](/docs/product-sample-category-product-and-variation-settings/) (how settings are inherited, sample stock and files)
