---
title: "Developer Filters"
description: "Complete reference of WordPress filters and actions available in the Split Pay Plugin, including the 3.7.0 integration architecture hooks (spp_register_integrations, spp_integrations, spp_before_process_transfers, spp_after_process_transfers, spp_fc_order_transferable_items, spp_product_data_tab_classes, spp_transfer_metadata) and platform-agnostic product-save filters."
url: "https://docs.splitpayplugin.com/features/developer-filters/"
---
## Overview

Split Pay exposes a set of WordPress filters that allow developers to programmatically modify transfer settings at runtime. These filters are useful for dynamic transfer logic, custom product types, multivendor scenarios, and any case where the admin UI settings are not sufficient.

All filters follow standard WordPress conventions. Add them in your theme's `functions.php`, a custom plugin, or a code snippets plugin.

Developer filters are available in **both the free and Pro** versions of Split Pay.

* * *

## Integration architecture hooks 3.7.0+

The 3.7.0 modular adapter architecture introduced a small set of hooks for registering additional platform/gateway integrations and for inspecting transfer-time events from any integration. These are the hooks you reach for if you’re building your own platform adapter or wiring Split Pay into a custom workflow.

### `spp_register_integrations` (action) 3.7.0+

Fires once at `plugins_loaded` with the shared `IntegrationRegistry`. Use it from third-party code to register additional integrations alongside the bundled WooCommerce and FluentCart adapters.

```
add_action( 'spp_register_integrations', function( $registry ) {
    if ( class_exists( 'My_Plugin\\Integration\\MyPlatformAdapter' ) ) {
        $registry->register( new \My_Plugin\Integration\MyPlatformAdapter() );
    }
} );
```

### `spp_integrations` (filter) 3.7.0+

Filter the populated `IntegrationRegistry` after the action above runs. Lets you inspect or substitute the full set of integrations Split Pay will use.

```
add_filter( 'spp_integrations', function( $registry ) {
    return $registry;
} );
```

### `spp_product_data_tab_classes` (filter) 3.7.0+

Filter the WooCommerce product-tab visibility classes for the Split Pay product data tab. By default the tab only appears for `show_if_simple` products. Add additional classes to opt other product types in.

```
add_filter( 'spp_product_data_tab_classes', function( $classes ) {
    $classes[] = 'show_if_subscription'; // Add for WC Subscriptions products
    $classes[] = 'show_if_variable-subscription';
    return $classes;
} );
```

### `spp_before_process_transfers` (action) 3.7.0+

Fires immediately before the `TransferEngine` processes the transfer set for an order. Receives the platform-specific order adapter, the integration slug (e.g. `'fluentcart'`), and the Stripe charge ID. Useful for logging, auditing, or last-minute conditional skip logic.

```
add_action( 'spp_before_process_transfers', function( $orderAdapter, $integration, $chargeId ) {
    error_log( "[SPP] About to process transfers for {$integration} order {$orderAdapter->getOrderId()} (charge {$chargeId})" );
}, 10, 3 );
```

### `spp_after_process_transfers` (action) 3.7.0+

Fires after the engine finishes processing transfers for an order, regardless of success/failure. Same parameters as the “before” action. Use this for post-transfer auditing, custom notifications, or analytics events.

```
add_action( 'spp_after_process_transfers', function( $orderAdapter, $integration, $chargeId ) {
    do_action( 'my_analytics/track', 'split_pay_transfer_completed', [
        'integration' => $integration,
        'order_id'    => $orderAdapter->getOrderId(),
        'charge_id'   => $chargeId,
    ] );
}, 10, 3 );
```

### `spp_fc_order_transferable_items` (filter) 3.7.0+

FluentCart-only. Filter the array of transferable line items returned by `FCOrderAdapter::getTransferableItems()`. Use it to suppress particular line items from triggering transfers (for example, a service fee that should not be split).

```
add_filter( 'spp_fc_order_transferable_items', function( $items, $order ) {
    return array_filter( $items, function( $item ) {
        return ! str_starts_with( $item['name'] ?? '', 'Service Fee' );
    } );
}, 10, 2 );
```

### `spp_transfer_metadata` (filter) 3.7.0+

Platform-agnostic transfer metadata filter. Currently fired by the FluentCart integration and intended as the unified hook for all integrations going forward. Receives the metadata array, the order object (or `null`), and the integration slug.

```
add_filter( 'spp_transfer_metadata', function( $metadata, $order, $integration ) {
    $metadata['source_integration'] = $integration;
    return $metadata;
}, 10, 3 );
```

* * *

## Global filters

These filters modify the global transfer settings that apply to all products without product-level overrides.

### `spp_get_stored_accounts`

Filter the list of connected Stripe accounts available for selection. Receives an array of account objects.

```
add_filter( 'spp_get_stored_accounts', function( $accounts ) {
    // Add a dynamically-registered connected account
    $accounts[] = array(
        'account_id' => 'acct_1234567890',
        'label'      => 'Vendor — Dynamic Account',
    );
    return $accounts;
} );
```

### `spp_global_connect_id_settings`

Filter the global transfer settings array. This is the main filter for overriding global behavior. The settings array includes keys for `connect_id`, `transfer_type`, `transfer_percentage`, `transfer_amount`, and shipping-related fields.

```
add_filter( 'spp_global_connect_id_settings', function( $settings ) {
    // Override the global connected account
    $settings['connect_id'] = 'acct_VENDOR_ABC';

    // Switch to percentage-based and set to 15%
    $settings['transfer_type'] = 'percentage';
    $settings['transfer_percentage'] = 15;

    return $settings;
} );
```

* * *

## Product-level filters

These filters modify transfer settings for individual products. Each filter receives the current value and the product ID (`$post_id`), allowing you to apply conditional logic per product.

**Platform-agnostic since 3.7.0.** Each `spp_before_save_product_*` filter listed below now also fires from the FluentCart product save path (`FCProductAdapter::saveProductSplitPaySettings()`) in addition to the WooCommerce save path. The same callback runs for both platforms, so you can write platform-agnostic logic.

### `spp_before_save_product_accounts`

Filter the connected account ID(s) assigned to a product.

```
add_filter( 'spp_before_save_product_accounts', function( $accounts, $post_id ) {
    // Route all products in category "electronics" to a specific vendor
    if ( has_term( 'electronics', 'product_cat', $post_id ) ) {
        $accounts = array( 'acct_ELECTRONICS_VENDOR' );
    }
    return $accounts;
}, 10, 2 );
```

### `spp_before_save_product_types`

Filter the transfer type for a product. Accepted values: `'percentage'` or `'fixed'`.

```
add_filter( 'spp_before_save_product_types', function( $type, $post_id ) {
    // Force all digital products to use fixed transfers
    $product = wc_get_product( $post_id );
    if ( $product && $product->is_virtual() ) {
        $type = 'fixed';
    }
    return $type;
}, 10, 2 );
```

### `spp_before_save_product_transfer_percentage`

Filter the transfer percentage for a product.

```
add_filter( 'spp_before_save_product_transfer_percentage', function( $percentage, $post_id ) {
    // Give premium vendors a higher split
    $vendor_tier = get_post_meta( $post_id, '_vendor_tier', true );
    if ( $vendor_tier === 'premium' ) {
        $percentage = 25;
    }
    return $percentage;
}, 10, 2 );
```

### `spp_before_save_product_transfer_amount`

Filter the fixed transfer amount for a product.

```
add_filter( 'spp_before_save_product_transfer_amount', function( $amount, $post_id ) {
    // Set a minimum transfer amount of $5
    if ( $amount < 5 ) {
        $amount = 5;
    }
    return $amount;
}, 10, 2 );
```

### `spp_before_save_product_shipping_transfer_type`

Filter the shipping transfer type for a product. Accepted values: `'percentage'` or `'fixed'`.

```
add_filter( 'spp_before_save_product_shipping_transfer_type', function( $type, $post_id ) {
    return 'percentage';
}, 10, 2 );
```

### `spp_before_save_product_shipping_transfer_percentage`

Filter the shipping transfer percentage for a product.

```
add_filter( 'spp_before_save_product_shipping_transfer_percentage', function( $percentage, $post_id ) {
    return 50; // Transfer 50% of shipping to vendor
}, 10, 2 );
```

### `spp_before_save_product_shipping_transfer_amount`

Filter the fixed shipping transfer amount for a product.

```
add_filter( 'spp_before_save_product_shipping_transfer_amount', function( $amount, $post_id ) {
    return 3.00; // Always transfer $3.00 for shipping
}, 10, 2 );
```

* * *

## Variable product filters

These filters follow the same pattern as product-level filters but apply to individual **product variations**. They use the `variable_product` prefix in the filter name and receive the variation's post ID.

### Available variable product filters

| Filter Name | Description |
| --- | --- |
| `spp_before_save_variable_product_accounts` | Connected account(s) for a variation |
| `spp_before_save_variable_product_types` | Transfer type for a variation |
| `spp_before_save_variable_product_transfer_percentage` | Transfer percentage for a variation |
| `spp_before_save_variable_product_transfer_amount` | Fixed transfer amount for a variation |
| `spp_before_save_variable_product_shipping_transfer_type` | Shipping transfer type for a variation |
| `spp_before_save_variable_product_shipping_transfer_percentage` | Shipping transfer percentage for a variation |
| `spp_before_save_variable_product_shipping_transfer_amount` | Fixed shipping transfer amount for a variation |

Usage follows the same pattern as product-level filters:

```
add_filter( 'spp_before_save_variable_product_transfer_percentage', function( $percentage, $variation_id ) {
    // Variation-specific logic
    $variation = wc_get_product( $variation_id );
    $size = $variation->get_attribute( 'size' );

    if ( $size === 'XL' || $size === 'XXL' ) {
        $percentage = 20; // Higher split for larger sizes
    }

    return $percentage;
}, 10, 2 );
```

* * *

## Transfer-time metadata filters

These filters run at the moment a Stripe Transfer is created, allowing you to modify the `metadata` array attached to each transfer. This is useful for adding custom tracking data, order details, or vendor-specific information to Stripe's transfer metadata.

Transfer metadata filters fire during webhook processing (when `payment_intent.succeeded` is received). They do not fire during admin save actions.

### `spp_global_account_wise_meta_data`

Filter the metadata attached to **global transfers** (both percentage and fixed). Receives the metadata array, the originating store order ID (a WooCommerce order ID on Stack A or a FluentCart order ID on Stack B — **not** WooCommerce-specific), and the connected account ID.

```
add_filter( 'spp_global_account_wise_meta_data', function( $meta_data, $order_id, $account_id ) {
    // Add custom tracking data to global transfers.
    // $order_id is a store order ID (WC or FC) - look it up via the
    // appropriate API for your platform if you need the order object.
    $meta_data['vendor_region'] = get_user_meta( get_current_user_id(), 'region', true );
    $meta_data['internal_ref']  = 'GLOBAL-' . $order_id;

    return $meta_data;
}, 10, 3 );
```

### `spp_product_wise_meta_data`

Filter the metadata attached to **product-level transfers**. Receives the metadata array, the originating store order ID (WooCommerce or FluentCart), and the connected account ID.

```
add_filter( 'spp_product_wise_meta_data', function( $meta_data, $order_id, $account_id ) {
    // Include the product name in the transfer metadata.
    // wc_get_product() is WC-specific; on FluentCart use the
    // platform's product accessor.
    if ( isset( $meta_data['Product Id'] ) && function_exists( 'wc_get_product' ) ) {
        $product = wc_get_product( $meta_data['Product Id'] );
        if ( $product ) {
            $meta_data['Product Name'] = $product->get_name();
        }
    }

    return $meta_data;
}, 10, 3 );
```

### Shipping transfer metadata filters

These filters work identically to the payment transfer filters but apply to shipping fee transfers:

| Filter Name | Description |
| --- | --- |
| `spp_shipping_transfer_meta_data` | Metadata for global shipping transfers (account-level) |
| `spp_global_shipping_transfer_meta_data` | Metadata for global shipping transfers (percentage/fixed) |
| `spp_product_wise_shipping_transfer_meta_data` | Metadata for product-level shipping transfers |

All shipping metadata filters receive the same three parameters: `$meta_data`, `$order_id`, and `$account_id`.

```
add_filter( 'spp_shipping_transfer_meta_data', function( $meta_data, $order_id, $account_id ) {
    $meta_data['shipping_carrier'] = 'USPS';
    return $meta_data;
}, 10, 3 );
```

* * *

## Complete filter reference

| Filter Name | When it Fires | Parameters |
| --- | --- | --- |
| `spp_register_integrations` (action) | `plugins_loaded` — integration registry boot (3.7.0+) | `$registry` |
| `spp_integrations` | `plugins_loaded` — after registry is populated (3.7.0+) | `$registry` |
| `spp_product_data_tab_classes` | WooCommerce product edit screen — tab visibility (3.7.0+) | `$classes` |
| `spp_before_process_transfers` (action) | Transfer time — before TransferEngine runs (3.7.0+) | `$orderAdapter, $integration, $chargeId` |
| `spp_after_process_transfers` (action) | Transfer time — after TransferEngine runs (3.7.0+) | `$orderAdapter, $integration, $chargeId` |
| `spp_fc_order_transferable_items` | FluentCart — reading transferable line items (3.7.0+) | `$items, $order` |
| `spp_get_stored_accounts` | Admin UI — account dropdowns | `$accounts, $level` |
| `spp_global_connect_id_settings` | Admin — saving global settings | `$settings` |
| `spp_before_save_product_accounts` | Admin — saving product | `$accounts, $post_id` |
| `spp_before_save_product_types` | Admin — saving product | `$type, $post_id` |
| `spp_before_save_product_transfer_percentage` | Admin — saving product | `$percentage, $post_id` |
| `spp_before_save_product_transfer_amount` | Admin — saving product | `$amount, $post_id` |
| `spp_before_save_product_shipping_transfer_type` | Admin — saving product | `$type, $post_id` |
| `spp_before_save_product_shipping_transfer_percentage` | Admin — saving product | `$percentage, $post_id` |
| `spp_before_save_product_shipping_transfer_amount` | Admin — saving product | `$amount, $post_id` |
| `spp_before_save_variable_product_accounts` | Admin — saving variation | `$accounts, $variation_id` |
| `spp_before_save_variable_product_types` | Admin — saving variation | `$type, $variation_id` |
| `spp_before_save_variable_product_transfer_percentage` | Admin — saving variation | `$percentage, $variation_id` |
| `spp_before_save_variable_product_transfer_amount` | Admin — saving variation | `$amount, $variation_id` |
| `spp_before_save_variable_product_shipping_transfer_type` | Admin — saving variation | `$type, $variation_id` |
| `spp_before_save_variable_product_shipping_transfer_percentage` | Admin — saving variation | `$percentage, $variation_id` |
| `spp_before_save_variable_product_shipping_transfer_amount` | Admin — saving variation | `$amount, $variation_id` |
| `spp_global_account_wise_meta_data` | Transfer time — global transfers | `$meta_data, $order_id, $account_id` |
| `spp_product_wise_meta_data` | Transfer time — product transfers | `$meta_data, $order_id, $account_id` |
| `spp_shipping_transfer_meta_data` | Transfer time — shipping transfers | `$meta_data, $order_id, $account_id` |
| `spp_global_shipping_transfer_meta_data` | Transfer time — global shipping | `$meta_data, $order_id, $account_id` |
| `spp_product_wise_shipping_transfer_meta_data` | Transfer time — product shipping | `$meta_data, $order_id, $account_id` |
| `spp_transfer_metadata` | Transfer time — all transfers (FluentCart today, all integrations going forward) | `$metadata, $order, $integration` |

* * *

## Best practices

*   **Always return a value** — Every filter callback must return the filtered value, even if unchanged.
*   **Test in test mode** — Use [Stripe test mode](../../faqs/testing/) to verify your filters produce the correct transfer amounts before going live.
*   **Use a custom plugin** — Placing filter code in a separate plugin (rather than `functions.php`) ensures it persists across theme changes.
*   **Log for debugging** — Use `error_log()` within your filter callbacks to trace values during development.
*   **Check priority** — If multiple filters modify the same value, use the priority parameter (default: 10) to control execution order.

Filters that set transfer amounts too high can result in transfer errors from Stripe. Ensure the total of all transfers for an order does not exceed the payment amount minus Stripe fees.
