Setting Up Listener Support (Stripe Mode)
Stripe mode lets listeners donate directly on your site via an embedded payment form — no redirecting to an external platform, no separate account required for them. Payments are processed through your connected Stripe account and recorded automatically after payment_intent.succeeded confirms.
Donations are never taxed. Turning on Calculate tax automatically in Settings → Payments, or Stripe Tax in your Stripe account, adds tax to built-in membership subscriptions only.
1. Connect Stripe
You need a Stripe account and a pair of API keys first — see Your Stripe Account and API Keys for how to get them, and for test mode, test cards, and the live-mode switch. That page covers the Stripe-side half; this section covers where the keys go.
Go to Benecaster → Settings → Listener Support and enter your Stripe publishable key, secret key, and webhook secret.
These are your site-wide Stripe keys, and they are the same keys Settings → Payments edits — saving in either place is reflected in the other. This panel shows a single key pair: whichever set is currently active. To switch between test and live, or to enter both sets at once, use Membership → Payments, which is the only screen with the mode toggle.
Benecaster displays a read-only webhook endpoint URL with a copy button. Register that URL in your Stripe Dashboard under Developers → Webhooks, subscribed to two events:
payment_intent.succeededpayment_intent.payment_failed
The first records the donation. The second is what lets Benecaster warn you when donations start failing in bulk — see Watching for card testing below. Subscribe to both.
A webhook without payment_intent.payment_failed still takes donations perfectly well, so nothing looks wrong. What it cannot do is count failures, which means the decline warning can never fire on that show no matter what happens to it.
If you also run built-in membership, add its events to the same endpoint rather than creating a second one. Connecting Stripe lists them.
Benecaster checks the endpoint once a day. On a show taking donations through Stripe in live mode, it reads the webhook endpoints on that show’s Stripe account and shows an admin notice when no endpoint points at your site’s webhook URL, when the endpoint is disabled, or when it is missing either of the two events above (or a built-in membership event, if the show also uses built-in membership). The notice names the problem, links to Stripe’s webhooks page, and clears itself at the next daily check once the endpoint is fixed. Test mode is not checked.
Use the Test connection button to verify your keys before going live. It creates and immediately cancels a $0.50 PaymentIntent, so nothing is charged.
Your secret key, webhook secrets and Turnstile secret are stored encrypted. Regenerating your WordPress salts does not affect them.
2. Enable Listener Support
On the same settings page, toggle Enable Listener Support on. This arms the feature — the prompt won’t appear until a show is also configured.
3. Configure Per Show
Open the show’s settings under Benecaster → Shows → [Your Show] → Listener Support.
Per-show Stripe keys are no longer set here. They moved to their own tab, Shows → [Your Show] → Settings → Payments, because they are not a donations setting: the same keys govern that show’s subscriptions, buy-ups, and the Products Benecaster creates in Stripe. Choosing a Stripe account for a show is a decision about where all of that show’s money lands — see Connecting Stripe for Subscriptions. The settings below are the donation form’s appearance and behavior only.
| Setting | What it does |
|---|---|
| Donor name | Whether to collect the donor’s name. Optional. |
| Donor email | Whether to collect the donor’s email. When collected, a thank-you email is sent automatically after payment confirms. |
| Donor message | Whether to show a free-text message field for the donor. |
| Thank-you message | Text shown to the donor after a successful payment. Supports {amount_formatted}, {amount}, {currency}, and {donor_name}. |
| Redirect URL | Instead of a thank-you message, redirect to a URL after payment. Benecaster appends ?donation=<intent_id> so the destination page can confirm success. |
| Donor mailing-list opt-in | When enabled, a checkbox appears on the donation form between the Payment Element and the submit button. Off by default. See Donor Mailing-List Opt-In below. |
Donation Amounts
At the bottom of the show’s Listener Support tab is Donation amounts (Stripe mode) — the currency, the buttons a supporter sees, and what the form will accept if they type their own figure. These control the Stripe donation form only; they have no effect on link-mode prompts, which just send people to a page you control.
| Setting | What it does |
|---|---|
| Currency | Three-letter ISO code — USD, GBP, EUR, JPY. |
| Suggested amounts | The preset buttons, comma-separated. Up to six, shown in the order you list them. |
| Custom amounts | Whether supporters may type their own figure instead of picking a button. |
| Minimum custom amount | The smallest figure a supporter may type. Default 100. |
The panel is in two halves. The top half sets the values for your whole site; below it, Override donation amounts for this show switches that show onto its own. Both halves live on each show’s tab, so it is worth reading the heading before you save — editing the top half from inside one show’s settings changes every show that has no override of its own.
Amounts are in the smallest currency unit
Every amount here is entered in the smallest unit of your currency, not in whole units. In USD that means cents: 500 is $5.00. In a currency with no subdivision it is the unit itself — 500 in JPY is ¥500.
You do not have to do the arithmetic in your head. The screen shows the formatted equivalent as you type, so 500 displays as $5.00 next to the field. If that preview does not say what you expect, the number is wrong.
The minimum applies only to typed amounts
Your own suggested amounts are always accepted, even one below the minimum. The floor exists to stop a supporter typing a figure too small to be worth processing; it was never meant to overrule a button you chose to offer. So a show with a $25 floor and a $3 suggested button keeps taking $3 through that button, deliberately.
If you want a suggested amount gone, remove it from the suggested list. No minimum will do it for you.
Zero means “no floor of mine”
Setting the minimum to 0 removes your floor. It does not mean any amount goes through — Stripe enforces its own per-currency minimum of roughly $0.50 underneath, and a donation below that is refused by Stripe whatever you set here.
A very low floor is also what card testers probe with, since the cheapest charge is the most useful one to test against. That is worth weighing before you set it to zero — though as the next section explains, the floor only raises the cost of an attack and is not what detects one.
4. Place the Shortcode
Add [benecaster_listener_support] to any page or episode template. Three display styles are available:
| Style | What it renders |
|---|---|
form |
Stripe Payment Element embedded inline on the page |
button |
A styled button that opens a modal with the Payment Element |
icon |
An SVG icon (heart, star, mic, or custom URL) with a caption that opens a modal |
<!-- Inline form -->
[benecaster_listener_support show_id="3" style="form"]
<!-- Button style in a sidebar -->
[benecaster_listener_support show_id="3" style="button" label="Support the show"]
<!-- Icon style with custom label -->
[benecaster_listener_support show_id="3" style="icon" icon="heart" label="Leave a tip"]
Always include show_id on standalone pages — outside a show or episode page context, the shortcode cannot resolve the show automatically and renders nothing.
The Blocks & Widgets Library add-on wraps this shortcode as a Gutenberg block and Elementor widget with a style picker in the sidebar.
5. Auto-Injection
If you prefer not to place the shortcode manually, Benecaster can inject the prompt automatically into episode pages and the subscriber account page. The default_stripe_style setting (per show) controls which style is used for auto-injection — default is button.
Donor Mailing-List Opt-In
When the Donor mailing-list opt-in toggle is enabled for a show, the donation form shows an unchecked checkbox between the Payment Element and the submit button:
☐ Add me to {Show Name}‘s mailing list
The checkbox is unchecked by default — donors must actively opt in. If the donor checks it and the payment succeeds, Benecaster creates a free follower account for that email address. This gives the donor access to your public follower feed and adds them to your subscriber list in Benecaster.
When accounts are created — and when they aren’t:
- A new follower account is created only when no WordPress user already exists for the donor’s email address.
- If a WP user already exists at that email — whether they are a paying subscriber, a canceled subscriber, an existing follower, or any other status — no follower account is created and their membership is not touched.
This means enrolment is additive only: it brings in genuinely new contacts, and podcasters don’t need to worry about accidentally overwriting a paying subscriber’s account.
Ticking the box also records marketing consent for the show, for new and existing accounts alike: a yes, with the checkbox’s own label stored as the wording the donor agreed to, and donation as where it came from. The address on a donation is typed, so the answer is stored as unconfirmed unless the donor was signed in to that account while donating. An unconfirmed answer never replaces a confirmed one. See Marketing Consent.
GDPR note: The checkbox is unchecked by default and the toggle is off by default. Podcasters must explicitly enable it per show. Donors must actively check the box before any account is created.
For developers: The benecaster_donor_enrolled_as_follower action fires after a new follower is provisioned. Use it to push the contact to an external newsletter platform or CRM. The action does not fire when an existing user is skipped.
add_action( 'benecaster_donor_enrolled_as_follower', function( $user_id, $show_id, $donation_reference ) {
// $donation_reference is the Stripe PaymentIntent ID
}, 10, 3 );
See Listener Support Hooks for the full hook reference.
Thank-You Email
When a donor provides their email address, Benecaster queues a donation_thank_you email after payment_intent.succeeded confirms. The email template is editable in Benecaster → Emails → donation_thank_you. Available merge tags: {donor_name}, {donor_message}, {donation_date}, {show_name}, {donation_amount}, {donation_platform}. Tags for fields the donor left blank render as an empty string.
Health Check
If Listener Support is enabled but no Stripe keys are configured anywhere — neither site-wide nor on any single show — Benecaster surfaces a warning notice in the admin. The notice re-surfaces weekly until resolved, or until you untick Settings → Listener Support → “I plan to use Listener Support on this site” — the way to silence it if you’re running link mode and never intend to connect Stripe.
“Anywhere” is the operative word: if you run every show on its own Stripe account and have no site-wide keys at all, that is a supported setup and the reminder stays quiet. See Notifications for how notices work.
Bot Protection
Settings → Listener Support → Bot Protection adds an optional Cloudflare Turnstile challenge to the donation form. It is off by default and most shows will never need it; turn it on if your form is being hit by automated submissions.
You register your own Cloudflare site
Turnstile keys are issued per domain, so there is no key Benecaster can supply — you create your own at Cloudflare and paste the pair in. The fields being empty on a fresh install is the expected state, not a fault.
- Sign in at Cloudflare and open Turnstile.
- Add a site for your domain. Cloudflare issues a site key and a secret key.
- Paste both into Settings → Listener Support → Bot Protection and save.
The secret follows the same rule as the other secrets on that screen: once saved, the field shows (saved — leave blank to keep current) and loads blank. Type a new value to replace it, or whitespace to clear it.
Both keys, or it stays off
Protection is on only when both keys are saved. Save just one and Turnstile does nothing at all: a red warning appears on the settings screen, and your donation form keeps working exactly as before.
That is deliberate. The alternative — refusing donations because a setting is half-filled — turns a mistyped paste into a silent revenue outage. A half-configured install therefore behaves as if the feature were off, and says so on screen rather than in your Stripe dashboard a week later.
Once both keys are in, the challenge does fail closed: a visitor who cannot complete it, or a Cloudflare outage, means the donation is refused. A challenge that waves traffic through when it cannot check anything would not be a challenge.
Staging sites need their own keys
Keys are bound to the domain you registered at Cloudflare, so your live keys will not validate on a staging copy. Cloudflare publishes testing keys that always pass — use those on staging and keep the real pair for production.
Bot Protection is site-wide. One Cloudflare site covers the domain, so there is no per-show setting.
Protecting Against Card Testing
A donation form is a public payment surface: anyone can reach it, and no account is needed. That is the point of Listener Support, but it also makes it attractive to people testing stolen card numbers. They submit a long run of small charges to find out which cards still work, and they do not care whether the payments succeed.
The cost lands on your Stripe account, not on your site. The charges run through your account, so the declines, the disputes that follow, and any account review are all yours. A burst of declines hurts your authorization rate, and Stripe can place an account under review over it. Benecaster is not in that blast radius, which is exactly why the settings below are not where this problem gets solved.
Stripe Radar is what actually detects an attack
Radar’s baseline protections are included with every Stripe account. In your Stripe Dashboard, open the Radar settings and confirm the built-in card-testing rules are active. Radar recognizes the pattern — many attempts in a short window, small amounts, shared characteristics across cards — and blocks it before the charges reach your balance.
Nothing on the Benecaster side does that. Everything below raises the cost of an attack; none of it recognizes one. A show running with all of it configured and Radar switched off is not protected, and that combination is how podcasters end up with a dispute problem they did not see coming.
What Benecaster does on its side
- The donation endpoint has its own rate limit — 10 payment attempts per five minutes from any one visitor. That is roughly thirty times tighter than the general limit it used to share with every other endpoint, and it absorbs normal use comfortably: a donor creates one attempt, sometimes two or three if a card declines or they change their mind.
- A typed amount below your minimum is refused before Stripe is contacted at all. See Donation Amounts above.
- Turn off custom amounts if your suggested amounts cover what you need. Only the amounts you configured are then accepted, which removes the ability to probe with the smallest charge Stripe will take.
- Set your suggested amounts above the minimum. Card testing favours the smallest charge available, so a lowest tier of $5 is a less useful target than one of $1.
- Bot Protection stops the automated submissions that make a long run of attempts cheap in the first place.
Watching for card testing
Benecaster watches your decline rate for you. When a show gets at least 10 donation attempts in 24 hours and 40% or more of them fail, a warning appears in your notification bell naming the show and the numbers, with a button through to Stripe Radar.
The warning clears itself once the rate falls back — it is not a badge you have to dismiss, which is what makes it worth trusting when it does appear.
Two things this warning cannot tell you.
It depends entirely on your webhook being subscribed to payment_intent.payment_failed. Failures are the only thing feeding the counter, so a show whose webhook omits that event records nothing and can never warn, however badly it is being attacked. A quiet notification bell on such a show is not a clean bill of health — it is the absence of any information at all. If you are unsure, check the webhook first.
And a declined attempt appears in no donation report anywhere in Benecaster. Your donation history is money received, deliberately, so failures are not listed there and never will be. The notification and your Stripe Dashboard are where declines are visible.
Watch your decline rate rather than your dispute rate. Card testing shows up as a sharp rise in failed payments days before any dispute is filed, and that is the point at which it is cheap to deal with.
Donor Data Retention
In Settings → Listener Support, the Donor data retention field sets how long donor records are kept (in days). Set to 0 to retain records indefinitely.
See Also
Need this built rather than just documented? See our services →