Implementing a system to block specific Ghost members

Long story short, we’re trying to implement a system for our Ghost site. It will enable us to block specific users from signing up (or from changing their email address to one that’s in our blacklist).

Unfortunately Ghost doesn’t have this feature, so I’m building a workaround. Does anyone have any ideas for how to achieve this?

Here’s the solution I’ve thought of so far:

  • the member.added webhook triggers a cloud function, which checks to see if the added user is in the blacklist. If it is, it will delete them from Ghost, and send them an automated email saying they’ve been blocked
  • the member.edited webhook will do the same thing as above

We aren’t using a custom theme with a custom sign up process, so I can’t do this on the front-end, since we’re using the Ghost portal plugin (which I can’t edit the code for).

This is obviously a hacky solution, but I haven’t thought of any better ideas. Does anyone else know a way to achieve this?

1 Like

It’s not actually all that tough to edit the portal code, if doing so would be a better option for you. (You can fork it from here: GitHub - TryGhost/Portal: Drop-in script to add membership features in a Ghost theme )

But having said that, I’m going to point out the obvious issue here: Email addresses are free and easy to get. How will blocking a specific email address serve your purposes? It’s presumably about the user attached to the email, not the email itself, right? Won’t the problem user just get another address and use that?


Thanks, how exactly do I make sure this script doesn’t run twice? Because right now I’m not sure where this script is included in my theme, so I don’t want to include it twice.

Regarding blocking emails being effective, sure, they can make another email. But if they try and sign up again and see they’ve been blocked, I expect most of these people won’t bother trying. That’s what happened when we were using Patreon - we never heard from those people again.

It’s not perfect, but it’s better than nothing. I expect it to intimidate any troublemakers from trying to sign up again.

Hey there @dspacejs - I wouldn’t call your proposed solution “hacky” at all - webhooks and the API are the non-hacky way of integrating with Ghost, specifically because it keeps your code independent of Ghost’s, so there’s no re-applying your changes every time we ship new code (which is all the time).

However, if you do want to build a custom version of Portal, the way to replace it would be through config:

1 Like

Thanks Hannah, the config is exactly what I was trying to find. There’s a problem though:

For self-hosted Ghost users, a custom configuration file can be used to override Ghost’s default behaviour. This provides you with a range of options to configure your publication to suit your needs.

I’m not self-hosting Ghost; we’ve already paid for hosting from So this isn’t really an option, unless it’s possible to edit the configuration for sites. But I don’t see that article mention this.

Yes, I was thinking it may be a bit of a pain to have to regularly update my forked @tryghost/portal code. However, I don’t expect to make a tonne of changes, so I imagine it’d be pretty straightforward to perform merges and I’d only have to do this every now and then.

The advantage to this approach is I’ll be able to easily make front-end changes for the portal, instead of being restricted to back-end changes with the webhooks.

There are some cases where I can see only having a back-end solution being an issue. For example, what if the blocked user signs up straight away with a premium tier, and has already paid for it with their card.

That means I’d have to programatically refund them in the webhook script, or alternatively, manually refund them later. This isn’t ideal–I want to prevent them from being able to make a payment in the first place.

Of course, another solution would be to block their email address on Stripe’s end too, so once they enter the Stripe checkout, they can’t proceed. But AFAIK that’s not possible, because the only way I’ve seen Stripe lets you block users, is to mark certain users as fraudulent (but this isn’t technically true, we’re not blocking them from fraudulent activity, but for other reasons). So I don’t think that solution would be appropriate.

Therefore because of the above logic, I thought it’s probably going to be best to just fork your @tryghost/portal code and have a front-end blocking feature, which will prevent them from being able to sign up at all (instead of the webhooks, which block/remove them after they’ve already signed up as a free/paid member).

But let me know if you have any better ideas. Thanks.