Developer Reference v3.9.2

Hooks & Filters

Every action and filter hook available in B2B Commerce Kit. Use these to extend, customise, or integrate with any module — no core edits needed.

Where to put your code: Add hook callbacks to your child theme's 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.
No hooks match your search. Try a different term.
Module: Company Credit File: class-woob2b-company-credit.php

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.

Parameters
$order_id int The WooCommerce order ID that triggered the charge.
$amount float Amount charged in base currency (regardless of multi-currency).
$company_id int The company account ID whose balance was charged.
// 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 );
What you'll see Every time a B2B customer places an order using Company Credit, your callback runs with the exact charge amount. You can use this to push invoices to QuickBooks, Xero, or any webhook-based system.
Module: Company Credit

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.

Parameters
$order_idintOrder ID.
$amountfloatAmount released back to the credit balance.
$company_idintCompany account ID.
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 );
Module: Company Credit

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.

Parameters
$availablefloatCalculated available credit (limit minus used).
$company_idintCompany account ID.
$user_idintCurrent user ID placing the order.
// 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 );
What the customer sees If their credit limit is $10,000 and they've used $3,000, normal available credit = $7,000. With this filter returning 90%, the checkout shows $6,300 available, blocking orders that would dip below the 10% reserve.
Module: Company Credit

Return false to hide the Company Credit payment gateway from checkout for specific users, orders, or conditions — even if the user has credit available.

Parameters
$eligibleboolWhether the gateway should be shown. Return false to hide.
$user_idintCurrent user ID.
// 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 );
Module: PO Approval Workflows

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.

Parameters
$orderWC_OrderThe WooCommerce order object awaiting approval.
$approver_idint|nullUser ID of the designated approver (null if admin approval).
// 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 );
What happens When a buyer submits an order above your approval threshold (e.g. $1,000), this hook fires immediately. Your Slack channel gets an instant message. The order sits at "Pending Approval" in WooCommerce admin until an approver acts.
Module: PO Approval Workflows

Fires after an approver clicks "Approve" on a pending order. The order status has already been updated to "processing" when this hook runs.

Parameters
$orderWC_OrderThe approved order object.
$approver_idintUser ID of the person who approved the order.
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 );
Module: PO Approval Workflows
Parameters
$orderWC_OrderThe rejected order object.
$approver_idintUser ID who rejected the order.
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 );
Module: PO Approval — Admin System

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.

Parameters
$po_idintPurchase Order record ID in woob2b_purchase_orders table.
$statusstring'pending' or 'approved' (if auto-approved by rule).
$user_idintBuyer's user ID.
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 );
Module: PO Approval — Admin System
Parameters
$po_idintPurchase Order ID.
$poarrayFull PO data row from the database.
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 );
Module: PO Approval — Admin System
Parameters
$po_idintPurchase Order ID.
$poarrayFull PO data row.
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 );
Module: Discount Rules Engine

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.

Parameters
$pricefloatThe calculated discounted price.
$productWC_ProductThe product being priced.
$user_idintThe customer's user ID.
$ruleobject|nullThe matched discount rule, or null if no rule matched.
// 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 );
What the customer sees Even if a 30% wholesale discount would price an item below your cost, the customer still sees your cost price as the minimum. Protects against deeply discounting high-cost items by accident.
Module: Discount Rules Engine

Lets you programmatically include or exclude specific users from a discount rule, overriding the rule's normal targeting settings.

Parameters
$matchesboolWhether the rule currently matches this user.
$rule_idintThe discount rule ID being evaluated.
$user_idintThe customer's user ID.
// 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 );
Module: Quote / RFQ System

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.

Parameters
$quote_idintThe new quote record ID.
$form_dataarrayAll submitted form field values, keyed by field name.
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 );
What happens Every quote request automatically creates a new deal in HubSpot (or Salesforce, Pipedrive, etc.) with the customer's details and product interest — no manual data entry needed.
Module: Quote / RFQ System

Supplement or replace the default admin email notification when a new quote comes in. The default email still fires unless you remove it.

Parameters
$quote_idintQuote record ID.
$form_dataarraySubmitted form data.
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 );
Module: Points & Rewards

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.

Parameters
$user_idintUser who received the points.
$pointsfloatNumber of points awarded in this transaction.
$reasonstringHuman-readable reason (e.g. "Points earned from Order #42").
$order_idint|nullAssociated order ID if earned from a purchase.
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 );
What happens When a customer accumulates 1,000 points, they're automatically promoted to your Gold wholesale tier and receive a congratulations email — no manual admin action required.
Module: Points & Rewards

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.

Parameters
$pointsfloatCalculated points to award.
$orderWC_OrderThe completed order.
$user_idintCustomer user ID.
// 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 );
What the customer sees Orders completed Saturday or Sunday earn double points. The My Account points history shows the bonus amount clearly. Great for driving weekend orders without needing a separate coupon campaign.
Module: Company Accounts

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.

Parameters
$company_idintThe new company's ID in woob2b_companies.
$company_dataarrayAll company fields (name, email, address, etc.).
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 );
Module: Sub-Accounts
Parameters
$sub_user_idintThe sub-account's WordPress user ID.
$parent_idintThe parent account's WordPress user ID.
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 );
What happens Every time a parent account invites a team member who accepts, the parent receives 50 bonus points automatically. Encourages companies to expand their team usage.
Module: Custom B2B Registration

Fires after admin manually approves a pending registration. The user's role has already been upgraded when this runs.

Parameters
$user_idintThe approved user's ID.
$new_rolestringThe role assigned upon approval.
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 );
Module: Private Catalogs

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.

Parameters
$visibleboolCurrent visibility decision.
$product_idintThe product being checked.
$user_idintUser being checked (0 for guests).
// 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 );
Module: Inventory Rules

Dynamically change the minimum quantity a user must order for a specific product. Useful for applying different minimum rules for new vs established accounts.

Parameters
$min_qtyintCurrent minimum quantity from the rule.
$product_idintProduct being purchased.
$user_idintCustomer user ID.
// 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 );
Module: Hide Price / Call for Price

Override the Hide Price module's decision. Return true to force-hide a price regardless of module settings, or false to always show it.

Parameters
$hiddenboolWhether the price is currently hidden.
$product_idintProduct ID.
$user_idintUser ID (0 for guest).
// 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 );
Module: Tax Exempt Management
Parameters
$user_idintThe user whose exemption was approved.
$exemption_dataarrayCertificate details (number, expiry, type).
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 );
Developer Notes

Best Practices #

Always check module availability. A user might disable a module from Settings → Features. Before calling B2B Commerce Kit classes directly, check with class_exists('WOOB2B_Store_Credits') so your code doesn't throw a fatal error if the module is off.

Use the correct priority

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.

Return the correct type

Filter hooks must return a value. Returning null or nothing from a filter will break the feature. Always end filter callbacks with return $value;.

Declare all parameters

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.

Test on staging first

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.

Quick reference: check if a module is active

// 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
}