Every action and filter hook available in B2B Commerce Kit. Use these to extend, customise, or integrate with any module — no core edits needed.
functions.php, or better, create a small custom plugin in wp-content/plugins/my-b2b-customisations/. Never edit the B2B Commerce Kit plugin files directly — your changes will be lost on update.
Triggered immediately after a company's credit balance is charged during checkout. Use this to sync balances to external accounting software, send custom notifications, or log transactions to a third-party system.
// Log every credit charge to a custom table add_action( 'woob2b_credit_charged', function( $order_id, $amount, $company_id ) { // Sync to your ERP or accounting system my_erp_sync_charge( $company_id, $amount, $order_id ); // Or send an admin Slack notification my_slack_notify( "Credit charged: \$" . $amount . " — Order #" . $order_id ); }, 10, 3 );
Fires when an order is refunded or cancelled and the company's credit balance is restored. Mirror this in your external system to keep credit balances in sync.
add_action( 'woob2b_credit_released', function( $order_id, $amount, $company_id ) { // Push a credit note to your accounting system my_erp_credit_note( $company_id, $amount, $order_id ); }, 10, 3 );
Filter the available credit amount shown to the customer and used to gate checkout. Use this to add a buffer, apply external credit adjustments, or temporarily reduce available credit without touching the database.
// Hold back 10% of credit as a reserve buffer add_filter( 'woob2b_credit_available', function( $available, $company_id, $user_id ) { return $available * 0.9; // 90% of calculated available }, 10, 3 );
Return false to hide the Company Credit payment gateway from checkout for specific users, orders, or conditions — even if the user has credit available.
// Hide credit gateway for orders containing a specific product category add_filter( 'woob2b_credit_gateway_eligible', function( $eligible, $user_id ) { if ( wc_cart_has_items_from_category( 'hazardous' ) ) { return false; // Force card payment for hazardous goods } return $eligible; }, 10, 2 );
Triggered when a checkout order is intercepted by the approval system and set to "pending-approval" status. Use this to send custom notifications, push to Slack, or create a task in your project management tool.
// Send a Slack message when an order needs approval add_action( 'woob2b_order_pending_approval', function( $order, $approver_id ) { $message = '🔔 Order #' . $order->get_order_number() . ' needs approval. Total: ' . wc_price( $order->get_total() ); my_slack_post( '#approvals', $message ); }, 10, 2 );
Fires after an approver clicks "Approve" on a pending order. The order status has already been updated to "processing" when this hook runs.
add_action( 'woob2b_order_approved', function( $order, $approver_id ) { // Trigger order fulfilment in your warehouse system my_wms_create_pick_ticket( $order->get_id() ); // Notify the buyer $buyer = get_userdata( $order->get_customer_id() ); wp_mail( $buyer->user_email, 'Your order is approved!', 'Great news...' ); }, 10, 2 );
add_action( 'woob2b_order_rejected', function( $order, $approver_id ) { $reason = $order->get_meta( '_woob2b_rejection_reason' ); // Log the rejection with reason to your CRM my_crm_log_rejection( $order->get_customer_id(), $reason ); }, 10, 2 );
Triggered when a buyer submits a PO request through My Account → POs. Different from woob2b_order_pending_approval — this is the pre-purchase PO system, not the checkout approval gate.
add_action( 'woob2b_po_submitted', function( $po_id, $status, $user_id ) { if ( $status === 'pending' ) { // Notify your sales team of a new PO to review my_notify_sales_team( $po_id ); } }, 10, 3 );
add_action( 'woob2b_po_approved', function( $po_id, $po ) { // Reserve stock in your inventory system my_reserve_stock_for_po( $po['items_json'] ); }, 10, 2 );
add_action( 'woob2b_po_paid', function( $po_id, $po ) { // Update your accounts receivable ledger my_ar_mark_paid( $po['company_id'], $po['total'] ); }, 10, 2 );
Runs after all discount rules are evaluated. Lets you further adjust the calculated price — round to nearest cent, apply an additional surcharge, or enforce a price floor.
// Enforce a minimum price floor — never below cost price add_filter( 'woob2b_discount_price', function( $price, $product, $user_id, $rule ) { $cost = (float) get_post_meta( $product->get_id(), '_wc_cog_cost', true ); if ( $cost > 0 && $price < $cost ) { return $cost; // Never sell below cost } return $price; }, 10, 4 );
Lets you programmatically include or exclude specific users from a discount rule, overriding the rule's normal targeting settings.
// Exclude blocked/flagged accounts from all discounts add_filter( 'woob2b_rule_matches_user', function( $matches, $rule_id, $user_id ) { if ( get_user_meta( $user_id, 'account_blocked', true ) ) { return false; // No discounts for blocked accounts } return $matches; }, 10, 3 );
Runs when the quote request form is submitted and saved. Use this to push the lead to your CRM, assign a sales rep, or trigger an internal review workflow.
add_action( 'woob2b_quote_submitted', function( $quote_id, $form_data ) { // Push to HubSpot CRM as a new deal my_hubspot_create_deal([ 'email' => $form_data['customer_email'], 'name' => $form_data['customer_name'], 'product' => $form_data['current_product_id'], 'source' => 'B2B RFQ', ]); }, 10, 2 );
Supplement or replace the default admin email notification when a new quote comes in. The default email still fires unless you remove it.
add_action( 'woob2b_quote_request_notification', function( $quote_id, $form_data ) { // Route to specific sales reps based on product category $product = wc_get_product( $form_data['current_product_id'] ); $rep_email = my_get_rep_for_product( $product ); wp_mail( $rep_email, 'New quote request', '...' ); }, 10, 2 );
Triggered every time points are added to a user — for purchases, account actions, milestones, or admin adjustments. Use this to send a congratulations email, push to a loyalty dashboard, or trigger tier upgrades.
add_action( 'woob2b_points_awarded', function( $user_id, $points, $reason, $order_id ) { // Auto-upgrade to Gold tier when they cross 1000 lifetime points $total = WOOB2B_SubAccount_Helpers::get_store_credits( $user_id ); if ( $total >= 1000 && ! user_has_cap( $user_id, 'wholesale_gold' ) ) { wp_update_user(['ID' => $user_id, 'role' => 'wholesale_gold']); my_send_tier_upgrade_email( $user_id ); } }, 10, 4 );
Adjust the number of points calculated for an order before they're awarded. Apply bonus multipliers for promotions, exclude certain product categories, or implement a double-points weekend.
// Double points on weekends add_filter( 'woob2b_points_to_award', function( $points, $order, $user_id ) { $day = (int) date( 'N' ); // 6=Sat, 7=Sun if ( $day >= 6 ) { return $points * 2; // 2× weekend bonus } return $points; }, 10, 3 );
Triggers after a new company account is saved — whether created by admin or via API. Use this to create a matching record in your CRM, assign default settings, or send a welcome email to the company contact.
add_action( 'woob2b_company_created', function( $company_id, $company_data ) { // Create matching account in Salesforce my_sf_create_account([ 'name' => $company_data['company_name'], 'email' => $company_data['email'], 'b2b_id' => $company_id, ]); }, 10, 2 );
add_action( 'woob2b_subaccount_created', function( $sub_user_id, $parent_id ) { // Grant sub-account 50 welcome points WOOB2B_SubAccount_Helpers::add_store_credits( $parent_id, 50, 'Bonus for inviting a team member' ); }, 10, 2 );
Fires after admin manually approves a pending registration. The user's role has already been upgraded when this runs.
add_action( 'woob2b_registration_approved', function( $user_id, $new_role ) { // Award welcome points on approval WOOB2B_SubAccount_Helpers::add_store_credits( $user_id, 200, 'Welcome bonus for new wholesale account' ); // Create the company account automatically $user = get_userdata( $user_id ); my_auto_create_company_for_user( $user ); }, 10, 2 );
Final override on whether a product is visible to a user — runs after all Private Catalog rules are evaluated. Return false to hide even if the catalog says it should show.
// Hide discontinued products from all non-admin users add_filter( 'woob2b_product_visible', function( $visible, $product_id, $user_id ) { if ( get_post_meta( $product_id, '_discontinued', true ) && ! current_user_can( 'manage_woocommerce' ) ) { return false; } return $visible; }, 10, 3 );
Dynamically change the minimum quantity a user must order for a specific product. Useful for applying different minimum rules for new vs established accounts.
// New accounts (less than 90 days old) must order at least 24 units add_filter( 'woob2b_min_quantity', function( $min_qty, $product_id, $user_id ) { $registered = strtotime( get_userdata( $user_id )->user_registered ); if ( ( time() - $registered ) < ( 90 * DAY_IN_SECONDS ) ) { return max( $min_qty, 24 ); // New accounts: min 24 } return $min_qty; }, 10, 3 );
Override the Hide Price module's decision. Return true to force-hide a price regardless of module settings, or false to always show it.
// Always hide prices for products in 'restricted' category add_filter( 'woob2b_hide_price', function( $hidden, $product_id, $user_id ) { if ( has_term( 'restricted', 'product_cat', $product_id ) ) { return true; // Always hidden regardless of role } return $hidden; }, 10, 3 );
add_action( 'woob2b_tax_exemption_approved', function( $user_id, $exemption_data ) { // Record exemption approval in your compliance log my_compliance_log( $user_id, 'TAX_EXEMPT_APPROVED', $exemption_data ); }, 10, 2 );
class_exists('WOOB2B_Store_Credits') so your code doesn't throw a fatal error if the module is off.
The default priority is 10. If you need to run after all B2B rules are evaluated, use 20 or higher. If you need to run before, use 5 or lower.
Filter hooks must return a value. Returning null or nothing from a filter will break the feature. Always end filter callbacks with return $value;.
Pass the correct $accepted_args count (last parameter of add_action/add_filter). If a hook passes 3 arguments and you declare 2, you'll only receive 2.
Hooks that modify prices or credit balances have real financial impact. Always test on a staging environment with real-world scenarios before deploying to production.
// Check Company Credit module before using its classes if ( class_exists( 'WOOB2B_Company_Credit' ) ) { // Safe to use company credit functionality } // Check Points & Rewards if ( class_exists( 'WOOB2B_Store_Credits' ) ) { $balance = WOOB2B_SubAccount_Helpers::get_store_credits( get_current_user_id() ); } // Check PO Approval if ( class_exists( 'WOOB2B_PO_Approval' ) ) { // Safe to read/write PO approval order meta }