Skip to main content

This is the one we've been building towards. If you've been following the last few releases, you know we shipped the subscription engine in 1.6.0 and said migration was coming. Well, here it is.

FluentCart now migrates your entire WooCommerce store. Products, orders, customers, coupons, tax rates, and yes - even WooCommerce Subscriptions. Everything comes over with history intact.

This isn't a half-baked import. Your order numbers stay the same. Stripe payment intents and PayPal transaction IDs carry over. Refunds, line items, tax breakdowns, shipping, order notes - all of it. Variable products become advanced variations with a shared attribute library. Grouped products and WC Product Bundles become FluentCart bundles. Categories keep their hierarchy.

Subscriptions were the hard part. WooCommerce Subscriptions bills from the store, not the gateway. So migrated subscriptions land on FluentCart's store-managed billing with their status, interval, amounts, trial, and all dates intact. If a customer has a saved Stripe card, auto-charging continues from FluentCart on the next due date. Everyone else gets invoice-based renewals with the payment link flow. Nobody's renewal falls into a gap.

You can run the whole thing from the wizard inside FluentCart, or use WP-CLI for large stores. It's resumable, re-runnable, and safe to test on staging first. Let me know which migrator you want next in the comments.

But that's not all in this release.

  • Data Export. You can now export Orders, Customers, Subscriptions, and Licenses directly from any list screen. CSV with column picker, or JSON with related data included. Filter first, export what you need. No more workarounds for getting data out.
  • Transaction Settlement Times. Transactions now show the payment provider's own settlement time for Stripe, PayPal, Mollie, Paddle, and Authorize.net. Your admin finally lines up with your bank statement.
  • Order Sources got smarter. The Order Sources report now accepts the same advanced filters as the Orders table - filter by product, customer, country, coupon, UTM fields. Plus ad click identifiers from Google, Microsoft, and Facebook are now captured separately and shown on the order's UTM card.

More good stuff:

  • Inventory screen is way faster now - handles thousands of variants without breaking a sweat
  • License renewals and reactivation from customer profile
  • Stripe checkout recovers cleanly from failed card/3D Secure steps (no more stuck checkouts)
  • Duplicate order-paid emails fixed
  • Mollie shows only the right payment methods on subscription checkouts
  • Tons of storefront, admin, and payment fixes
  • Security hardening across core and pro

How to get the Migrator:
It's a separate plugin so we can iterate fast. Grab it here: https://addons-cdn.fluentcart.com/fluent-cart-migrator.zip or install it from FluentCart > Settings > Features & Addons. Also available on GitHub.

Full release notes with all the migration details: https://fluentcart.com/blog/fluentcart-1-6-2/

I'm really proud of this one. The team has been pushing hard, and this release is a milestone for FluentCart. If you've been thinking about moving from WooCommerce, the door is wide open now.

Update us and let us know how it goes. If you need any help with migration, please get in touch with support; we would love to help you to migrate to FluentCart.

Hi. Please see the screenshots for the issues. "Select Page" is coming from code I wrote, but the issue is still there with Target, for example.

1.00

1.00

I need to customise, and add information, preferably a whole tab or two, in the customer account dashboard. Is there a way to do this?

A Bricks solution would be ideal, but even if it takes some custom code I would love to be able to control what they see when they log in to their dashboard and add some information.

Is this possible now with custom code?

I find it inelegant that a customer needs a conventional wordpress account in order to see and manage their service subscription (or past purchases). The automatic "New User Registration" emails that wordpress sends, breaks the illusion this is a proper ecommerce site. What are your best practices for creating a better user experience when logins are required, but you don't want the customer to interact with the classic wordpress interface elements or experience?

I'm going to use Pirate Ship for order shipping. They support importing csv to bulk buy shipping labels. But I can't find how to export orders from fluent cart at all. Just the analytics reports. How do people coordinate shipping labels with this software??? I've looked through everything I can find and can't see this.

I need to be able to have all the info a shipping label needs export to csv. Customer address, store address, package size and weight, etc.

Assume the base currency for a store is USD, and I'm only selling simple digital products. Now there is a customer who bought a product 1 worth 50$. When they open their account page, the product is purchased at 50$.

In the admin order backend it shows as the product is bought at 50$.

All good till this.

If admin changes the base currency to EUR, from the Admins perspective order 1 is shown to be bought at 50$. Now on the customers end, every where that 50USD is supposed to show, now shows 50€

I won't consider this as a edge case, as I was working on multicurrency checkout and customers switching currency can cause this, well at-least in my architecture.

Do these 2 plugins integrate with each other to collect payment on a form by using Fluentcart checkout (instead of the default option settings: Stripe, paypal, mollie, etc)?

Tested against FluentCart 1.6.1 and FluentCart Pro 1.6.1 on a German store
(WordPress locale de_DE, date format "j. F Y", time format "H:i", timezone
Europe/Berlin).

This is not about missing strings. The month and weekday names are already
translatable and work fine. What cannot be reached is the format: the order
of day and month, and the 12-hour clock. Both are literals in the source, so no
translation and no filter can change them.

In German, "Aug 16, 2026 03:30 PM" is wrong three times over: the month name is
English, day and month are in the wrong order, and nobody writes AM/PM. Our
customers see it in transactional e-mails, on the thank-you page and in their
account dashboard.

1 PHP: DateTime::format() with a hard-coded pattern

PHP's DateTime::format() has no locale at all, so "M" always returns "Aug",
even with a German site language. These call sites are therefore impossible to
localize:

app/Views/emails/order/reminder/due/admin.php:10 'M d, Y h:i A'
app/Views/emails/order/reminder/due/customer.php:10 'M d, Y h:i A'
app/Views/emails/order/reminder/overdue/admin.php:10 'M d, Y h:i A'
app/Views/emails/order/reminder/overdue/customer.php:10 'M d, Y h:i A'
app/Views/emails/subscription/reminder/admin.php:11 'M d, Y h:i A'
app/Views/emails/subscription/reminder/customer.php:11 'M d, Y h:i A'
app/Views/emails/subscription/trial_end/admin.php:13 'M d, Y h:i A'
app/Views/emails/subscription/trial_end/customer.php:13 'M d, Y h:i A'
app/Views/emails/subscription/canceled/admin.php:12 'M d, Y'
app/Views/emails/subscription/canceled/customer.php:13 'M d, Y'
app/Views/emails/subscription/renewal/admin.php:34 'd M Y, H:i'
app/Views/invoice/parts/subscription_items.php:39 'M d, Y h:i A'
app/Services/Renderer/Receipt/ThankYouRender.php:625 'M d, Y h:i A'

app/Services/ShortCodeParser/Parsers/SubscriptionParser.php:43,55````app/Services/ShortCodeParser/Parsers/LicenseParser.php:42````date('M j, Y', strtotime(...))

app/Modules/Integrations/FluentPlugins/FluentCRMDeepIntegration.php:607,611,664````gmdate('M j, Y', strtotime(...))

Suggested fix: wp_date(get_option('date_format'), $timestamp), plus
get_option('time_format') where a time is shown. That is what
ReceiptRenderer.php:246 and :813 already do, and the receipt is the one place
where the date comes out right on our store. Making the rest match it would fix
this class of issue completely.

Two of the three date() calls have a second problem: date() and gmdate() use
the PHP default timezone, not the store timezone, so the shortcodes
{{subscription.next_billing_date}}, {{subscription.expire_at}} and
{{license.expiration_date}} can be a day off around midnight.

2 JavaScript: the dayjs format string is a default parameter

Every date in the admin SPA and in the customer dashboard goes through one
helper per bundle:

chunks/Utils.js function S(e, r = "MMM DD") { ... .format(r) }
Start.js function j(e, s = "MMM DD") { ... .format(s) }

The month and weekday names come from window.fluentcart_admin_vars.datei18 at
call time, so those are translatable. The pattern is not: it is a default
parameter inside the module. Concrete results with a fully translated catalog:

ConvertedTime (orders, customers, subscriptions, activity log)
"MMM DD" in the current year, "MMM DD, YYYY" otherwise,
"+ h:mm A" when a time is shown,
and the title attribute always "MMM DD, YYYY h:mm A"
reports and charts
"MMMM D, YYYY", "MMM YYYY"

Because the names are translated but the order is not, a German store ends up
with the worst of both: "August 16, 2026".

The bundle is an ES module, so there is nothing a site can override from the
outside: no window.dayjs, no global formatter, no filter.

Suggested fix: send a display pattern along with the names, for example

'datei18' => [
'weekdays' => [...], 'months' => [...],
'formats' => [
'date' => 'MMM DD, YYYY',
'dateShort' => 'MMM DD',
'time' => 'h:mm A',
],
]

derived from get_option('date_format') / get_option('time_format') (there are
small, well-known converters from PHP date format to dayjs tokens), and have
the helpers fall back to their current literals when the key is absent. That
would keep every existing installation identical and let localized stores use
their own format.

3 TransStrings::dateTimeStrings() has no filter

Every other map in app/Services/Translations/TransStrings.php passes through a
filter: fluent_cart/admin_translations, fluent_cart/blocks_translations,
fluent_cart/customer_profile_translations, fluent_cart/checkout_translations,
fluent_cart/payments_translations. dateTimeStrings() does not. Adding

return apply_filters('fluent_cart/date_time_strings', $strings);

would at least give sites a way to correct the names, and it would be the
natural place to inject the formats from point 2.

4 Small note on monthsShort

dayjs resolves MMM as

monthsShort && (monthsShort[index] || monthsShort(instance, format))
|| months[index].slice(0, 3)

If a translation ever yields an empty string for one of the twelve entries, the
falsy branch calls the array as a function and throws. gettext returns the msgid
for an untranslated string, so this cannot happen today, but it is worth a
guard if the array is ever built programmatically.

Happy to test a patch on our staging install.

Thank you for FluentCart and for constantly improving and developing it!

If you're using a hybrid block theme instead of a full FSE/block theme, you may notice that FluentCart's native Product Description block isn't available everywhere in the block builder.

The block itself already exists in FluentCart and works perfectly fine. FluentCart simply restricts it to certain FluentCart parent/ancestor blocks.

If you want to use the native Product Description block freely inside your own product template, you can remove that restriction with this small snippet:

/**
 * FluentCart 1.6.x
 * Make the native Product Description block available everywhere
 * in the WordPress block editor.
 *
 * No custom block is created.
 * No product data is changed.
 * FluentCart's original block and rendering are still used.
 */

add_filter('register_block_type_args', function ($args, $block_type) {

    if ($block_type !== 'fluent-cart/product-description') {
        return $args;
    }

    unset($args['ancestor']);
    unset($args['parent']);

    return $args;

}, 20, 2);

After adding the snippet, search for:

Product Description

in the block inserter.

You can then place FluentCart's native Product Description block directly inside your own hybrid-theme product template, wherever you want it.

For example:

Product Gallery + Product Info

Product Description

Related Products

The nice thing about this approach is that it doesn't introduce a shortcode, duplicate content, or create a separate description system.

You're still using FluentCart's own native Product Description block, including its normal block styling and settings. It simply becomes available outside of the parent blocks FluentCart normally restricts it to.

Might be useful for anyone building FluentCart product templates with a hybrid theme rather than a full FSE theme.

I found an issue in FluentCart 1.6.0+ when the store is configured to use a comma as the decimal separator.

Problem:

When I open an existing product, make any change and try to save it, FluentCart returns:

Error: Price must be a number.

This happens even when I don't touch the price field.

Interestingly, if I edit the price field manually first, FluentCart allows the product to be saved again.

So the issue seems specifically related to the localized price value that is loaded into the editor when opening an existing product.

How to reproduce:

  1. Configure FluentCart to use a comma as the decimal separator.
  2. Create or open a product with a price such as 19,95.
  3. Open the existing product again.
  4. Change something unrelated, for example the product title.
  5. Save the product.
  6. FluentCart returns: β€œError: Price must be a number.”
  7. Now manually edit/re-enter the price.
  8. Save again, the product can now be saved successfully.

Cause:

From what I can see in FluentCart 1.6.0, the product update validation checks fields such as:

variants.*.item_price

using PHP's numeric validation.

However, when an existing product is loaded, the admin UI can send the localized value back as:

19,95

PHP does not consider 19,95 numeric.

After manually editing the price, the PriceInput apparently converts it back into a format that the backend accepts, which would also explain why saving suddenly works afterwards.

The same issue can potentially affect localized values such as:

1.234,56

So this seems to be a mismatch between localized admin price formatting/state and the server-side validation format.

Expected behaviour:

The admin can continue displaying:

€ 1.234,56

but the value submitted to the API should be normalized internally to:

1234.56

before numeric validation.

I currently have a small workaround that normalizes these values before the FluentCart REST validation runs, and saving existing products works correctly again without having to touch the price field. The snippet is in the comments.

Would be great if this could be fixed in FluentCart itself, since stores using comma decimal formatting can otherwise run into this every time an existing product is edited.