Customize Metadata
When processing payments through Stripe, you may want to include additional information about the order, customer, or transaction context. Stripe allows you to attach custom metadata to payment intents, which can be invaluable for tracking, reporting, and debugging purposes. This metadata appears in your Stripe Dashboard and can be used for analytics or integration with other systems.
This approach gives you complete control over what information accompanies each payment, allowing you to include business-specific details that help with order management, customer service, or financial reporting.
When would you use this?
Customizing Stripe metadata is particularly useful for businesses that need to track additional context beyond the standard payment information. Instead of relying solely on Stripe's default metadata, you can include details that matter to your specific business processes.
Common use cases include adding custom order numbers or internal tracking IDs for integration with external systems, including customer lifetime value or VIP status for prioritized support, tracking marketing campaign sources or referral codes, or adding product-specific information like subscription tiers or service levels.
The Code
This example shows how to both add custom metadata and remove default metadata fields. The first example adds custom fields while keeping the defaults, and the second shows how to completely replace the metadata with your own set.
Adding custom metadata while keeping defaults:
/**
* Add custom metadata to Stripe payment intents
* @param array $args Payment intent arguments
* @param WC_Order $order The order object
* @return array Modified payment intent arguments
*/
add_filter('wc_stripe_payment_intent_args', function($args, $order){
// Add custom fields to existing metadata
$args['metadata']['customer_type'] = $order->get_meta('_customer_vip_status', true) ?: 'standard';
$args['metadata']['utm_source'] = $order->get_meta('_wc_order_attribution_utm_source', true);
$args['metadata']['utm_medium'] = $order->get_meta('_wc_order_attribution_utm_medium', true);
$args['metadata']['custom_order_number'] = $order->get_meta('_custom_order_id', true);
return $args;
}, 10, 2);
Completely replacing metadata with custom fields:
/**
* Replace default metadata with custom metadata
* @param array $args Payment intent arguments
* @param WC_Order $order The order object
* @return array Modified payment intent arguments
*/
add_filter('wc_stripe_payment_intent_args', function($args, $order){
// Replace all metadata with custom fields
$args['metadata'] = [
'order_id' => $order->get_id(),
'customer_email' => $order->get_billing_email(),
'order_total' => $order->get_total(),
'customer_type' => $order->get_meta('_customer_tier', true) ?: 'standard',
'fulfillment_center' => 'warehouse_east',
];
return $args;
}, 10, 2);
Removing specific default metadata fields:
/**
* Remove specific default metadata fields
* @param array $args Payment intent arguments
* @param WC_Order $order The order object
* @return array Modified payment intent arguments
*/
add_filter('wc_stripe_payment_intent_args', function($args, $order){
// Remove sensitive or unnecessary default fields
unset($args['metadata']['ip_address']);
unset($args['metadata']['user_agent']);
// Add replacement fields if needed
$args['metadata']['location'] = $order->get_billing_country();
return $args;
}, 10, 2);
How the Code Works
The code uses the wc_stripe_payment_intent_args
filter, which runs when payment intents are being created and sent to Stripe. This filter receives the payment intent arguments array and the WooCommerce order object, allowing you to modify the metadata before it's transmitted to Stripe.
By default, the plugin sends this metadata to Stripe:
gateway_id
- The payment method ID (e.g., 'stripe_cc')order_id
- The WooCommerce order IDuser_id
- The customer's WordPress user IDip_address
- The customer's IP addressuser_agent
- The customer's browser informationpartner
- Identifies the plugin ('PaymentPlugins')
You can add to this existing metadata using $args['metadata']['new_field'] = $value
, completely replace it by setting $args['metadata'] = [new_array]
, or remove specific fields using unset($args['metadata']['field_name'])
.
Customizing Metadata for Different Scenarios
You can create more sophisticated metadata logic based on your business needs:
Conditional metadata based on order value:
add_filter('wc_stripe_payment_intent_args', function($args, $order){
if($order->get_total() > 500){
$args['metadata']['high_value'] = 'true';
$args['metadata']['review_required'] = 'manual';
}
if($order->get_total() > 1000){
$args['metadata']['priority_processing'] = 'urgent';
}
return $args;
}, 10, 2);
Adding product-specific information:
add_filter('wc_stripe_payment_intent_args', function($args, $order){
$product_categories = [];
$has_subscription = false;
foreach($order->get_items() as $item){
$product = $item->get_product();
if($product){
$categories = $product->get_category_ids();
$product_categories = array_merge($product_categories, $categories);
if($product->get_type() === 'subscription'){
$has_subscription = true;
}
}
}
$args['metadata']['product_categories'] = implode(',', array_unique($product_categories));
$args['metadata']['contains_subscription'] = $has_subscription ? 'yes' : 'no';
return $args;
}, 10, 2);
Adding customer history information:
add_filter('wc_stripe_payment_intent_args', function($args, $order){
if($order->get_user_id()){
$customer = new WC_Customer($order->get_user_id());
$args['metadata']['customer_orders_count'] = $customer->get_order_count();
$args['metadata']['customer_total_spent'] = $customer->get_total_spent();
$args['metadata']['first_time_buyer'] = $customer->get_order_count() === 1 ? 'yes' : 'no';
}
return $args;
}, 10, 2);
Important Considerations
Stripe has a 500-character limit per metadata key and a 500-character limit per metadata value. Additionally, you can have up to 50 metadata key-value pairs per payment intent. Make sure your custom metadata stays within these limits to avoid API errors.
Be mindful of including sensitive information in metadata, as this data will be visible in your Stripe Dashboard. Avoid including full credit card numbers, social security numbers, or other sensitive personal information. Consider using hashed values or reference IDs instead.
Metadata is stored permanently with each payment record in Stripe, so be selective about what information you include to avoid cluttering your records with unnecessary data.
Testing Your Metadata
To verify your custom metadata is being sent correctly, process a test payment and check the payment intent details in your Stripe Dashboard. Navigate to the specific payment and look for the "Metadata" section to confirm your custom fields are appearing as expected.
You can also add logging to see exactly what metadata is being sent:
add_filter('wc_stripe_payment_intent_args', function($args, $order){
$args['metadata']['custom_field'] = 'test_value';
// Log the metadata for debugging
wc_stripe_log_info("Sending metadata for order {$order->get_id()}: " . print_r($args['metadata'], true));
return $args;
}, 10, 2);
Remember to remove or disable debug logging in your production environment to avoid generating excessive log files.