Skip to main content

Customizing Tenure Badges

Three filters give developers full control over how tenure badges are computed and rendered. They compose cleanly — each one fires at a different point in the pipeline, so you can use any combination without interference.

Filter Fires from What you control
benecaster_tenure_badge_milestones TenureBadgeCalculator::resolve_milestones() The threshold map — which month counts produce which labels
benecaster_tenure_badge_label TenureBadgeCalculator::build_snapshot_from_row() The selected label, per subscriber, after the map is matched
benecaster_tenure_badge_output BadgeChipRenderer::render_chip() The chip HTML for tenure_auto rows

benecaster_tenure_badge_milestones — Redefine the Threshold Map

Replace the entire milestone map with your own month → label pairs. The calculator picks the highest threshold that does not exceed the subscriber’s tenure and uses that entry’s label.

add_filter( 'benecaster_tenure_badge_milestones', function ( array $default ): array {
    return [
        3  => 'First-Quarter Supporter',
        6  => 'Half-Year Supporter',
        12 => 'One-Year Anniversary',
        24 => 'Two-Year Anniversary',
    ];
} );

Normalization: the calculator sorts your map ascending and drops entries with non-positive month keys or non-string / empty labels. Returning a non-array falls back to the built-in defaults. Return order does not matter.

Below-first-milestone subscribers: a subscriber whose tenure is below your lowest threshold receives an empty label — the chip is suppressed unless benecaster_tenure_badge_label returns a non-empty string for them.


benecaster_tenure_badge_label — Override the Matched Label

Fires after the milestone map is matched. Use this when the label needs to vary per subscriber in ways the threshold map alone cannot express: localisation, a special designation for very long-tenure members, or injecting a “New Supporter” label below the first milestone.

add_filter(
    'benecaster_tenure_badge_label',
    function ( string $label, int $user_id, int $show_id, int $months_since_join ): string {
        // Charter Member designation for anyone past three years.
        if ( $months_since_join >= 36 ) {
            return __( 'Charter Member', 'my-addon' );
        }
        return $label;
    },
    10, 4
);

Inject a label for below-first-milestone subscribers:

add_filter(
    'benecaster_tenure_badge_label',
    function ( string $label, int $user_id, int $show_id, int $months_since_join ): string {
        // $label is '' when tenure is below the lowest milestone threshold.
        // Return a non-empty string to show a chip for new members.
        return $label !== '' ? $label : __( 'New Supporter', 'my-addon' );
    },
    10, 4
);

$show_id notes:

  • On per-show surfaces (Supporter Wall), $show_id is the show being rendered.
  • On the site-wide account page, the calculator uses the earliest active token across all shows and passes that show’s ID as $show_id.
  • $show_id === 0 only when the user has no active tokens at all.

benecaster_tenure_badge_output — Replace the Chip HTML

Fires from BadgeChipRenderer::render_chip() only for tenure_auto badge rows. Tier and manual badges are unaffected. Use this to wrap the chip, add a tooltip, link it to a page, or replace it with entirely custom markup.

add_filter(
    'benecaster_tenure_badge_output',
    function ( string $html, int $user_id, int $show_id ): string {
        $tip = esc_attr__( 'Based on your subscription start date', 'my-addon' );
        return '<span class="my-tenure-tooltip" data-tip="' . $tip . '">' . $html . '</span>';
    },
    10, 3
);

$show_id is 0 when the chip renders on the site-wide account page (per-user mode).


Composing All Three Together

The filters fire in order: milestones → label → output. Here is a complete example that customizes all three stages:

// Stage 1 — quarterly milestone map.
add_filter( 'benecaster_tenure_badge_milestones', function ( array $default ): array {
    return [
        3  => 'First-Quarter Supporter',
        6  => 'Half-Year Supporter',
        12 => 'One-Year Anniversary',
        24 => 'Two-Year Anniversary',
    ];
} );

// Stage 2 — override label for very long-tenure members.
add_filter(
    'benecaster_tenure_badge_label',
    function ( string $label, int $user_id, int $show_id, int $months_since_join ): string {
        if ( $months_since_join >= 36 ) {
            return __( 'Charter Member', 'my-addon' );
        }
        return $label;
    },
    10, 4
);

// Stage 3 — link the chip to a "how tenure works" page.
add_filter(
    'benecaster_tenure_badge_output',
    function ( string $html, int $user_id, int $show_id ): string {
        return '<a href="/about-membership-tenure/" class="my-tenure-link">' . $html . '</a>';
    },
    10, 3
);

See the Redefine tenure badge milestones recipe for a standalone, copy-pasteable version of this pattern.


Checking Whether the Feature Is Active

Add-ons and theme templates can check the site-wide toggle without reading wp_options directly:

if ( BenecasterMembershipTenureBadgeAppender::is_enabled() ) {
    // Tenure badge is on — safe to render tenure-specific UI.
}

See TenureBadgeAppender and TenureBadgeCalculator for the full class references.

See Also