Developer Usage

Reserved Stock Pro for WooCommerce is highly customizable with many developer hooks available.

We’ve listed the most commonly requested changes using example snippets within this documentation. Keep in mind that these are examples only. You’ll likely need to customize the snippets further to fit your use-case

Are you unsure how to add code snippets in WordPress & WooCommerce?
🔌 See our post customize WooCommerce with snippets.

Function: Get reservation amounts

We recommend you use the rsp_get_stock_amounts function to get the stock amounts for any product ID.

The function will provide you with the amount of available, reserved, and stock in inventory for a specific WooCommerce Product.

Here’s an example use where each number is stored within the returning array.

// Make sure we have our function.
if ( function_exists( 'rsp_get_stock_amounts' ) ) {
	$stock_amounts = rsp_get_stock_amounts( 100 ); // Product ID.

	$stock_amounts['available']; // Integer: Available for reservations.
	$stock_amounts['reserved']; // Integer: Amount reserved.
	$stock_amounts['inventory']; // Integer: Inventory in stock.
	$stock_amounts['status']; // String: out_of_stock or fully_reserved or partially_reserved or none_reserved
}Code language: PHP (php)

Shortcode: Stock Amounts & Status

We’ve made a shortcode that will allow you to display a dynamic message based on the product’s reserved stock levels. You can place this anywhere, even on custom landing pages.

Make sure to set the following in the shortcode

  • product_id (optional if used in a query loop)
  • out_of_stock_text
  • fully_reserved_text
  • available_text
[rsp_product_stock_status product_id="2362" out_of_stock_text="Currently out of stock" fully_reserved_text="All stock reserved - Check back in a few minutes" available_text="{available_quantity} is available"]Code language: JSON / JSON with Comments (json)

Filter: Change which products should be reservable.

By default the Reserved Stock Pro plugin will apply reservation control to products which are “stock managed” within WooCommerce. If you have specific product which you wan’t to opt-out of reservations, and use default WooCommerce stock behavior. Then you can use the filter reserved_stock_pro_should_handle_product_stock

Opt-out of specific products or categories

Here’s a an example of excluding specific products by their ID’s or categories.

/**
 * Skip specific products from stock resveration. $product is the entire product object.
 */
function puri_reserved_stock_pro_should_handle_product_stock( $should_handle, $product ) {

	// Check if the product ID equals 100.
    if ( $product->get_id() === 100 ) {
		$should_handle = false; // Don't reserve stock for product 100.
	}

	// Check if product belongs to a category.
    if ( has_term( 'shirts', 'product_cat', $product->get_id() ) {
		$should_handle = false; // Don't reserve for the product category 'shirts'.
	}

	return $should_handle;
}
add_filter( 'reserved_stock_pro_should_handle_product_stock', 'puri_reserved_stock_pro_should_handle_product_stock', 10, 2 );Code language: PHP (php)

Opt-in specific product categories

We are often asked how to enabled Reserved Stock Pro to handle reservations for specific product categories.
Here’s an example snippet which will enable only 1 product category for stock reservations.

If the product belongs to the “shirts” category allow reservations, otherwise disable reservations for all other products.

/**
 * Skip specific products from stock reservation. $product is the entire product object.
 */
function puri_reserved_stock_pro_should_handle_product_stock( $should_handle, $product ) {

    // Check if product belongs to a category.
    if ( has_term( 'shirts', 'product_cat', $product->get_id() ) ) {
        $should_handle = true; // Only Reserve products in the category of shirts.
    } else {
        $should_handle = false; // Disable reservations for all other products.
    }

    return $should_handle;
}
add_filter( 'reserved_stock_pro_should_handle_product_stock', 'puri_reserved_stock_pro_should_handle_product_stock', 10, 2 );Code language: PHP (php)
/**
 * Configure the not_enough_stock_notice
 */
function custom_rsp_not_enough_stock_notice( $message, $product_id) {

	$current_lang = apply_filters( 'wpml_current_language', null );

	if ( $current_lang === 'en' ) {
	  $message = 'Cannot add {added_quantity} × {product_name}. There is {available_quantity} available right now.';
	}

	if ( $current_lang === 'pl' ) {
	  $message = 'Cannot add {added_quantity} × {product_name}. There is {available_quantity} available right now.';
	}

	return $message;
}
add_filter( 'reserved_stock_pro_filter_not_enough_stock_notice', 'custom_rsp_not_enough_stock_notice', 10, 2 );Code language: PHP (php)

Filter: Register a custom product type

You can use the reserved_stock_pro_supported_product_types filter. We use this filter to make sure Reserved Stock Pro doesn’t try to control the stock of product types that aren’t fully tested or supported yet.

Make sure that you completely test that everything is working well with your custom product type before you enable reservations for product types on a production site.

/**
 * Add or remove specific product types from stock reservations.
 */
function puri_reserved_stock_pro_supported_product_types( $supported_array ) {

	array_push( $supported_array, 'custom_product_type' ); // Replace with the name of your product type.

	return $supported_array;
}
add_filter( 'reserved_stock_pro_supported_product_types', 'puri_reserved_stock_pro_supported_product_types', 10 );Code language: PHP (php)

[Experimental] Enable WooCommerce subscription products types: subscription & variable-subscription

/**
 * Add or remove specific product types from stock reservations.
 */
function puri_custom_rsp_supported_product_types( $supported_array ) {

	array_push( $supported_array, 'subscription' ); // Simple Subscription Products.
	array_push( $supported_array, 'variable-subscription' ); // Variable Subscription products.

	return $supported_array;
}
add_filter( 'reserved_stock_pro_supported_product_types', 'puri_custom_rsp_supported_product_types', 10 );
Code language: PHP (php)

Filter: Change Reservation Message Location

You can change the default hook placement of the reservation messages.

This snippet will move the stock messages from below the “add to cart” buttons, to above the “add to cart” buttons on single product pages. You can replace with any hooks on the single product page.

If you return false the stock message will not be rendered at all. Instead you can manually place it with a shortcode mentioned above.

/**
 * Change the placement of the reservation messages on single product pages.
 */
function custom_rsp_single_product_stock_message_placement( $placement_hook ) {

	$placement_hook = 'woocommerce_before_add_to_cart_form';

	return $placement_hook;
}

add_filter( 'reserved_stock_pro_stock_message_placement', 'custom_rsp_single_product_stock_message_placement', 10, 1 );Code language: PHP (php)

Filter: Change the date format

You can change the date format of the expiration date on the product in the cart via this PHP snippet. The date format uses the standard PHP date format. You can reference the format options https://www.php.net/manual/en/datetime.format.php and https://www.php.net/manual/en/function.date.php

/**
 * Change the date format the expiration date appears.
 * Find examples of PHP date formats here: https://www.php.net/manual/en/function.date.php
 */
function custom_reserved_stock_pro_date_format( $format ) {

	$format = 'g:i a, F j, Y'; // New PHP Date format without the timezone.

	return $format;
}
add_filter( 'reserved_stock_pro_filter_date_format', 'custom_reserved_stock_pro_date_format', 10 );Code language: PHP (php)

Filter: Customizing Messages & Notices

You can change the messages that appear in WooCommerce per product using the product id. You’ll need to hook into the reserved_stock_pro_filter_reserved_until_message filter.

Here’s an example for product with ID of 100.

/**
 * Change the text on reserved products the cart.
 */
function puri_reserved_stock_pro_filter_reserved_until_message( $message, $product_id ) {

	if ( $product_id === 100 ) {
		$message = 'Custom reserved until {expiration_date}'; // Only for the product with an ID of 100.
	}

	return $message;
}
add_filter( 'reserved_stock_pro_filter_reserved_until_message', 'puri_reserved_stock_pro_filter_reserved_until_message', 10, 2 );Code language: PHP (php)

These filters will allow you to change the other messages dynamically. You change the filter to customize the following messages as well.

  • reserved_stock_pro_filter_added_to_cart_notice
  • reserved_stock_pro_filter_removed_from_cart_notice
  • reserved_stock_pro_filter_not_enough_stock_notice
  • reserved_stock_pro_filter_single_all_stock_reserved_message
  • reserved_stock_pro_filter_single_single_all_stock_available_message
  • reserved_stock_pro_filter_single_has_reserved_stock_message
  • reserved_stock_pro_filter_out_of_stock_text

Translating with WPML

For those who require specific text for each language in WPML, you can use the following snippet to change the text for the current WPML language code.

Replace the shortcode language code with the ones from your WPML install.

Use WPML to translate the countdown text.

/**
 * Configure the options of the Reserved Stock Pro countdown.
 *
 * @param array $options
 * @return array $options
 */
function custom_rsp_countdown_options( $options ) {

	$current_lang = apply_filters( 'wpml_current_language', null );

	if ( $current_lang === 'en' ) {
		$options['countingHtml'] = 'Cart items are reserved for {minutes} minutes and {seconds} seconds.';
		$options['expiredHtml'] = 'Your cart item reservations have expired';
	}

	if ( $current_lang === 'pl' ) {
		$options['countingHtml'] = 'Cart items are reserved for {minutes} minutes and {seconds} seconds.';
		$options['expiredHtml'] = 'Your cart item reservations have expired';
	}

	return $options;

}
add_filter( 'rsp_countdown_options', 'custom_rsp_countdown_options', 10, 1 );Code language: PHP (php)
/**
 * Change the text on reserved products the cart.
 */
function puri_reserved_stock_pro_filter_reserved_until_message( $message, $product_id, $cart_item_key ) {

	$current_lang = apply_filters( 'wpml_current_language', null );

	if ( $current_lang === 'en' ) {
		$message = 'Custom reserved until {expiration_date}';
	}

	if ( $current_lang === 'pl' ) {
		$message = 'Custom reserved until {expiration_date}';
	}

	return $message;
}
add_filter( 'reserved_stock_pro_filter_reserved_until_message', 'puri_reserved_stock_pro_filter_reserved_until_message', 10, 3 );Code language: PHP (php)
/**
 * Configure the fully reserved text.
 */
function custom_rsp_out_of_stock_text( $message, $product_id) {

	$current_lang = apply_filters( 'wpml_current_language', null );

	if ( $current_lang === 'en' ) {
	  $message = 'Stock reserved';
	}

	if ( $current_lang === 'pl' ) {
	  $message = 'Stock reserved';
	}

	return $message;
}
add_filter( 'reserved_stock_pro_filter_out_of_stock_text', 'custom_rsp_out_of_stock_text', 10, 2 );Code language: PHP (php)
/**
 * Configure the partially_reserved text.
 */
function custom_rsp_partially_reserved_text( $message, $product_id) {

	$current_lang = apply_filters( 'wpml_current_language', null );

	if ( $current_lang === 'en' ) {
	  $message = '{reserved_quantity} already reserved. {product_name} can only be held for {minutes} minutes. Get yours now!';
	}

	if ( $current_lang === 'pl' ) {
	  $message = '{reserved_quantity} already reserved. {product_name} can only be held for {minutes} minutes. Get yours now!';
	}

	return $message;
}
add_filter( 'reserved_stock_pro_filter_single_has_reserved_stock_message', 'custom_rsp_partially_reserved_text', 10, 2 );Code language: PHP (php)
/**
 * Configure the none_reserved text - all available.
 */
function custom_rsp_none_reserved_text( $message, $product_id) {

	$current_lang = apply_filters( 'wpml_current_language', null );

	if ( $current_lang === 'en' ) {
	  $message = 'Reserve {product_name} now for {minutes} minutes before anyone else does!';
	}

	if ( $current_lang === 'pl' ) {
	  $message = 'Reserve {product_name} now for {minutes} minutes before anyone else does!';
	}

	return $message;
}
add_filter( 'reserved_stock_pro_filter_single_single_all_stock_available_message', 'custom_rsp_none_reserved_text', 10, 2 );Code language: PHP (php)
/**
 * Configure the fully_reserved text - all reserved.
 */
function custom_rsp_fully_reserved_text( $message, $product_id) {

	$current_lang = apply_filters( 'wpml_current_language', null );

	if ( $current_lang === 'en' ) {
	  $message = 'All {reserved_quantity} stock is currently reserved. {product_name} can only be reserved for a maximum of {minutes} minutes. Check back soon.';
	}

	if ( $current_lang === 'pl' ) {
	  $message = 'All {reserved_quantity} stock is currently reserved. {product_name} can only be reserved for a maximum of {minutes} minutes. Check back soon.';
	}

	return $message;
}
add_filter( 'reserved_stock_pro_filter_single_all_stock_reserved_message', 'custom_rsp_fully_reserved_text', 10, 2 );Code language: PHP (php)
/**
 * Configure the added_to_cart_notice
 */
function custom_rsp_added_to_cart_notice( $message, $product_id) {

	$current_lang = apply_filters( 'wpml_current_language', null );

	if ( $current_lang === 'en' ) {
	  $message = 'You can hold {product_name} for maximum of {minutes} minutes.';
	}

	if ( $current_lang === 'pl' ) {
	  $message = 'You can hold {product_name} for maximum of {minutes} minutes.';
	}

	return $message;
}
add_filter( 'reserved_stock_pro_filter_added_to_cart_notice', 'custom_rsp_added_to_cart_notice', 10, 2 );Code language: PHP (php)
/**
 * Configure the removed_from_cart_notice
 */
function custom_rsp_removed_from_cart_notice( $message, $product_id) {

	$current_lang = apply_filters( 'wpml_current_language', null );

	if ( $current_lang === 'en' ) {
	  $message = '{product_name} has been removed from your cart. Products can only be held for a maximum of {minutes} minutes.';
	}

	if ( $current_lang === 'pl' ) {
	  $message = '{product_name} has been removed from your cart. Products can only be held for a maximum of {minutes} minutes.';
	}

	return $message;
}
add_filter( 'reserved_stock_pro_filter_removed_from_cart_notice', 'custom_rsp_removed_from_cart_notice', 10, 2 );Code language: PHP (php)

Extra: Countdown Changes

By default Reserved Stock Pro will display the countdown as a sticky popup timer on every page. We this method is best for most sites & customers.

Don’t worry you can still do custom countdowns easily. Just make sure to remove the default countdown location and CSS if needed before creating a custom location.

Remove default CSS & location

If you need to replace the countdown with your own, then use the below snippet to remove the CSS or location. You can then add your own version.

/**
 * Remove defaults in Reserved Stock Pro.
 * So you can safely add your own styles without overriding.
 */

// Remove the default CSS.
add_filter( 'rsp_default_countdown_css', '__return_false' );
// Remove the default countdown location.
add_filter( 'rsp_default_countdown_location', '__return_false' );Code language: PHP (php)

Custom Countdown Styling & Shortcode

Here’s an example for making the RSP countdown into a top bar/banner across your whole WooCommerce store.

/**
 * Makes the Reserved Stock Pro countdown display as a top bar.
 * Add your own CSS inline or copy it into your themes custom CSS.
 *
 * Note: This method requires your theme to support 'wp_body_open'.
 */
function puri_rsp_countdown_bar() {

	// New custom CSS. Can be place here or in your theme.
	// Make sure you've removed the default styles first.
	$css = '
	.rsp-countdown-wrapper {
		background: black;
    	color: white;
		text-align: center;
		padding: 15px 0;
		width: 100%;
	}

	.rsp-countdown-wrapper.rsp-no-reservations {
		display: none;
	}

	.rsp-countdown-wrapper.rsp-is-counting {

	}
	.rsp-countdown-wrapper.rsp-is-expired {
		color:red;
	}
	';

	echo '<style>' . $css . '</style>';
	// End of custom css.

	// Output the Resvered Stock Pro Countdown.
	echo do_shortcode( '[rsp_countdown]' );
}
add_action( 'wp_body_open', 'puri_rsp_countdown_bar' );Code language: PHP (php)

Extra: Change add to cart buttons based on stock

The add to cart button text on the shop page, may still displayed “add to cart” in your theme. if you click the button on a product that is out of stock, then WooCommerce will attempt to add the product to cart and display the notice stating thare is no stock left.

You can the button text based on stock availability using this snippet as an example. Note that changing the button with the woocommerce_loop_add_to_cart_link filter will also change the button html. Therefore the button will no longer add to cart when clicked. Customers will simply be redirected to the product page instead.

Example of add to cart buttons changed based on stock levels.

/**
 * Change Add to cart buttons when all stock is reserved.
 * Buttons will link to the product instead of trying to add to cart.
 * If the product is already in cart, the button text will be "Already in cart".
 *
 * @param [type] $add_to_cart_html
 * @param [type] $product
 * @return void
 */
function puri_custom_add_to_cart_button( $default_button_html, $product ) {

	// Make sure we have our function.
	if ( function_exists( 'rsp_get_stock_amounts' ) ) {

		$new_button_text = false;

		$stock_total = rsp_get_stock_amounts( $product->get_id() );

		if ( $stock_total && ! empty( $stock_total['status'] ) ) {
			// if stock is zero or less then sold out.
			if ( $stock_total['status'] === 'out_of_stock' ) {
				$new_button_text = 'Sold Out'; // Change here.
			}

			if ( $stock_total['status'] === 'fully_reserved' ) {
				// Check if product is already in cart.
				$cart_contents = WC()->cart->get_cart_contents();
				
				foreach ( $cart_contents as $cart_item ) {
					if ( $cart_item['product_id'] === $product->get_id() ) {
						$new_button_text = 'Already in cart'; // Change here.
						break;
					}
				}
				if ( ! $new_button_text ) {
					$new_button_text = 'Last Stock Reserved'; // Change here.
				}
			}
		}

		if ( $new_button_text ) {
			// Product link without adding to cart.
			$button_html = '<a class="button" href="' . $product->get_permalink() . '">' . $new_button_text . '</a>';

			return $button_html;
		}
	}

	return $default_button_html;
}

add_filter( 'woocommerce_loop_add_to_cart_link', 'puri_custom_add_to_cart_button', 100, 2 );Code language: PHP (php)

Extra: Variable Products

We’ve been asked about several customizations for WooCommerce stores that sells mostly product variations. Here’s some example snippets.

Disable product variation in dropdown

Screenshot of disabled variation dropdown.
Single product variation not selectable.

On single product pages you can disable variations that are fully reserved or out of stock. Each of those variations will be disabled and appear greyed out. Customers will not be able to select the variations.

/**
 * Disables the variation in the single product dropdown if the variation is fully reserved or out of stock.
 *
 * @param bool   $is_active should variation be active or disabled.
 * @param object $variation product object.
 * @return bool
 */
function rsp_maybe_disable_variation( $is_active, $variation ) {

	if ( ! $is_active ) {
		return $is_active;
	}

	if ( function_exists( 'rsp_get_stock_amounts' ) ) {

		$data = rsp_get_stock_amounts( $variation->get_id() );

		if ( ! empty( $data ) ) {

			if ( $data['status'] === 'fully_reserved' || $data['status'] === 'out_of_stock' ) {
				return false;
			}
		}
	}

	return $is_active;
}

add_filter( 'woocommerce_variation_is_active', 'rsp_maybe_disable_variation', 10, 2 );Code language: PHP (php)

Change product variation stock descriptions

The woocommerce_available_variation hook allows you to change various variation data used to create the frontend dropdown.
We recommend that you fully test this hook to make sure you don’t create conflicts with other plugins that could be using it as well.

The below snippet does a couple of things. You should modify it to fit your needs.

  • Disable the add to cart button when a variation is “Out of stock” and “Fully Reserved”
  • Adds a custom message to variations that are “Fully Reserved”.
/**
 * Reserved Stock Pro - Apply various of things single product variations.
 *
 * Hook in use: https://github.com/woocommerce/woocommerce/blob/5007d17596855a685bd3ec3c8791e689a4e707f5/includes/class-wc-product-variable.php#L363
 *
 * @param array  $variation_data data used to display the available variations.
 * @param object $product product object.
 * @param object $variation variation product.
 * @return bool
 */
function rsp_filter_variation_data_for_single( $variation_data, $product, $variation ) {

	if ( is_admin() || ! is_single() ) {
		return $variation_data;
	}

	if ( function_exists( 'rsp_get_stock_amounts' ) ) {

		$data = rsp_get_stock_amounts( $variation->get_id() );

		if ( ! empty( $data ) ) {
			if ( $data['status'] === 'out_of_stock' ) {
				// Disable the variation "add to cart" button.
				$variation_data['is_purchasable'] = false;
			}

			if ( $data['status'] === 'fully_reserved' ) {
				// Disable the variation "add to cart" button.
				$variation_data['is_purchasable'] = false;
				// Add a custom message when fully reserved.
				$variation_data['variation_description'] = $variation_data['variation_description'] . 'All items reserved. Check back in a few minutes.';
			}
		}
	}

	return $variation_data;
}

add_filter( 'woocommerce_available_variation', 'rsp_filter_variation_data_for_single', 10, 3 );
Code language: PHP (php)

Action Hook: Reserved quantity changed

The action hook reserved_stock_pro_reserved_stock_quantity_changed will be triggered every time a the reservation quantity for a product has changed.

You should use this hook with care, you can potentially slow down performance by overusing it.

/**
 * Reserved Stock Pro - Do something when stock reservations change per product.
 *
 * @param int $product_id Product ID.
 */
function custom_reservation_quantity_changed( $product_id ) {
	// Do something..
}

add_action( 'reserved_stock_pro_reserved_stock_quantity_changed', 'custom_reservation_quantity_changed', 10, 1 );
Code language: PHP (php)

Cache

Reserved Stock Pro has automatic cache integration, so you don’t need to do anything to enjoy the faster speed. However, you can use snippets to disable them for testing, or other reasons.

Disable automatic page cache integrations

Reserved Stock Pro has automatic integrations with several caching plugins. The integration is on by default. This setting relates to page cache only!

What does it do?

The integration makes sure that the page cache of the product is purged every time the reservation quantity of a product changes. This is to make sure that customers see the correct stock quantities and not the old cache.

Why disable it?

  1. If you are not displaying the stock numbers or any related reservation quantity information on the frontend, then you can disable the integration.
  2. If you are running a large store where your customers are continuously adding the same products to their cart. Highly frequent reservation changes will result in the page cache being purged quickly without having time to rebuild. In this situation, you may want to disable this feature and remove related reservation quantity from the product page.

Note: The built-in countdown for stock reservations uses the WooCommerce cart fragments and object caching. It’s not affected by the page cache or this setting.

add_filter( 'rsp_enable_page_cache_plugin_integrations', '__return_false' ); Code language: JavaScript (javascript)

Disable object caching

Generally object caching will only apply if you have Redis for a similar solution running on your server to store the cache between loads.

We recommend you keep object caching turned on since it will greatly improve the speed of database calls.

Object Caching are used for the following:

  • The quantity of a product that is currently reserved.
  • The current customer reservation expiration timestamp.
  • Product IDs curently reserved by the customer.

Disable RSP Object Cache using this snippet.

add_filter( 'reserved_stock_pro_disable_object_cache', '__return_true' ); Code language: JavaScript (javascript)
Was this page helpful?