What a course plugin has to do before the first refund
Course plugins are compared on quizzes and drip. The decision is where the video lives, how access is revoked, and what a refund does to an enrolment.
Ana Ferreiro · @aferreiro
WooCommerce engineering
- Topic
- WOO
- Section
- WooCommerce & Storefront
- Published
- 17 OCT 2026
- Reading time
- 9 MIN
- Words
- 2087W
Fourteen months after the first sale, a store refunds a course. The order flips to Refunded, the receipt goes out, the money returns to the card, and the student can still open every lesson, because the enrolment came from a plugin that listens for a cancelled order and this order was never cancelled.
The lessons are unlisted YouTube embeds and the links are in the welcome email. Refunding an order cannot revoke a URL that is already in somebody's mailbox.
Neither failure is on a comparison page. Course plugins get compared on quizzes, drip schedules and certificates, the visible part of the decision and the part that matters least. What decides the outcome is three things: where the video lives, how access is revoked, and what a refund does to an enrolment.
The video comes first because it sets a ceiling. A plugin controls a template and a capability check, not a file it hands to a browser.
Revocation comes down to where the grant is stored. An enrolment derived from the order at check time survives a refund for free; one copied into a table or a role needs something to delete it.
A refund has four shapes, and only some of them change the order status a plugin is watching.
Disclosure: some links on this page are affiliate links, and WPSifero may earn a commission if you buy through them. That does not change the price you pay, and it does not change what this piece recommends: the hosted platform below is named as the right answer for one case, and the section on when not to buy names five situations where nothing should be bought.
Where the video lives decides what revocation means
Four arrangements are common, and only the last makes revocation complete.
- Unlisted YouTube or Vimeo. The embed URL is in the page source and in every email that carried a lesson. Unlisted is a search visibility setting, not an access rule.
- Vimeo with domain-level embed privacy. Closer. The player refuses to run elsewhere, but the file URL still exists and a player with downloads enabled hands it over.
- A file in
wp-content/uploads. The weakest and the most common. A<video src>at a predictable path is a public URL in a folder WordPress serves to anyone. - Signed playback URLs. A token with an expiry, generated after the access check. The only arrangement where ending access also ends the file, because the URL dies on its own.
The free option is the first, and it is genuinely enough for a first course sold to a named cohort. Material taught elsewhere does not need a protected pipeline; what marks the end is whether a refunded student kept watching.
One check takes a minute: open a lesson, view source, copy the media URL, paste it into a private window. If it plays, no work on the refund path will help.
How access is revoked, and why the grant matters more than the revoke
Two designs are possible, and no plugin page says which one it uses.
The derived design computes access on every check: does this user have an order in a granting status, containing a product mapped to this course, inside the window that order bought? Nothing is written at purchase, so the refund needs no handling. It costs a query per page view and cannot drift.
The granted design writes a row, a role or a meta key at purchase, which makes every other feature easier. It is fine as long as revocation exists. The failure is that the copy outlives the thing it was copied from.
One detail stays invisible until the first revocation. A role change does not end a session, because WordPress keeps the user logged in through an auth cookie, so revocation has to be evaluated at request time; a plugin that checks only on the archive leaves the lesson URLs open.
Four ways to sell a course, and what each one takes responsibility for
The four are presented as interchangeable. They divide the work differently, and the division outlives the launch.
A course plugin on top of WooCommerce
Content, lessons, quizzes, progress and certificates live in the course plugin. Cart, tax, gateway, invoices, refunds and renewals stay in WooCommerce. The seam is one product-to-course mapping and one rule about granting statuses.
This is the right default for a store that already sells something else, because the money stays where it knows how to come back from. The first refund is where it breaks: the plugin grants on completion and revokes on cancellation, and a refund is not a cancellation; a partial refund leaves the status alone. Sensei LMS, Automattic's course plugin, is worth looking at first not for its features but because the access rule is WooCommerce's, so there is one source of truth for who bought what.
The year-two failure is the subscription. A recurring course leaves the original order completed forever, so a check reading only order status grants access after a failed renewal. Sell annual access and test a failed renewal first.
The free option is real: WooCommerce is free, and Sensei's core plugin runs one course with lessons, quizzes and manual enrolment. Paid tiers buy drip, prerequisites and reports. Find out what the free core cannot do before paying.
A hosted platform embedded in the site
Here the platform owns the money, the video, the access, the refund and the dispute. WordPress owns the sales page.
The failure is the half-measure: WooCommerce takes the payment and the platform hosts the video. Two systems, half an entitlement each. The refund happens in WooCommerce, the order flips, and the platform never hears, because nobody built the webhook. Worse in reverse: refund in the console, access ends, WooCommerce untouched, and the books disagree with the student record.
A hybrid with webhooks both ways costs a small plugin to maintain: the seam work without the control.
A membership plugin
A membership plugin sells a level, and a level is a rule about who may see what. One purchase covers a course page, a forum, a library and a monthly call, which suits a course that is one item inside something larger.
The failure is that a level is not an enrolment. A refund cancels the membership and the pages vanish, but the progress rows, quiz attempts and certificate stay keyed to a user who is now a stranger; buy again in six months and the plugin may resume them at lesson nine or refuse a second attempt.
Membership plugins are also where revocation looks solved and is not. The level goes, the page hides, and the video URL from last week's email still works. The free option is WordPress itself: a role, a capability check and one protected page hold a single cohort enrolled by hand.
A learning-management plugin that handles payment itself
Some LMS plugins bring a checkout of their own: one system, one refund screen, one access rule, no seam.
What that buys is a second commerce system. Tax classes, invoice numbering, dunning, payment methods and the reports the store trusts live in WooCommerce, and the LMS has a thinner version of each. The first-refund failure is recording rather than access: the refund is correct and leaves no order in WooCommerce, so the month's revenue exists only in the LMS report and the export is assembled by hand. A store selling only courses can live with that; one selling a book and a course cannot.
When the hosted platform is the right answer
One course, no technical team, and no intention of integrating anything: buy the hosted platform and stop there.
The four-way comparison is a comparison of seams, and this is the only option with no seam to build. One vendor owns the payment, the video, the access, the refund and the dispute, so every failure above becomes that vendor's problem. Checking that vendor once is a morning's work, not a quarter's maintenance.
The free version of that decision is one free LMS plugin, a cohort sold by invoice and a shared folder, which is enough until the course outgrows people who can be named.
What the store gives up: the recurring line grows with students, the video sits on a domain it does not control, the design is the platform's templates or an embed, and leaving means exporting a student list and rebuilding the course. For one course with a few hundred students that is fine; for twelve courses sharing a checkout with physical goods, it is not.
The check before committing: buy with a real card, request a refund the way a customer would, and watch how long access survives.
The first refund, walked through
Four events can take money back, and they do not look alike from inside WordPress.
- A refund from the order screen. The order moves to Refunded when the refund is full and the refund hooks fire. Whether access ends is now a plugin question; a derived check needs no listener and denies on the next page load.
- A refund from the gateway dashboard. The money is gone the moment it is issued. Whether WooCommerce learns depends on the gateway's webhook; in plenty of stores the order quietly stays Completed and the student keeps the course.
- A partial refund. WooCommerce leaves the order Completed because most of the sale stands, so access survives. That is usually right, and it should be a written policy rather than an accident.
- A chargeback. Not a refund: a dispute opens, the money leaves immediately, and the order does not change. Nothing in the typical stack revokes; access ends when a person reads the email.
Revoking the enrolment is the smallest part. The list also runs through the user's session, the video platform's entitlement, the drip sequence in the mail tool, the community group, the certificate and the progress record. A removed student still gets lesson four tomorrow if the mail tool holds its own list.
The extensions sold through WooCommerce's extension marketplace are where most of these integrations come from, and the thing to read is the changelog rather than the feature grid. One that has fixed a refund-revocation bug has thought about it; one that never mentions refunds has not.
Whether revocation is instant is a policy question. Ending access when the refund lands is consistent; a week is generous. Either works if the terms say which, and finding out during the first dispute does not.
When not to buy any of this
- No course has sold yet. Sell the first cohort by invoice, a protected page and a mailing list; an entitlement system is for the second cohort.
- The content is four PDFs and a monthly call. A membership plugin or a password-protected page is the whole product.
- The video is the product. Fix where it lives first; a plugin bought to protect a public file buys a support ticket.
- The catalogue must share a checkout with physical goods. A hosted platform looks simple until two sets of orders are reconciled by hand.
- There is no staging site. The refund test revokes somebody's access, and on production that somebody is a real student.
The decision rule
Feature comparisons are written to be compared with each other, which makes them a poor basis. Four facts decide it: whether the store already sells something in WooCommerce, how many courses there will be, whether anyone can maintain a webhook, and whether the video is the asset.
- Sells anything else in WooCommerce. A course plugin on WooCommerce, access derived from the order, video behind signed URLs. One checkout, one refund path.
- One course, no technical team, nothing to integrate. The hosted platform, and then leave it alone. No half-integrated checkout behind it.
- Courses as one item in a library. A membership plugin, one level per library, and a written decision about progress records.
- Only courses, no other products, one screen wanted. An LMS with its own payment, accepting that the accounting export stays manual.
Whatever the answer, run three checks before paying. Buy one course with a test card. Refund it from the store admin, then from the gateway dashboard. Open a lesson URL in a private window. An afternoon of that answers more than the feature list, and the store finds out in October rather than the month a customer keeps the course after a refund.
The container's job is not to teach. It is to end access when the money goes back, and to know which of those two things happened first.
Ana Ferreiro · @aferreiro
WooCommerce engineering
Covers the WooCommerce order lifecycle: checkout, HPOS, session handling, transactional email and the post-purchase layer where most storefront complaints actually originate.
Continue