Skip to main content

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.

Code

<?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 →

Hooks Used

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