Skip to main content

benecaster_promote_grace_length_days

Filter Premium

Varies the grace-period length, in days, for one transferred subscriber at the moment it is set — so the length can depend on tier, billing interval or the individual subscriber rather than being the single number the Promote to Bridge wizard collected. Runs once per transferred row during the promotion run.

Returning 0 does not mean “no grace period”. The value is floored to one day after the callback returns, deliberately: a zero would write a deadline in the past and the daily expiry cron would revoke that subscriber on its very next tick — cutting off the person being migrated. If someone should not get a grace period, do not promote them.

It applies to the initial set only, never to Extend. The number typed into the Promotion History panel is used as typed; filtering it would make the panel report a change it did not make.

The wizard’s result payload reports the baseline, not the outcome. grace_period_ends_at in the run response is calculated from the number the podcaster typed, so with this filter in play individual rows will differ from it. Read promote_grace_period_ends_at per row instead.

Give higher tiers a longer window to re-enter payment details

Premium Intermediate

The Promote to Bridge wizard collects a single grace-period length and applies it to everyone. That is usually right, but not always: a podcaster migrating a $2/month tier and a $50/month tier has more to lose from the second group churning during the transition, and may want to give them longer to act.

benecaster_promote_grace_length_days runs once per transferred row, inside the migration loop, at the moment the deadline is written — so the length can vary by tier, by billing interval, by how long the subscriber has been around, or by anything else on the row.

Notes

Returning 0 or a negative does not mean “no grace period”. The value is floored to one day after your callback runs, deliberately: a zero would write a deadline in the past, and the daily expiry cron would revoke that subscriber on its very next tick — cutting off the person you were migrating, which is the opposite of what a grace period is for. If you want someone excluded from the migration, do not promote them.

The filter applies to the initial set only, not to extend_grace_period(). When the podcaster types a number into the Extend field in Promotion History, that number is used as typed. Filtering it would make the panel report a change it did not make.

The grace_period_ends_at field in the wizard’s result payload is the baseline the podcaster typed, not a summary of what each row received. With this filter in play, individual rows can and will differ from it. Read the per-row deadlines from promote_grace_period_ends_at rather than from that one field.

$promotion is the subscription row being transferred — id, user_id, show_id, tier_slug, billing_interval, status and the rest of the row’s columns. $user_id duplicates $promotion['user_id'] for convenience. Return the incoming $days whenever you do not want to intervene, so you compose with other callbacks rather than overriding them.

<?php
add_filter( 'benecaster_promote_grace_length_days', function ( int $days, array $promotion, int $user_id ): int {
    $extra = [
        'gold'   => 90,
        'silver' => 60,
    ];

    // Annual subscribers get the longest window regardless of tier - they are
    // the least likely to be watching their inbox on any given week.
    if ( 'annual' === ( $promotion['billing_interval'] ?? '' ) ) {
        return max( $days, 120 );
    }

    return $extra[ $promotion['tier_slug'] ] ?? $days;
}, 10, 3 );

View on GitHub →

⚠ The return is cast with (int), so a numeric string works, and a non-numeric return silently becomes 0 — which the floor described above then lifts to one day rather than erroring.

Parameters

Name Type Default Description
$days int The wizard's `grace_days` value, already floored to 1.
$promotion array The subscription row being transferred.
$user_id int Subscriber's WordPress user ID. Also present in `$promotion`.

Returns: int

Need this built rather than just documented? See our services →