Listener Support Hooks and Shortcode Reference
Developer reference for the Listener Support system. Full documentation for each hook and shortcode — parameters, return types, and usage examples — lives in the dedicated CPT entries linked below.
A note on amounts
Every amount passed through a Stripe-mode hook is an integer in the smallest currency unit — 500 is $5.00 in USD, and 500 is ¥500 in JPY. None of them is a float in major units.
This matters more than it sounds. A guard written as $amount >= 5.00 compares 500 against 5.00, passes, and admits a 50-cent donation through what its author believed was a $5 minimum. Nothing warns you: the filter runs, returns a value, and the donation succeeds. Read the currency from the settings rather than dividing by 100, because minor units are not hundredths in every currency.
The exception is benecaster_donation_received, which fires from the webhook after payment and receives a float in major units. The two conventions coexist deliberately — the webhook reports settled money, the intent-side hooks handle a submission — so check which side of the payment you are on.
Filters — prompt and display
| Hook | Description |
|---|---|
benecaster_listener_support_enabled |
Controls whether the Listener Support prompt renders for the current request. Return false to suppress. |
benecaster_listener_support_output |
Filters the fully rendered HTML of a Listener Support variant before it is returned to the caller. Fires even when the output is empty. Its arguments are ( $html, $style, $show_id ) on both the link and Stripe paths — $show_id is 0 when there is no show context, so don’t type-hint the third argument as an array. |
benecaster_listener_support_button_label |
Filters the button label text. |
benecaster_listener_support_message |
Filters the message body text. Returning an empty string hides the message element. |
benecaster_listener_support_button_position |
Filters the corner anchor for the floating-button variant. Accepts bottom-right, bottom-left, top-right, top-left. |
benecaster_donor_enrollment_label |
Filters the label on the donor mailing-list opt-in checkbox. |
Filters — donation amounts (Stripe mode)
| Hook | Description |
|---|---|
benecaster_donation_suggested_amounts |
Filters the preset amount buttons — int[], minor units. This filter owns the buttons, and it is the only thing that does. |
benecaster_donation_minimum_amount |
Filters the floor a supporter’s typed amount must clear, per show. The supported way to enforce a donation minimum. |
benecaster_donation_amount |
Filters the amount immediately before it is sent to Stripe. Changes what the supporter is charged without telling them — not a way to enforce a minimum. |
The minimum can never veto a show’s own suggested amounts, and no filter can make it. Benecaster matches the suggested list first, deliberately: a floor that could disable a button the podcaster can see on their own page would fail with the explanation nowhere. To remove a suggested amount, remove it with benecaster_donation_suggested_amounts.
Filters — donation flow (Stripe mode)
| Hook | Description |
|---|---|
benecaster_should_create_donation_intent |
Blocks PaymentIntent creation. Runs after amount validation and before Stripe is contacted. Takes four parameters — a callback declaring three silently never receives the currency. |
benecaster_donation_decline_alert_thresholds |
Tunes the per-show decline-rate warning. Both halves matter — see below. |
benecaster_donation_confirmation_message |
Filters the thank-you message HTML on the confirmation screen. |
Filters — recording a donation report
| Hook | Description |
|---|---|
benecaster_listener_support_accept_donation |
Runs before a donation report sent to POST /listener-support/donations is written. Return false and nothing is recorded, benecaster_listener_support_donation_logged does not fire, and the caller gets 403 donation_rejected. $submission carries show_id, platform, canonical_platform, verified, user_id, donor_email, amount (major units), currency, reference, note, display_name and donated_at (UTC). See the recipe Refuse fake donation reports. |
Actions
| Hook | Description |
|---|---|
benecaster_before_donation_form |
Fires during shortcode rendering, immediately before the donation form markup. |
benecaster_after_donation_form |
Fires immediately after the donation form markup. |
benecaster_donation_received |
Fires on payment_intent.succeeded after the donation is recorded and the thank-you email queued. The donation is already committed — not a place to prevent recording. |
benecaster_donation_payment_failed |
Fires on payment_intent.payment_failed for a donation. The only way to observe a declined donation — see below. |
benecaster_before_donation_confirmation |
Fires before the confirmation screen HTML. |
benecaster_after_donation_confirmation |
Fires after the confirmation screen HTML. |
benecaster_listener_support_donation_logged |
Fires after a link-mode donation reference row is written. Use to sync records to a CRM, send a Slack notification, or trigger any follow-up process. The row is already written: to stop one being recorded, use benecaster_listener_support_accept_donation below. |
benecaster_donor_enrolled_as_follower |
Fires after a donor who opted in is provisioned as a free follower. Does not fire when an existing user is skipped. |
benecaster_donor_data_erased |
Fires whenever donation records are anonymised (identity cleared, amount and date kept; no row is removed): from the donor’s own erasure request, from Tools → Erase Personal Data, and when a WordPress account is deleted. Carries the email and the number of rows anonymised, and fires with a count of 0 too, so check the count. |
On the two confirmation actions, $amount is always 0.0. The screen is rendered before any amount is known, so the parameter is a placeholder rather than the donation’s value — use benecaster_donation_received when you need the real figure.
Observing declined donations
benecaster_donation_payment_failed is the only way to see a declined donation anywhere in Benecaster. No failure row is written to any table: the donations table is money received, and every reader of it — the admin donation list, the dashboard panel, the Analytics Dashboard add-on — would count a failure row as a donation. There is no failure table and none is planned, so a decline not captured at this action is not recoverable afterwards.
Two conditions govern whether it fires at all. It ignores any Stripe intent without a show ID in its metadata, so membership and buy-up failures on the same Stripe account never reach it. And it depends on the show’s Stripe webhook being subscribed to payment_intent.payment_failed — a show missing that event produces no declines, no counters and no warning, so silence there is absence of data rather than health.
When tuning benecaster_donation_decline_alert_thresholds, keep min_attempts rather than filtering on rate alone. One genuinely expired card on a quiet day is a 100% decline rate, and an alert that fires on that is one the podcaster learns to ignore. Benecaster clamps the floor to a minimum of 1 for that reason.
Neither hook detects card testing. They raise the cost and report the shape; Stripe Radar’s card-testing rules are what recognise an attack, and they live on the podcaster’s own Stripe account.
Shortcode
| Shortcode | Description |
|---|---|
[benecaster_listener_support] |
Renders a Listener Support prompt. Supports link-mode and Stripe-mode styles. Available on all plans including free. |
See Also
Need this built rather than just documented? See our services →