SkyVerge WooCommerce Extensions

When we discussed how to get all WooCommerce orders with a refund, we talked about why the “refunded” status isn’t a great way of tracking orders with a refund, as a partially-refunded order will not have that status.

We put together a helper function to directly query refunds and return the associated order IDs for them. Now let’s talk about a good use-case for that helper: exporting refunded orders.

This tutorial requires intermediate PHP and WordPress development skills.

Export WooCommerce Refunded Orders

When using either our Customer / Order CSV Export or Customer / Order XML Export plugins, filtering the export options for orders or customers is pretty straight-forward. There are filters in place to modify the query arguments for included orders (or customers), the IDs in the export file, or the overall export output.

This lets you have the maximum flexibility over what’s included in exports. We’ll use these filters to adjust the order IDs in the export to only include orders that have a refund associated with them (using our helper function to get refunded orders).

First, we’ll add a setting to only include orders with refunds, then we’ll use this setting to determine when to filter the order IDs in the export.

Add Refunds Export Setting

Both the CSV and XML Export plugins have filters to modify the export settings: wc_customer_order_csv_export_options or wc_customer_order_xml_export_suite_options. These filters will let us add a new option to export all orders, or only those with refunds. No matter which filter we use, our method to add settings will look something like this:

function sv_wc_export_add_refund_options( $options ) {

    $new_options   = array();
    $refund_option = array(
        'name'     => __( 'Refunds', 'textdomain' ),
        'id'       => 'refunds',
        'type'     => 'select',
        'class'    => 'wc-enhanced-select show_if_orders',
        'desc_tip' => __( 'Determine whether to export all orders or those with at least 1 refund.', 'textdomain' ),
        'options'  => array(
            'all'          => __( 'Include all orders', 'textdomain' ),
            'only_refunds' => __( 'Only include orders with refunds', 'textdomain' ),
        'default'  => 'all',

    // add the refund options *before* statuses
    // TODO: can update this when CSV Export uses an associative array for settings {BR 2017-03-18}
    foreach ( $options as $k => $v ) {

        if ( isset( $v['id'] ) && 'statuses' === $v['id'] ) {
            $new_options[] = $refund_option;

        $new_options[] = $v;

    return $new_options;

Notice a couple things: (1) the show_if_orders class — this ensures the setting is hidden for customer exports; (2) the id for the setting — we’ll use this shortly to check if we should be filtering the included order IDs or not; and (3) I’m going to loop through existing settings to determine where to add my new one. Checking the position of an existing settings group is a bit cumbersome because the settings array isn’t keyed, but will be in the future 😉

So far, it’s looking good! I have my new option available for the export tool:

WooCommerce Orders Export: New Export Option

Now I need to actually use the setting.

Filter Order Export Query Args

Either the wc_customer_order_csv_export_query_args or wc_customer_order_xml_export_suite_query_args filter will come into play next. Now we need to adjust the orders included in the export. We’ll first ensure that our refunds setting is set to only_refunds, and if it is (and we’re exporting orders), we’ll adjust the query to get the IDs for the export. Adding a post__in parameter to the query will let us ensure only orders that match our list of orders with refunds are included.

function sv_wc_export_only_orders_with_refunds( $query_args, $export_type ) {

    if ( 'orders' === $export_type && 'only_refunds' === $_POST['export_query']['refunds'] ) {

        // we don't need the refund's ID, just order ID
        $refund_order_ids = array_values( sv_get_wc_orders_with_refunds() );

        if ( ! empty( $refund_order_ids ) ) {
            $query_args['post__in'] = isset( $query_args['post__in'] ) ? array_merge( (array) $query_args['post__in'], $refund_order_ids ) : $refund_order_ids;


    return $query_args;

If the query has a post__in value set already, we’ll merge ours in; if not, we’ll set the parameter 🙂 This ensures that the records included in the export are only included from our set of order IDs with refunds.

Now the final thing: notice to get $refund_order_ids we used our helper function from the previous blog post. Be sure to include that helper function, and you’re all set!

Now when I export orders with the “only include refunds” setting enabled, I’ll get a CSV / XML export of orders with refunds associated only, regardless of status. We’ve also ensured other parameters can still be used, such as products, so you can drill down the export file as needed.

You can check out the full CSV Export snippet or full XML Export snippet to see all of the steps put together.

Published by Beka Rice

Beka leads product direction for SkyVerge and technical documentation. She spends a lot of time on research and interviews, but likes to write so she has an excuse to spend more time jamming out to anything from The Clash to Lady Gaga.


  1. Hello, thanks for the fragment is very helpful. I have a question, I need to include metadata of the credit notes for each refund, can you give me an example to add the columns I need?
    For example I need to add:
    – _ywpi_credit_note_formatted_number
    – _ywpi_credit_note_date
    – _refund_amount

    Thank you

    • Hey Antonio, I think the one row per item format would be easiest to start with here, as it will give you refunded amount per line item. However, the export won’t include custom meta like you’ve outlined here by default. I’d recommend reaching out to Codeable for a project like this, as adding columns / column data for these data points is possible.

Hmm, looks like this article is quite old! Its content may be outdated, so comments are now closed.