Your subscriptions are not all going to renew. Milo tells you which ones.
Every subscription store has a number it cannot see: how many active subscribers will fail to renew when their next payment falls due.
Not because of churn, or expired cards, or a decision the customer made. Because of something mundane that went wrong months earlier and left no trace. A card that was never fully saved. A migration that brought the subscription across but not the payment token. A checkout completed with a payment method that cannot be charged again.
These subscriptions look perfect until the day they are meant to bill. The status says active. The next payment date sits neatly in the future. And nothing anywhere says the charge cannot succeed.
Milo Subscriptions ships a Health Check that finds them, in the free core, with no add-on required.
What it looks for
The Health Check runs nightly and scans every live subscription for the states that predict a failure rather than report one:
No renewal source on file. The subscription is set to renew automatically and has nothing stored to charge. This is the one that costs the most, because it passes every other check you might run. A free plan or a manual-invoice subscription legitimately has nothing stored, so those are left alone.
An expired or unusable payment method. The card is there and no longer works. Milo validates stored methods against the gateway in a separate throttled pass, so this is a real answer from your processor rather than a guess from an expiry date.
A missed renewal. The next payment date has passed and no renewal order was created. Something stopped the schedule.
A missing schedule. No next payment date and no end date. The subscription has lost track of when it should bill.
Manual when it could be automatic. The subscription is set to manual renewal, but the gateway supports recurring payments and a card is on file. That is revenue you are asking customers to remember to send you.
Finding the problem is half the job
A list of broken subscriptions is only useful if you can do something about it.
Every category comes with a fix you can apply from the same screen. A missing schedule gets recalculated. A missed renewal gets processed. A subscription that could auto-renew gets switched over. And the two cases where the customer holds the answer, an unusable card or no card at all, send a re-authorization email that walks them through storing a new one.
For stores at scale, the re-authorization flow runs as a throttled campaign across a whole cohort, so you can recover a migrated base without hand-holding each subscriber.
Built for migrations, because that is where it hurts most
Moving a subscription base between platforms is where these problems cluster. Payment data is the hardest part to bring across, and the failure mode is delayed: everything reports success, and the truth arrives one billing cycle later.
Milo’s migrator imports from WooCommerce Subscriptions, WP Swings, YITH, Sublium and Flexible Subscriptions, and the Health Check is what you run afterwards to confirm the base can actually bill. Alongside it, stores using the official WooCommerce Stripe gateway get a dedicated mandate health screen through the Milo Stripe Bridge add-on, which classifies every Stripe subscription by whether its saved method carries a valid off-session mandate.
If you are evaluating a migration, that pairing is worth more than any feature list. A verification report that says “1,500 subscriptions migrated successfully” is not the same as “1,500 subscriptions can take their next payment”, and only the second one pays your invoices.
Where to find it
Subscriptions, then Health Check, in your WordPress admin. It scans nightly on its own and you can run it on demand at any time.
It is part of the free core plugin. Milo Subscriptions is a free WooCommerce subscriptions plugin with recurring billing, trials, sign-up fees, plan switching, a customer self-service portal, and a standalone mode that works without WooCommerce at all.
How to take recurring payments on WordPress without running a shop
You want to charge people every month. A membership, a paywall, access to a tool, a patron button. What you do not want is a shopping cart, a product catalogue, shipping settings and a tax engine, for something that has no products and nothing to ship.
This is one of those problems where WordPress gives you five answers and no way to choose between them. Here is an honest look at the options, what each one actually costs you, and how to pick.
The four ways this is usually done
Stripe on its own
Stripe Payment Links or a small custom integration. You create a recurring price in the Stripe dashboard, drop the link on a page, and you are taking money in ten minutes. Nothing to install, nothing to maintain, and the lowest possible cost: Stripe’s processing fee and nothing else.
The catch arrives the day after the first payment. Your WordPress site knows nothing. It cannot tell a subscriber from a visitor, so it cannot restrict a page, show someone their plan, or stop serving a download when a card fails. You end up either building that yourself or copying email addresses between two systems by hand.
Good for: a donation button, a tip jar, anything where paying does not unlock something on your site.
A membership plugin
MemberPress, Paid Memberships Pro, Restrict Content Pro and their peers. Built exactly for this: levels, content protection, member dashboards, drip content, often with their own gateway integrations.
They work, and if memberships are the whole of your business they are a reasonable place to land. The cost is that you are adopting a second, fairly opinionated system: its own idea of what a member is, its own user interface, its own way of gating content, and usually an annual licence in the low hundreds. It is a lot of machinery if all you needed was to charge nine euros a month for access to a documentation site.
Good for: membership as the product, with courses, levels, communities, drip content.
A hosted platform
SureCart, Lemon Squeezy, Paddle, Gumroad. Checkout, billing, invoices, tax and dunning are all handled off your site, and you embed a button.
The appeal is real: someone else deals with EU VAT and the sales tax paperwork, which alone is worth money. The trade-offs are equally real. Your customer data lives on their platform, your checkout is on their domain or in their iframe, and you pay a platform percentage on every payment on top of the processing fee. Read what happens to your data and your subscribers if you leave: that answer varies a lot, and it is the question people skip.
Good for: digital products sold worldwide where tax compliance is the thing you most want to outsource.
A full WooCommerce store
Install WooCommerce, add a subscriptions plugin, and you have a proper store with recurring products.
Nothing wrong with it, and if you already run WooCommerce it is obviously the answer. But standing up a whole shop to sell one recurring plan means configuring shipping zones you will never use, tax classes for a product with no physical form, and a cart and checkout flow for something bought in a single click. Every one of those is a page that can break and a setting that can be wrong.
Good for: you already sell things, or you are going to.
The gap
Look at what those four have in common: each one asks you to accept something you did not want. Stripe alone leaves your site ignorant. A membership plugin makes memberships your architecture. A hosted platform takes your customers off your site. A store makes you run a store.
What is missing is small: charge on a schedule, and let WordPress know who paid. That is the whole requirement for a great many sites, and until recently nothing filled it without dragging something larger behind it.
What we built instead
Milo Subscriptions has a standalone mode. Turn it on and the plugin runs recurring subscriptions on your site with no WooCommerce, no products, no cart, and no checkout pages to build.
The flow is deliberately the simplest one that works:
Someone clicks a Subscribe button you placed with a block or a shortcode. They land on a secure Stripe Checkout page and enter their card. Stripe Billing then handles everything that follows: the recurring charges, failed payment retries, strong customer authentication, and the self-service portal where customers update their card or cancel. A webhook syncs the status back to your site, so what your pages show always matches what Stripe knows.
Stripe is the source of truth. Your site stores only what it needs in order to gate content and show members where they stand. There are no orders, no cart sessions and no background queues to go wrong, because none of that exists in this mode.
On your side you get blocks and shortcodes for the parts that touch your pages: a subscribe button, a members area, a “my subscription” panel, restricted content, and gated downloads. Content restriction, subscriber analytics, transactional emails and GDPR export and erase are all included.
What it costs
Standalone mode is free to switch on. No licence, no feature gating, unlimited plans and unlimited subscribers.
We take one percent of each subscription payment, on top of Stripe’s own processing fee. That is how the free plugin is funded, and it is shown to you during setup, in the settings and on the plans screen, because a fee you discover later is not a fee, it is a surprise.
One percent is deliberately below what hosted platforms charge for the same job, and the reason is structural rather than generous: they are running your checkout, your tax compliance and your customer records, and that costs them money. We are not. Your subscribers stay on your site, in your database, in your WordPress users table. We only sit in the payment path.
It also means we only earn when you do. If your subscribers stop paying, we stop being paid, which puts us on the same side of the table as you regarding failed payments and churn.
How to choose
Ask what you actually need, in this order.
Does paying unlock something on your site? If not, use Stripe on its own and stop reading. A payment link is genuinely the right answer for a donation button.
Is membership your product, with levels, courses, drip content and a community? Then a membership plugin will fit you better than we will, and you should use one.
Do you sell physical goods, or need shipping, per-line tax, or coupons on orders? Use WooCommerce, and Milo in its standard mode on top of it.
Is cross-border tax compliance the thing you most want off your plate, and are you comfortable with your customers living on someone else’s platform? A hosted platform earns its percentage.
Is what you need “charge every month, and let my site know who paid”? That is what standalone mode is, and it is the case nothing served well.
Getting started
You need the free Milo Subscriptions plugin, Milo Payments connected to Stripe, and a Stripe account. The connection is one click and stores no API keys on your site. Then you switch standalone mode on in the settings, create a plan, and place a subscribe button.
Turning standalone mode on has no effect on an existing WooCommerce store. The two modes are independent, and a site that already sells subscriptions through WooCommerce does not need this at all.
The full walkthrough is in the standalone mode documentation.
How We Make Sure a Milo Update Never Breaks Your Store
A small bug in the wrong place is not a cosmetic glitch. It is a missed renewal, a double charge, or a customer locked out of content they paid for.
That is why, before any change to Milo Subscriptions reaches your site, it has to pass through a series of automated checks. Here is what that looks like, without the jargon.
We test the whole journey, not just the pieces
A lot of software testing checks tiny isolated parts in a vacuum. That is useful, but it is not enough for subscriptions, because the bugs that hurt the most happen between the steps: a switch that forgets to keep the next payment date, a migration that drops a sign-up fee, a renewal that ends up on hold for no reason.
So most of our tests are what we call integration tests. Instead of checking one function on its own, they spin up a real WordPress and WooCommerce, create a real subscription, and then run it through real situations: a customer upgrades their plan, a renewal succeeds (or fails), a store imports its subscriptions from another plugin, someone cancels. The test then checks that the outcome is exactly what it should be, down to the dates and the amounts.
In plain terms: we rehearse the things your customers and you actually do, automatically, every single time.
What one of these tests actually rehearses
Let us make it concrete. Say a customer on your Basic plan upgrades to Premium. That sounds simple, but a lot has to happen correctly in one move. The old plan has to be swapped for the new one. The price has to update. The next payment date has to be preserved, not reset, so the customer is not charged again tomorrow by accident. The change has to be recorded so you can see what happened.
One of our tests does exactly this, start to finish, and then checks every one of those details. If a future change accidentally resets that payment date, the test fails immediately and the update is stopped before it ever ships. The customer never feels it, because the mistake never leaves our hands.
We have tests like that for renewals, cancellations, failed payments, trials, sign-up fees, shipping address changes, and more. Each one is a small, patient rehearsal of something real.
A few real examples
This is not theoretical. Here are a few things our checks have quietly caught or now guard against.
An upgrade must touch only the right plan. When a customer moves from one plan to another, the change has to apply to that subscription and nothing else, even if they have other items in their cart at the time. A test rehearses exactly that, an upgrade made while an unrelated product sits in the cart, and confirms the upgrade only ever attaches to the customer’s own subscription. The day a future change blurs that line, the test fails and the release stops before it ships.
A first payment must match the real calendar. When renewals are synchronized to a fixed day, the first payment is prorated so customers pay only for the days they actually get. That math is easy to get subtly wrong, for example treating a plan billed every three months as if it billed monthly, which is a real difference in what someone pays. A test checks the discount against the true billing calendar on every release, so the amount and the schedule can never drift apart.
Every cent must survive, in every format. Much of the world writes prices like “12,50” with a comma. It is exactly the kind of detail that quietly breaks rounding. A test enters that value and confirms the full amount is saved, down to the last cent, so a parsing slip can never eat the decimals.
None of these are dramatic on their own. Added up over years, they are the difference between software you can trust with your revenue and software you cannot.
Moving from another plugin, safely
One of the most stressful things a store owner can do is move existing subscriptions from one plugin to another. Get it wrong and you can lose billing schedules, payment details, or the link between a subscription and its past orders.
So our importers, including the ones for WooCommerce Subscriptions, WP Swings and YITH (more to come!), are tested both ways: the import is rehearsed end to end, and so is the rollback. Your original data is copied, never moved, and an import can be reverted, putting everything back as it was. We do not just hope that works. We have tests that import a subscription, undo it, and confirm the original is restored exactly. You get to try before you commit.
With WooCommerce or without it
Milo Subscriptions runs both as a WooCommerce extension and in a standalone mode that does not need WooCommerce at all. That is two quite different worlds, and a fix in one must not break the other.
So we test both. The same lifecycle, renewals, emails, cancellations, gets its own rehearsals in standalone mode, separate from the WooCommerce ones. When we add something new, we are explicit about which world it belongs to, and the tests for the other world keep standing guard.
Nothing merges until every gate is green
Tests are only one of the checks. Before any change is accepted, it also has to pass:
- Coding standards, so the code stays consistent and readable, which makes future bugs easier to avoid.
- Static analysis, a tool that reads the code and flags suspicious patterns before they ever run, like using a value that might not exist.
- The full test suite, the hundreds of scenarios above.
All of this runs automatically. If even one check fails, the change does not go in. There is no “we will fix it later.”
We also use it like you do
Automated tests are fast and thorough, but they do not have eyes. So for anything visible, like a new screen, a button, or a block, we also open it in a real browser and use it the way you would: click through it, fill the forms, check it looks right and behaves right. Code can be correct and still feel wrong, and that final human check is where we catch it.
Why this lets us move faster, not slower
It would be easy to assume all this testing slows releases down. It does the opposite. Because the safety net is there, we can ship improvements often and with confidence, instead of sitting on changes for months out of fear. The recent 1.3.0 update, with editable standalone emails, a new importer, a Products view, and a long list of fixes, went out as one coherent release precisely because every part of it was verified before it left our hands.
Today Milo Subscriptions ships with more than two hundred of these automated tests, and the number grows with almost every update. Whenever we fix a bug or add a feature, we add a test that locks in the correct behavior. That test then stays forever, quietly guarding against the same mistake ever coming back. The work we did six months ago is re-verified on every release.
What this means for you
You should not have to think about any of this. That is the whole point. You run your store, your subscriptions renew, your customers stay happy, and the machinery that makes sure an update is safe stays quietly in the background, doing its job on every single release.
And if you ever do hit something that looks off, tell us. It usually becomes a new test the same week, so it can never happen to you, or anyone else, again.
Migrate from WooCommerce Subscriptions to Milo (Free Guide)
If you run a subscription store on WooCommerce, you’ve probably paid the WooCommerce Subscriptions tax: $279 a year, every year, just to keep recurring billing running. Here’s the good news: you don’t have to keep paying it.
Here’s the good news: you can move off it. Milo Subscriptions is a free, modern alternative, it’s on WordPress.org, and it ships with a built-in migrator that brings your existing subscriptions across, usually in an afternoon, without your customers re-entering their cards.
This guide walks through why store owners are switching, and exactly how the migration works.

Why store owners are leaving WooCommerce Subscriptions
It’s rarely one thing. It’s the stack of them:
- $279/year, forever. For a lot of stores, that’s pure overhead on a feature that should be table stakes.
- Gateway lock-in. The “official” path increasingly pushes you toward a single payments stack. If you use Stripe, PayPal, Mollie or Square directly, you want a tool that works with your gateway, not around it.
- A dated admin. Managing subscriptions still feels like 2015, slow list tables, clunky screens.
Meet Milo: free core, modern, and multi-gateways
Milo Subscriptions is a complete subscriptions plugin for WooCommerce, rebuilt on modern WordPress:
- Free core, on WordPress.org. Subscription products, free trials, sign-up fees, plan switching with proration, a self-service customer portal, Blocks checkout, HPOS, 17 languages.
- Your gateways, your way. Payments run through the free Milo Payments plugin (Stripe, PayPal, Mollie, Square in one place), or keep your existing recurring-capable gateway with the Any Gateway add-on.
- A modern admin that’s actually fast to work in.
- Standalone mode, sell subscriptions even without a full WooCommerce store.
Instead of a $279 license, the model is simple: the core is free, Milo Payments takes a small 1% commission on what it processes (or use your own gateway), and a few optional paid add-ons exist for stores that need extras. You only pay in proportion to what you actually sell.
“”But migrating sounds risky.”
It isn’t.
This is the objection that keeps people stuck, so let’s kill it.
Milo ships with a built-in migrator designed specifically for stores coming from WooCommerce Subscriptions (and WP Swings). It brings across:
- your subscriptions, customers, and billing schedules,
- the saved payment methods, so renewals keep charging automatically, customers never re-enter their cards,
- with a preflight check that verifies the matching Milo Payments gateway is connected to the right account before you start.
Connect the same Stripe/PayPal/Mollie/Square account you already use, and your existing tokens keep working. Most stores migrate in an afternoon.
The migration, step by step

- Install Milo Subscriptions (free, from your Plugins screen) and Milo Payments.
- Connect your gateway in Milo Payments, the same account your current subscriptions already charge.
- Open Milo → Import and run the migrator. It reads your existing WooCommerce Subscriptions data and runs a preflight check.
- Review the dry run, then migrate. Your subscriptions, schedules, and saved payment methods come across.
- Verify in the new admin: statuses, next-payment dates, and payment methods. Run the built-in Health Check to confirm nothing drifted.
That’s it. Renewals keep firing on schedule, on the same cards.
Is Milo right for you?
We’re not going to pretend Milo does everything WooCommerce Subscriptions does on day one, no serious tool would. The fundamentals are here today, and the long tail is closing quickly, just follow the changelog and you’ll see it move.
Rome wasn’t built in a day, but with the right craftsmen, nothing stays out of reach.
If you rely on one very specific WCS-only behavior, check the feature comparison first. Otherwise, the gap that actually matters, free vs $279/year, is already closed.
Get started
- Install Milo Subscriptions free →
- Read the full migration guide →
- Compare Milo vs WooCommerce Subscriptions →
Stop renting your subscriptions. Own them.
Milo Subscriptions, meet Breakdance: restrict content by subscription

This one started in our support inbox.
A customer was building client sites in Breakdance and wrote in with a simple question: “Using WooCommerce Subscriptions, we’re able to set conditions in Breakdance based on ‘User Subscriptions’ to display or hide content. Are we able to do this with your plugin somehow?”
Out of the box, the answer was “not yet.” But it turned out to be an easy gap to close, so we wrote a snippet for them. This post is that snippet, cleaned up and explained, so anyone can do the same today.
Once it’s in place, two new conditions show up in Breakdance:
- User Subscription Status: is / is not Active, On hold, Expired, or “any active subscription”
- Subscribed to Product: is one of / none of / all of your subscription products
They sit right alongside Breakdance’s built-in conditions, like logged-in status or user role. No shortcodes, no custom fields, just pick an element and gate it.
The snippet, explained bit by bit
Save the three blocks below, stacked in order, as a single file in wp-content/plugins/ (for example milo-breakdance-conditions.php) and activate it like any plugin. You can also paste the body into your theme’s functions.php or a Code Snippets plugin.
It’s inert unless both Breakdance and Milo Subscriptions are active, so it’s safe to leave it installed.
Block 1: the header, the hook, and a safety check
<?php
/**
* Plugin Name: Milo Subscriptions: Breakdance Conditions
* Description: Adds "User Subscription" display conditions to Breakdance, powered by Milo Subscriptions.
* Version: 1.0.0
*/
defined( 'ABSPATH' ) || exit;
add_action(
'breakdance_register_template_types_and_conditions',
'milo_bd_register_conditions'
);
function milo_bd_register_conditions() {
if (
! function_exists( '\Breakdance\Themeless\registerCondition' )
|| ! class_exists( '\Milo\Subscriptions\Manager' )
) {
return;
}
What’s happening here:
- The plugin header is standard WordPress boilerplate.
defined( 'ABSPATH' ) || exit;just stops anyone from loading the file directly in a browser. - Breakdance fires the
breakdance_register_template_types_and_conditionsaction when it’s collecting the list of conditions to show in the builder. We hook our function onto that moment. This is the one hook you need to know. - The
ifblock is the safety net. If Breakdance’sregisterConditionfunction isn’t available, or Milo’sManagerclass isn’t loaded, wereturnearly and do nothing. That’s what makes the file safe to leave installed even if you deactivate one of the two plugins later.
Note we don’t close the function yet. The two conditions go inside it.
Block 2: the “User Subscription Status” condition
// Condition 1 — User Subscription Status
\Breakdance\Themeless\registerCondition( array(
'supports' => array( 'element_display', 'templating' ),
'availableForType' => array( 'ALL' ),
'slug' => 'milo-user-subscription-status',
'label' => 'User Subscription Status',
'category' => 'Milo Subscriptions',
// Breakdance flags third-party conditions as Pro-only by default, which
// disables them on the free version. Opting out makes them work on both.
'proOnly' => false,
'operands' => array( 'is', 'is not' ),
'valueInputType' => 'dropdown',
'values' => function () {
return array( array(
'label' => 'Subscription',
'items' => array(
array( 'text' => 'Any active subscription', 'value' => 'any-active' ),
array( 'text' => 'Active', 'value' => 'active' ),
array( 'text' => 'On hold', 'value' => 'on-hold' ),
array( 'text' => 'Pending', 'value' => 'pending' ),
array( 'text' => 'Pending cancellation', 'value' => 'pending-cancel' ),
array( 'text' => 'Cancelled', 'value' => 'cancelled' ),
array( 'text' => 'Expired', 'value' => 'expired' ),
),
) );
},
'callback' => function ( $operand, $value ) {
$user_id = get_current_user_id();
$has = false;
if ( $user_id ) {
// "Any active subscription" = Active OR Pending-cancellation
// (still in a paid period). A specific status matches only itself.
$statuses = ( 'any-active' === $value )
? array( 'active', 'pending-cancel' )
: array( (string) $value );
$has = ! empty( \Milo\Subscriptions\Manager::get_user_subscriptions( $user_id, $statuses ) );
}
return ( 'is not' === $operand ) ? ! $has : $has;
},
) );
registerCondition takes one big array. Read it top to bottom and it’s mostly self-describing:
supportssays the condition works on both individual elements (element_display) and whole templates (templating). More on that second one later.slug,label, andcategoryare just identity and grouping. Thiscategoryis what puts everything under a tidy “Milo Subscriptions” heading in the builder.proOnlyis set tofalseon purpose. Breakdance marks third-party conditions as Pro-only by default and disables them on the free version; opting out lets these run everywhere.operandsis the is / is not toggle the user sees.valuesis a function that returns the dropdown options. It runs when Breakdance draws the condition, so the list is always current.
The interesting part is callback. This is the function that decides true or false when the page renders:
- Grab the current user. If nobody’s logged in, the answer is just
false. - Work out which statuses count as a match. If the user picked “Any active subscription,” we treat both
activeandpending-cancelas a pass, because someone who cancelled but is still inside a paid period still has access. Otherwise, we match only the exact status they chose. - Ask Milo for the user’s subscriptions in those statuses. If the result isn’t empty, they have one, so
$hasistrue. - Finally, flip the result if the user chose “is not.”
That Manager::get_user_subscriptions() call is the entire bridge. It’s Milo’s public method, and it does the heavy lifting so the snippet doesn’t have to.
Block 3: the “Subscribed to Product” condition
// Condition 2 — Subscribed to Product
\Breakdance\Themeless\registerCondition( array(
'supports' => array( 'element_display', 'templating' ),
'availableForType' => array( 'ALL' ),
'slug' => 'milo-subscribed-to-product',
'label' => 'Subscribed to Product',
'category' => 'Milo Subscriptions',
// Same opt-out as above, so this condition works on free Breakdance too.
'proOnly' => false,
'operands' => array( 'is one of', 'is none of', 'is all of' ),
'values' => function () {
$products = wc_get_products( array(
'type' => array( 'subscription', 'variable-subscription' ),
'status' => 'publish',
'limit' => -1,
) );
return array( array(
'label' => 'Subscription products',
'items' => array_map( function ( $p ) {
// Value MUST be a string. Breakdance validates condition
// values as strings and rejects the payload otherwise.
return array( 'text' => $p->get_name(), 'value' => (string) $p->get_id() );
}, $products ),
) );
},
'callback' => function ( $operand, $value ) {
$selected = array_map( 'intval', (array) $value );
$owned = array();
$user_id = get_current_user_id();
if ( $user_id ) {
$subs = \Milo\Subscriptions\Manager::get_user_subscriptions( $user_id, array( 'active', 'pending-cancel' ) );
foreach ( $subs as $sub ) {
foreach ( $sub->get_items() as $item ) {
$owned[] = (int) $item->get_product_id();
if ( $item->get_variation_id() ) {
$owned[] = (int) $item->get_variation_id();
}
}
}
}
$matches = array_map( function ( $id ) use ( $owned ) {
return in_array( $id, $owned, true );
}, $selected );
if ( 'is one of' === $operand ) { return in_array( true, $matches, true ); }
if ( 'is none of' === $operand ) { return ! in_array( true, $matches, true ); }
if ( 'is all of' === $operand ) { return ! empty( $matches ) && ! in_array( false, $matches, true ); }
return false;
},
) );
}
Same shape as the first condition, with two differences worth pointing out:
- The
valuesfunction builds its dropdown from your actual store. It callswc_get_products()for published subscription products (both simple and variable) and lists them. There’s a small but important detail in the comment: the value has to be cast to a string with(string), because Breakdance validates condition values as strings and will reject the whole thing if you hand it a number. - The
callbackdoes a bit more. It collects every product (and variation) the user is actively subscribed to, then checks the selected products against that list. The three operands then mean what they say: is one of passes if at least one matches, is none of passes if none do, and is all of passes only if every selected product is owned.
The final } closes the milo_bd_register_conditions function we opened back in Block 1. Stack the three blocks in order and that’s the complete plugin.
Using it in Breakdance
- Edit any page in Breakdance.
- Click the element you want to gate, say a “Members Only” section.
- In the right-hand panel, open Settings → Conditions.
- Click Add Condition and open the category dropdown. You’ll see a new Milo Subscriptions group.
- Pick User Subscription Status → is → Any active subscription.
Now that section only renders for customers with a live subscription. Everyone else never even receives the content. It’s removed server-side, not just hidden with CSS.
Want to gate by a specific plan instead? Use Subscribed to Product → is one of → [your product]. That’s the one for “Gold tier” content, course modules, or download areas tied to a particular subscription.
Bonus: gate a whole template
Because the conditions also support templating, you can apply them to an entire Breakdance Template, not just individual elements. Build a “Members Area” template, set its condition to User Subscription Status is Active, and the whole layout becomes subscriber-only.
A couple of things to know
- It works at render time. The condition is evaluated when the page is built, so it always reflects the visitor’s current subscription. No caching gotchas on the logic itself, though you should still exclude gated pages from full-page caches.
- Logged-out visitors always fail the “active” checks, which is exactly what you want for a paywall.
- Performance: Each check runs a quick lookup of the user’s subscriptions. On a page with a lot of gated elements that’s fine, but the native integration we’re building will memoise it down to a single query per request.
Which builder should we do next?
This snippet came from one support request, and it turned into something every Breakdance user can use.
With that being said, which page builder do you reach for, and which one would you most like to see Milo support next? If you’re using something that isn’t Breakdance, Elementor, or Bricks, tell us. We’d like to know what to prioritise.
Annual vs Monthly Billing: Which to Offer and How to Price It
The answer affects your cash flow, churn rate, and how customers perceive your value. Most stores should offer both, but the way you frame and price them matters more than the options themselves.
Why annual plans are better for your business
The math is straightforward. A monthly subscriber makes 12 stay-or-leave decisions per year. An annual subscriber makes one. That alone cuts your churn exposure dramatically.
Annual plans also improve cash flow. Collecting a full year upfront means you have money to invest in inventory, marketing, or product development before you need to deliver 12 months of value. For early-stage subscription businesses, this cash flow advantage can be the difference between growing and stalling.
There is a compounding effect too. Annual subscribers who renew tend to have higher lifetime value because they already proved they see long-term value in what you offer. They self-selected for commitment.
Why monthly plans still matter
Not everyone is ready to commit for a year. Monthly plans lower the barrier to entry and let hesitant customers try your product with less risk.
Monthly subscribers also give you faster feedback. If you launch a new product line or change your offering, monthly churn (or lack of it) tells you within weeks whether it is working. Annual subscribers mask that signal for months.
For many stores, the best path is: acquire on monthly, convert to annual over time.
How to set the annual discount
The standard approach is to offer annual billing at the price of 10 months, effectively giving 2 months free. This works because it is simple to communicate and feels like a meaningful saving without destroying your margins.
Here is a framework:
| Monthly price | Annual price | Savings | Framing |
|---|---|---|---|
| $29/mo | $290/yr | $58 | “2 months free” |
| $49/mo | $490/yr | $98 | “Save $98/year” |
| $9/mo | $89/yr | $19 | “Less than $7.50/mo” |
“2 months free” works better than showing the percentage discount. 17% off sounds modest. Two free months sounds generous. Same math, different psychology.
Show the monthly equivalent. “$290/year ($24.17/mo)” makes the annual price feel small by anchoring it to a familiar monthly number.
When to push annual harder
Some products naturally lend themselves to annual commitments:
Software and digital access. Customers expect to use it long-term. The switch cost is high (migrating data, learning a new tool). Annual pricing aligns with how they plan to use the product.
Seasonal products. A gardening subscription box or a holiday-themed curation works on annual cycles. Monthly pricing on an inherently annual product creates awkward mid-year cancellations.
B2B and professional services. Businesses budget annually. A yearly invoice is easier to expense than 12 monthly charges. Offer annual billing as the default for B2B customers.
When to keep monthly as the default
Physical subscriptions with high upfront cost. Asking someone to pay $500 upfront for a premium subscription box is a hard sell, even with a discount. Lead with monthly and offer annual as an upgrade after the third or fourth renewal.
New products without social proof. If you have no reviews, no track record, and no brand recognition, an annual commitment feels risky for the customer. Start monthly, build trust, then introduce annual plans once you have retention data that proves people stick around.
High-churn categories. If your average subscriber stays 4-5 months, offering annual plans will not magically fix retention. It will just increase refund requests. Fix the underlying retention problem first.
The upgrade moment
The best time to offer an annual upgrade is not at checkout. It is after the customer has already experienced enough value to know they want to stay.
After the second renewal is a proven sweet spot. The customer has paid twice and received value twice. They are past the “trying it out” phase. An email offering to lock in their current price for a year with two months free converts well at this point.
At renewal time is another natural moment. “Your next monthly charge is coming up. Want to switch to annual and save $58 this year?” It is timely and relevant.
Do not offer it at first checkout as the default. A new customer choosing between “$29/month” and “$290/year” will often choose neither. The annual price creates sticker shock that overshadows the savings. Show monthly as the primary option and mention annual as an alternative for customers who already know what they want.
One more option: quarterly
Quarterly billing is an underused middle ground. It reduces churn decisions from 12 to 4 per year, improves cash flow over monthly, and does not require the large upfront commitment of annual.
It works particularly well for physical product subscriptions where customers want flexibility but find monthly renewals too frequent for products they do not consume that quickly.
Price it at a modest discount over monthly (roughly one month free per year, so 8-10% off). Reserve the bigger discount for annual.
milosubscriptions supports any billing interval: daily, weekly, monthly, quarterly, or annual. Set different prices per period and let customers choose the schedule that fits them at checkout.
Migrating to a New Subscription Plugin Without Losing Subscribers
Active subscribers are paying you on a schedule, and any disruption means lost revenue and support tickets. But staying on a plugin that does not fit your needs has its own cost: workarounds, limitations, and technical debt that compounds over time.
Here is how to migrate cleanly, whether you are moving from WooCommerce Subscriptions, WP Swings, or any other solution.
Before you touch anything
Export your current data. Download a full list of active subscriptions with their status, next payment date, billing amount, and payment method. A CSV from your current plugin or a database backup works. This is your safety net and your verification checklist after migration.
Know your numbers. How many active subscriptions do you have? How many are on automatic payment vs manual renewal? How many have active trials? These numbers tell you the scope of the migration and help you verify nothing was lost.
Pick a low-traffic window. Do not migrate on the first of the month when half your renewals are scheduled. Find a quiet period, ideally 3-5 days before your next batch of renewals, so you have time to verify everything before real charges go through.
The payment method question
This is the part that worries store owners most, and rightly so. Saved payment methods (cards, PayPal agreements, bank mandates) are what make automatic renewals work. If they do not transfer, every subscriber gets a “please update your payment method” email, and a percentage of them never will.
Stripe tokens are portable. If both your old and new plugin connect to the same Stripe account, the saved payment method tokens (stored as customer IDs and payment method IDs) carry over. The new plugin just needs to know where to find them. No customer action required.
PayPal billing agreements depend on the setup. If your old plugin created PayPal reference transactions or vault tokens under your PayPal account, they are still valid. The new plugin needs to use the same PayPal credentials and store the agreement IDs correctly.
The key rule: do not disconnect your payment gateway accounts during migration. Keep the same Stripe account, the same PayPal account. The tokens are tied to those accounts, not to the WordPress plugin.
Migration approaches
Automated migration tool
Some plugins offer a built-in importer that reads your existing subscription data and converts it. This is the fastest path when available.
What to look for in a migration tool:
- Dry-run mode that shows what will be migrated before anything changes
- Mapping of subscription statuses (active, on-hold, cancelled, expired)
- Preservation of billing schedules and next payment dates
- Transfer of payment gateway tokens
- Background processing for large stores (hundreds or thousands of subscriptions)
After running the import: compare your pre-migration numbers against the new plugin. Same number of active subscriptions? Same next payment dates? Same payment methods attached? Go through 5-10 subscriptions manually and verify every field.
Manual migration for small stores
If you have fewer than 50 subscriptions, manual recreation might actually be faster and safer than debugging an automated tool. Create each subscription in the new plugin, copy the billing details, and verify the payment tokens.
Tedious, but you will understand exactly what happened to every subscription.
Testing before you go live
Process a test renewal. Find a subscription with a next payment date coming up soon (or create a test one) and let it renew through the new plugin. Verify the charge went through on Stripe/PayPal, the renewal order was created in WooCommerce, and the customer received the correct email.
Test the customer experience. Log in as a subscriber and check their My Account page. Can they see their subscriptions? Can they pause, cancel, change payment method? Does the next payment date look correct?
Test a failed payment. Use a Stripe test card that declines and verify the new plugin handles it correctly: correct order status, correct customer notification, no accidental cancellation.
The cutover checklist
On migration day, work through this in order:
- Put your store in maintenance mode (optional but reduces variables)
- Take a full database backup
- Run the migration (automated or manual)
- Verify subscription counts match your pre-migration export
- Spot-check 10 subscriptions: status, dates, payment method, customer
- Process one test renewal
- Deactivate the old subscription plugin
- Check the frontend: product pages, cart, checkout, My Account
- Take your store out of maintenance mode
- Monitor the first batch of renewals closely over the next 48 hours
After migration
Keep the old plugin files for 30 days. Do not delete them immediately. If something unexpected surfaces, you want the ability to reference the old code or temporarily reactivate.
Watch your first full renewal cycle. The real test is not migration day. It is the first week of renewals running through the new system. Monitor failed payment rates, check that emails are sending, and watch for support tickets about unexpected charges or missing access.
Tell your subscribers nothing. Unless the customer-facing experience is changing (different My Account layout, new emails), there is no need to announce the migration. Customers do not care what plugin you use. They care that their subscription works.
milosubscriptions includes a built-in migration tool for WooCommerce Subscriptions and WP Swings. It runs a dry-run report first, processes subscriptions in the background, and preserves payment gateway tokens so automatic renewals continue without interruption.
Free Trials That Convert: A Practical Guide for WooCommerce Stores
A customer who hesitates at “$29/month” will often say yes to “try it free for 30 days.” But a trial that is too long, too short, or poorly structured just delays the cancelation.
Here is how to set up trials that actually convert to paying subscribers.
The length of your trial should match your product
There is no universal “right” trial length. It depends on how quickly someone can experience the value of what you sell.
7 days works for products with immediate value: software tools, digital downloads, content libraries. If someone cannot see the benefit in a week, a longer trial will not help.
30 days is the safe default for most subscriptions. Long enough to form a habit, short enough to maintain urgency.
30 days makes sense for products tied to monthly cycles: meal planning services, fitness programs, reporting tools. The customer needs a full cycle to evaluate properly.
Longer than 30 days almost never converts better. It just delays the decision and lets people forget they signed up.
Collect payment information upfront
Trials that require a card on file convert at 2-3x the rate of trials that do not. This is well documented across SaaS and e-commerce.
Yes, some people will not start the trial if you ask for payment details. That is fine. Those are largely the same people who would not have converted anyway. A smaller pool of serious prospects is worth more than a large pool of casual ones.
Be transparent about it. “Your card will not be charged during the trial. You can cancel anytime before it ends.” This single sentence addresses the main objection.
Send a reminder before charging. Three days before the trial ends, email the customer with the exact date they will be charged and a clear link to cancel if they want to. This is not just good practice; in many jurisdictions it is a legal requirement. It also builds trust that pays off in lower post-conversion churn.
Sign-up fees and trials can work together
A small sign-up fee ($1-5) combined with a free trial period filters out people who have no intention of paying while still lowering the barrier.
This works especially well for physical product subscriptions where you have real fulfillment costs during the trial. A $3 sign-up fee on a coffee subscription covers your shipping cost while the customer evaluates the product risk-free.
It also works as a psychological commitment device. Someone who paid even a small amount is more invested than someone who paid nothing.
What to do during the trial
The trial period is not waiting time. It is your best window to turn a curious visitor into a committed subscriber.
Day 1: Deliver immediately. Ship the product, grant the access, send the download. Any delay between signup and value delivery is conversion leaking out.
Day 3-5: Check in. A short email asking how things are going, with a link to support or a getting-started guide. Keep it personal and brief. This is not a marketing campaign.
Day 7 (for 30-day trials): Show what is coming. Preview what they will get as a paying subscriber. New content dropping next week, the next box theme, upcoming features. Give them a reason to look forward to staying.
3 days before end: Be direct. “Your trial ends on [date]. Your card will be charged [amount]. Here is what you will keep getting: [value summary]. Not ready? Cancel here.”
Track the right metric
Trial-to-paid conversion rate is the obvious one. But track it alongside these:
Trial activation rate. What percentage of trial signups actually use the product? If people start trials and never engage, you have a traffic quality or onboarding problem, not a pricing problem.
Time to first value. How quickly does a trial user do the thing your product is for? Download a file, open the box, complete a lesson. The faster this happens, the higher your conversion rate will be.
Post-trial churn at 30 and 90 days. A trial that converts at 80% but loses half those customers in the first three months is not actually performing well. It is attracting people who are not a good fit. Consider whether your trial is setting accurate expectations.
Common mistakes
Making the trial too generous. If the trial includes everything with no limits, there is no reason to upgrade. For access-based subscriptions, consider limiting features or content during the trial rather than giving the full experience away.
No trial-end email. Surprising someone with a charge is the fastest way to get a refund request and a bad review. Always notify before the first charge.
Treating all trial users the same. Someone who logged in six times during their trial needs a different message than someone who never came back after day one. Even basic segmentation (active vs. inactive) dramatically improves conversion.
Never testing the length. If you picked 30 days because it felt right, run a test with 7. Many businesses discover shorter trials convert better because urgency drives action.
milosubscriptions supports free trials, paid trials, and sign-up fees out of the box. Set the trial length and fee per product, and the plugin handles the transition to the first paid renewal automatically.
How to Reduce Subscription Churn Before It Starts
A 5% monthly churn rate means you lose half your subscribers in a year. Even small improvements in retention compound dramatically over time.
Most churn advice focuses on winning back customers who already left. That is too late. The decisions that determine whether someone stays or cancels happen much earlier. Here is where to focus.
The first 7 days decide everything
A subscriber who engages with your product in the first week is significantly more likely to stay past month three. A subscriber who does nothing after checkout is already halfway out the door.
For physical products: ship fast. A subscription that takes 10 days to arrive starts with disappointment. If you cannot ship within 48 hours, send an email immediately after purchase with a tracking timeline and something useful (a guide, a recipe, setup instructions).
For digital products: deliver value before the first renewal. If someone subscribes to your course platform and has not logged in after three days, that is your cue to send a targeted email. Not a generic welcome sequence; a specific “here is the best place to start” nudge.
Price anchoring prevents sticker shock
The number one reason people cancel subscriptions is “I am not getting enough value for the price.” Often the problem is not the price itself but that the customer forgot what they were paying for.
Show the math. If your monthly box contains items worth $80 and costs $40, say so on the product page and in the order confirmation. Remind subscribers of the value in every shipment or renewal email.
Use annual plans strategically. A customer on an annual plan has 1 renewal decision per year instead of 12. That alone reduces churn. Offer a meaningful discount (2 months free is a common and effective framing) to nudge monthly subscribers toward annual.
Let customers pause instead of cancel
When someone clicks “cancel,” they are often not unhappy with your product. They are overwhelmed, traveling, overstocked, or tightening their budget temporarily.
Give them a pause option. A customer who suspends for a month and comes back is infinitely more valuable than one who cancels and never returns. Make the pause button just as visible as the cancel button in their account.
Set a limit. Unlimited pauses can become indefinite cancellations. One or two suspensions per subscription is a reasonable default that protects both sides.
Failed payments are not customer decisions
Involuntary churn, when a subscription ends because a payment failed, accounts for 20-40% of all churn in most subscription businesses. The customer did not choose to leave. Their card expired, their bank flagged the charge, or they hit a temporary limit.
Retry automatically. A single failed charge should not cancel a subscription. Retry 2-3 times over a week with increasing intervals. Most failed payments recover on the second or third attempt without the customer doing anything.
Notify clearly. When a payment fails, send a plain email that says what happened and includes a direct link to update their payment method. Skip the marketing fluff. This is a transactional moment; treat it like one.
Cancellation surveys tell you what analytics cannot
Your analytics show you who churns and when. They do not tell you why. A short cancellation survey (3-5 options plus an open text field) fills that gap.
Common reasons worth tracking:
- Too expensive (pricing problem or value communication problem?)
- Not using it enough (onboarding problem?)
- Switching to a competitor (feature gap or positioning problem?)
- Temporary, plan to come back (do you offer pause?)
- Product quality (fulfillment or sourcing problem?)
Review these monthly. If one reason dominates, you have a clear priority.
The renewals you do not lose
Churn reduction is not one big fix. It is a collection of small decisions:
- Ship or deliver fast after signup
- Remind subscribers what they are paying for and why it is worth it
- Offer pause before cancel
- Retry failed payments automatically
- Ask why when someone leaves, and act on the patterns
A subscription business with 3% monthly churn instead of 5% does not just retain a few more customers. Over a year, it is the difference between keeping 70% of your subscribers and keeping 54%. That gap is your entire growth margin.
milosubscriptions includes built-in pause controls, cancellation surveys, and payment method management. The Failed Payment Retry add-on handles automatic retries so involuntary churn does not silently drain your revenue.
5 Subscription Models That Work for WooCommerce Stores
Subscriptions change that. Recurring revenue is predictable, easier to forecast, and compounds over time.
But “add a subscription” is vague advice. The model you choose determines everything: pricing, fulfillment, churn rate, and customer expectations. Here are five subscription models that work well on WooCommerce, with real examples of each.
1. Replenishment subscriptions
The simplest model. Customers need your product regularly, so you ship it on a schedule and save them the effort of reordering.
Works best for: coffee, supplements, pet food, skincare, cleaning supplies.
Why it works: the buying decision only happens once. After that, convenience keeps customers subscribed. Churn tends to be low because the product is genuinely consumed.
Pricing tip: offer a small discount (10-15%) over the one-time price. “Subscribe and save” is a proven framing that customers already understand from Amazon.
2. Curation and discovery boxes
You pick the products, the customer gets a surprise. Subscription boxes work because they turn shopping into an experience.
Works best for: specialty food, beauty, books, hobby supplies, wine.
Why it works: the surprise element creates excitement and social sharing. Unboxing content from customers is free marketing.
Watch out for: fulfillment complexity. Every box is a mini-project. Keep your SKU count manageable and plan your inventory months ahead. Churn is higher than replenishment because the novelty can wear off.
3. Access and membership subscriptions
Customers pay for ongoing access to content, tools, or perks rather than physical goods. This is the model behind most SaaS businesses, online courses, and membership communities.
Works best for: digital downloads, online courses, stock photography, premium content, private communities, software licenses.
Why it works: delivery costs are near zero. Margins are high. You can tier access levels to capture different price points.
Pricing tip: start with two tiers, not five. A basic and a premium plan is enough to learn what customers actually value before you add complexity.
4. Service subscriptions
Recurring services billed through WooCommerce. The checkout handles the billing; you handle the delivery offline or through integrations.
Works best for: maintenance plans, consulting retainers, managed hosting, cleaning services, tutoring.
Why it works: WooCommerce handles invoicing, payment collection, and renewal reminders. You focus on delivering the service. Customers get predictable billing instead of one-off invoices.
Watch out for: make sure your cancellation policy is clear upfront. Service subscriptions generate the most support tickets when customers feel locked in.
5. Hybrid: one-time products with a subscription option
Instead of creating separate subscription products, you add a “subscribe and save” toggle to your existing catalog. Customers choose between a single purchase or a recurring delivery at a discount.
Works best for: any store that already sells consumable or regularly purchased products.
Why it works: zero disruption to your existing catalog. You are not asking customers to change how they shop. You are giving them an additional option that benefits both sides.
Pricing tip: keep the discount modest. You are already saving the customer time and mental effort. A 10% discount on a product they were going to buy anyway is a strong offer.
Choosing the right model
Pick based on what you sell, not what sounds trendy:
- Physical consumables? Replenishment or hybrid.
- Unique/curated products? Subscription box.
- Digital goods or content? Access/membership.
- Professional services? Service subscription.
You can also combine models. A coffee roaster might offer replenishment subscriptions on their core beans and a curated discovery box for seasonal blends.
What matters more than the model
Whichever model you choose, three things determine whether it succeeds:
Make cancellation easy. Counterintuitive, but true. Stores that make cancellation hard get chargebacks, bad reviews, and support overhead. Stores that make it easy get customers who come back.
Watch your payment failure rate. Involuntary churn from expired cards and failed charges is the silent killer of subscription businesses. Automated retry logic recovers revenue you would otherwise lose without doing anything.
Talk to your subscribers. A monthly email with what is coming, what changed, or what other subscribers are saying goes further than any discount code. Subscribers who feel connected to the brand stay longer.
Starting a subscription store on WooCommerce? milosubscriptions handles the billing, lifecycle management, and customer self-service so you can focus on the product.