GumPress

Gumroad licensing for WordPress products. No server required

Visit Website
August 18, 2026 I gave away the hard part of my SaaS for free, and it's the whole distribution strategy

I wanted to sell WordPress plugins. Like a lot of people in this niche, I wanted to sell them through Gumroad, because they handle checkout, VAT and refunds and I don't want to run a store.

Then I went to add Gumroad licensing, and found a hole.

Gumroad's /v2/licenses/verify endpoint returns success: true for a purchase that has been refunded, charged back, or disputed. That success simply tells you the HTTP request suceeded. The refund status is in the response, but it's in a different field, and you have to check a combination of different fields to figure out if the license is actually valid.

There's a second one. Gumroad has a "uses" counter that looks like seat enforcement: cap a license at N activations. But it counts verification calls rather than installations, so it only ever goes up. There's no way to release a seat without a seller access token, which a plugin you've distributed obviously can't hold. A fresh database reads as a brand new site. And the increment itself is a flag the client sets - anyone willing to open one file can buy one seat and run it on a thousand sites.

It's a courtesy counter. Plenty of people ship it as if it were enforcement.

So I built GumPress. It's two things, and the split is the whole business model.


The free part

The shim is an MIT-licensed folder you drop inside your own plugin's directory. Two lines of PHP - require the shim, register the plugin:

require_once DIR . '/gumpress/gumpress.php';
Gumpress::register(__FILE__, 'your-gumroad-product-id');

That gets you a license screen, a row action on the plugins table, refund/chargeback/dispute validation on every check, subscription handling that doesn't brick someone's site the moment a card fails, and a GumPress::valid() call to gate whatever you want.

No account with me. No API key. No webhook. No OAuth. By default it talks straight to api.gumroad.com and nothing phones home anywhere else. It is genuinely, permanently useful without me existing.

That last part is deliberate, and it took me a while to be comfortable with it.

The paid part

The shim can't do real seats - for the same reason Gumroad can't. Enforcement needs server-side state that the client isn't allowed to control. So there's a hosted licensing server, and switching to it means changing one configuration property - the license check URL. That's the entire migration. Still no account linking, still no webhook, still nothing to import.

What you get for it: per-domain seats you can actually see and release, self-hosted updates, and config push - you can change a license's seat limit in a dashboard and the live site obeys it on the next check, without shipping a plugin update. That last one is the feature people react to, because the alternative is asking thousands of users to upgrade in order to change a number.

Pricing: free tier, then $9 / $29 / $69 a month. Metered on active seats - a single domain that's checked in within the last 90 days. Not lifetime sales, so the number goes down when sites go quiet.

The part I actually want to talk about

The shim is the distribution channel. It gets bundled inside other people's plugins and shipped to their customers. Every install is a copy of my code sitting in a codebase I don't control, doing something useful, permanently. I cannot buy that kind of distribution, and I certainly can't buy it for the price of one HTTP call every twelve hours.

Which is why the free tier is real rather than a trial. My closest competitor in this niche has no free plan at all - 30-day trial, then pay. They've been at it since 2016, so I assume they've tested it. I went the other way on purpose: the people who never convert are still carrying my code into places I'd never reach.

The wedge is narrow and I think that's fine. Everyone in this space asks you to migrate - move your products, connect your store, import your customers. I ask you to change a URL. If I disappear tomorrow you change it back and nothing breaks. I put that on the pricing page, above the plans, because "what happens if you shut down" was the first question I'd have asked.

What I don't know yet

A few things I'd genuinely welcome opinions on:

  1. Roughly half my potential audience distributes a free version through the WordPress.org repo and only gates pro features. Those devs get their update channel for free from wordpress.org, so most of my paid tiers are irrelevant to them - they're capped at the cheap plan forever. I'm not sure whether to build for them or accept that my revenue comes from the other half.

  2. Free tier is 50 active seats. That's roughly a developer with 30-40 paying customers. I keep going back and forth on whether that's generous enough to be a real hook or so generous that nobody ever needs to leave.

  3. I have no defence against someone with two plugins making two free accounts. I decided the friction of running two dashboards forever is its own punishment and moved on. Tell me if that's naive.


Video walkthrough, clean WordPress install: https://youtu.be/hK9RDztTg-Y
Shim source: https://github.com/avramovic/gumpress

Happy to go into any of it - including the parts I've probably got wrong.

3 Comments

  1. 1

    The free shim being genuinely useful without GumPress is an unusual choice. It makes the distribution mechanism part of the product itself, rather than just a free version of the paid product.

    1. 1

      Right. The shim has to be worth installing even if I never build anything else. If it only made sense as a lead magnet, nobody would bundle it in their own product, and bundling is the whole distribution.

      1. 1
        That makes sense. The fact that the shim has to stand on its own for the distribution model to work is what makes the strategy interesting.

About

I want to make licensing WP plugins and themes sold on Gumroad hassle free for developers.