Writing a Custom Product-Type Adapter

June 5, 2026

The plugin ships adapters for WooCommerce Product Bundles and Composite Products that enrich the AJAX stock payload with per-child / per-component data. You can add the same kind of support for any custom or third-party product type using a single filter — no core changes.

The extension point

ssap_stock_data_for_product filters the per-product stock payload before it’s returned in the AJAX response. It only runs when Refresh stock via AJAX is enabled.

  • Params: ( array $data, WC_Product $product )
  • Return: the (augmented) $data array.

Default keys in $data:

Key Type Meaning
availability_html string WooCommerce’s rendered stock HTML
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

Minimal example

add_filter( 'ssap_stock_data_for_product', function ( $data, $product ) {
    $data['my_field'] = (bool) get_post_meta( $product->get_id(), '_my_flag', true );
    return $data;
}, 10, 2 );

A proper adapter (mirroring the built-ins)

Self-registering, and a no-op unless the target product type/plugin is present:

class My_SSAP_Adapter {

    public static function maybe_register() {
        // Bail if the target plugin/type isn't loaded — keeps this harmless everywhere else.
        if ( ! class_exists( 'WC_Product_MyType' ) ) {
            return;
        }
        add_filter( 'ssap_stock_data_for_product', array( __CLASS__, 'add_data' ), 10, 2 );
    }

    public static function add_data( $data, $product ) {
        if ( ! is_object( $product ) || ! method_exists( $product, 'is_type' ) || ! $product->is_type( 'mytype' ) ) {
            return $data;
        }
        // Guard every type-specific call with method_exists for cross-version safety.
        $children = array();
        if ( method_exists( $product, 'get_my_children' ) ) {
            foreach ( $product->get_my_children() as $child ) {
                $children[ (int) $child->get_id() ] = array(
                    'is_in_stock'    => (bool) $child->is_in_stock(),
                    'is_purchasable' => (bool) $child->is_purchasable(),
                );
            }
        }
        $data['mytype_children'] = $children;
        return $data;
    }
}
add_action( 'init', array( 'My_SSAP_Adapter', 'maybe_register' ) );

Patterns to copy from the built-in adapters (includes/adapters/)

  • Guard registration with class_exists and each call with method_exists / is_type — so the adapter tolerates the plugin being absent or a different version.
  • Return only JSON-safe values — cast to int/bool, key child data by ID.
  • Keep it cheap — this runs for every product on the page (subject to the ssap_max_products_per_request cap). Avoid heavy per-product queries; cache if you must.

Consuming it on the front end

The whole stock map is delivered to JavaScript via the wc_ajax_inventory_updated event:

jQuery( document.body ).on( 'wc_ajax_inventory_updated', function ( e, stock ) {
  // stock[ productId ].mytype_children …
} );

Notes

  • Data only appears in the response when Refresh stock via AJAX is enabled.
  • The payload is per-page and capped — don’t bloat it.
  • For the request/response shape, see Developer Reference.

Cross-links: Developer Reference, Compatibility & Integrations, Architecture, Styling & Customizing the Markup.

×
1/1