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_idis 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 === 0only 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.