Developer Reference
Technical reference for developers extending or integrating with Super Speedy AJAX Prices.
Last updated for plugin version 1.3.
Table of Contents
Constants
Two behaviour flags, defined in the main plugin file with if (!defined(...)) guards so you can override them earlier (e.g. in wp-config.php or an mu-plugin).
WC_AJAX_PRICING_VERBOSE_LOGGING
- Default:
false - Enables verbose tracing of the VAT-exempt tax logic to the error log (via
error_log()). - Privacy note: when on, the log includes the resolved customer tax location (country/state/postcode/city) and VAT-exempt status. Use it only for debugging and turn it off afterwards — don’t leave it enabled on production.
// wp-config.php
define( 'WC_AJAX_PRICING_VERBOSE_LOGGING', true );
WC_AJAX_PRICING_TRUST_VAT_EXEMPT
- Default:
false - Controls whether an explicit
is_vat_exemptflag on theWC_Customer(e.g. set by an EU VAT-number plugin) is trusted to trigger the inclusive-tax strip in the VAT-exempt fix. - Off by default because of a known WooCommerce edge case around that flag; the plugin otherwise determines exemption from the visitor’s resolved location and matching tax rates. See the VAT-Exempt / Tax-Inclusive Pricing article.
define( 'WC_AJAX_PRICING_TRUST_VAT_EXEMPT', true );
AJAX request / response contract
If you want to consume the pricing endpoint directly (custom front end, headless probe, queueing layer) rather than relying on the bundled script, this is the contract.
Endpoint: admin-ajax.php, action get_wc_prices (registered for both logged-in and logged-out visitors).
Request (POST):
| Field | Type | Notes |
|---|---|---|
action |
string | get_wc_prices |
nonce |
string | From wp_create_nonce('wc-ajax-pricing-nonce'), localized as wc_ajax_pricing_params.nonce. Checked, but weak-by-design on cached pages (see note). |
product_ids |
array | Product IDs. Coerced to int, de-duplicated, zero-filtered, and capped at ssap_max_products_per_request (default 200). |
Response (wp_send_json_success):
{
"success": true,
"data": {
"prices": {
"123": { "price_html": "<span …>£10.00</span>", "is_variable": false }
},
"stock": {
"123": {
"availability_html": "<p class=\"stock in-stock\">5 in stock</p>",
"is_in_stock": true,
"is_purchasable": true,
"add_to_cart_html": "<a …>Add to cart</a>"
}
}
}
}
pricesis always present (keyed by product ID). Unknown / non-published / non-existent IDs are simply omitted.stockis present only when Refresh stock via AJAX is enabled. Adapter fields (bundled_items,components, etc.) appear inside each stock entry viassap_stock_data_for_product.- On no valid IDs the response is
wp_send_json_error({ message }).
Nonce caveat: because the page is full-page cached, the localized nonce is effectively a shared constant for logged-out visitors. The endpoint is safe to expose only because it returns public data, changes no state, gates to published products, and caps the batch — do not treat the nonce as an access boundary.
Filters
ssap_max_products_per_request
Caps how many product IDs a single AJAX request to get_wc_prices will process. Each ID in the request triggers a wc_get_product() load plus a price render (and, when stock refresh is enabled, a stock + Add-to-Cart template render), so the cap exists to stop one request from forcing thousands of those — both as an accidental-load safeguard on very large grids and as a deliberate-abuse / request-amplification safeguard on a public endpoint.
- Default:
200 - Applied: server-side, in
WC_AJAX_Pricing::get_ajax_prices(), after the incoming IDs are sanitised (absint), de-duplicated, and zero-filtered. The first N IDs are kept; the rest are dropped for that request. - Return: an integer. The value is cast with
(int), so returning a numeric string is fine.
A normal shop or category page shows far fewer than 200 products, so most stores never need to touch this. Raise it only if you legitimately render more than 200 products in a single page (and therefore in a single batched refresh).
// Allow up to 500 products per AJAX refresh.
add_filter( 'ssap_max_products_per_request', function () {
return 500;
} );
You can also lower it to tighten the safeguard further:
add_filter( 'ssap_max_products_per_request', fn() => 60 );
Note: Auto Infinite Scroll appends products in batches and re-initialises only the newly-added placeholders, so each refresh only ever requests the IDs that have not yet been loaded — this almost never approaches the cap regardless of total catalogue size.
ssap_stock_data_for_product
Filters the per-product stock payload returned by the AJAX endpoint (only present when Refresh stock via AJAX is enabled). This is the extension point the bundled Bundles and Composite adapters use to add their own per-product fields without the core plugin hard-coding knowledge of those product types.
- Parameters:
( array $data, WC_Product $product ) - Return: the (optionally augmented)
$dataarray.
Default $data keys:
| Key | Type | Description |
|---|---|---|
availability_html |
string | WooCommerce’s rendered stock HTML (e.g. 5 in stock) |
is_in_stock |
bool | $product->is_in_stock() |
is_purchasable |
bool | $product->is_purchasable() |
add_to_cart_html |
string | Rendered loop Add-to-Cart markup |
add_filter( 'ssap_stock_data_for_product', function ( $data, $product ) {
$data['my_custom_flag'] = (bool) get_post_meta( $product->get_id(), '_my_flag', true );
return $data;
}, 10, 2 );
Published-only gate
The endpoint only ever returns data for products whose status is publish. Draft, pending, private, and scheduled (future) products are skipped — both when the price placeholder is inserted (replace_price_with_placeholder()) and again inside the AJAX handler (get_ajax_prices()). This prevents an unauthenticated caller from enumerating prices/stock for unpublished products. There is intentionally no filter to relax this — if you need AJAX pricing on a product, publish it.
JavaScript events
The front-end script fires these on document.body so other scripts can react:
| Event | Fired when | Args |
|---|---|---|
wc_ajax_pricing_updated |
After prices have been swapped in | — |
wc_ajax_inventory_updated |
After stock/Add-to-Cart have been swapped in | [stock] — the per-product stock map |
jQuery( document.body ).on( 'wc_ajax_inventory_updated', function ( e, stock ) {
console.log( 'Live stock for these products:', stock );
} );