Skip to main content

benecaster_show_limit_exceeded

Action Premium

Fires during the daily license validation cycle when the active show count exceeds the plan limit and at least one show has just been automatically disabled. The newly_disabled_show_ids array contains only the delta — shows disabled in this cycle — not the full set of disabled shows.

This action does not fire on repeat cron ticks where the disabled set is unchanged (idempotent: if the same shows are still disabled on the next validation, the action is silent). It fires only when the disabled set grows.

show_limit is null on unlimited plans. On a transition from a limited plan to an unlimited plan, all previously disabled shows are re-enabled and this action does not fire (use benecaster_show_limit_recovered to observe that transition).

Which shows get disabled. The newest first. Shows are ordered by publish date descending and the first excess of them carry the disabled flag, so the oldest show on a site is the last one to be switched off. Archived shows are excluded — archiving already returns the slot.

Use cases: custom admin notices that go beyond the built-in Shows portfolio banner, external telemetry or monitoring alerts (“show X just got disabled”), add-on hooks that pause ancillary behavior (e.g. pausing Analytics Digest for disabled shows), and Slack or webhook notifications.

The payload is a delta; do not build your picture of the site out of deltas alone. An add-on that only accumulates newly_disabled_show_ids across ticks is permanently wrong the first time it misses one, with nothing to correct it. Use this action to know when to react, then call benecaster_get_over_limit_show_ids() to read the full current set.

Render a site-wide show-limit admin notice

Premium Beginner

The built-in show-limit banner appears only on the React Shows portfolio screen (/#/shows). Use this recipe to surface the same alert on every wp-admin page — useful when you’re working on episodes, subscribers, or settings and don’t want to navigate back to Shows to notice the over-limit state.

The recipe hooks benecaster_show_limit_exceeded and benecaster_show_limit_recovered to stash and clear a wp_option, then renders an admin_notices banner on each wp-admin page load that reads from that option.

Why the wp_option indirection? Both lifecycle actions fire from the daily license cron job — there is no HTML output happening at that moment, so you cannot render a notice directly from the action callbacks. Stash the state in a persistent option and let the next wp-admin page load pick it up via admin_notices.

Delta-only payloads. benecaster_show_limit_exceeded carries newly_disabled_show_ids (the IDs that changed this cycle, not the full disabled set). The recipe uses active_show_count and show_limit from the payload for the notice text. If you need the full current disabled set for a richer message, call benecaster_get_over_limit_show_ids().

Idempotency. Both actions fire only when the disabled set changes — repeat cron ticks with identical license server responses fire nothing, so the wp_option is not rewritten on every cron run.

<?php
// On over-limit: stash the current state so admin_notices can render it.
// Fires from the daily license cron, so we can't render directly — the
// notice hook runs on wp-admin page loads.
add_action( 'benecaster_show_limit_exceeded', function ( array $payload ): void {
    update_option( 'my_theme_show_limit_alert', [
        'active_show_count' => (int) ( $payload['active_show_count'] ?? 0 ),
        'show_limit'        => $payload['show_limit'] ?? null,
        'first_seen_at'     => time(),
    ], false );
} );

// On recovery: clear the stashed state so the notice stops rendering.
// Fires when the license server confirms the site is back under its
// show_limit (upgrade or archive freed capacity).
add_action( 'benecaster_show_limit_recovered', function (): void {
    delete_option( 'my_theme_show_limit_alert' );
} );

// Render on every wp-admin page. The React Shows portfolio's own banner
// renders separately — this is additive, not a replacement.
add_action( 'admin_notices', function (): void {
    $state = get_option( 'my_theme_show_limit_alert' );
    if ( ! is_array( $state ) ) {
        return;
    }
    $active = (int) ( $state['active_show_count'] ?? 0 );
    $limit  = $state['show_limit'];

    printf(
        '<div class="notice notice-error"><p><strong>%s</strong> %s <a href="%s">%s</a></p></div>',
        esc_html__( 'Benecaster:', 'my-theme' ),
        esc_html( sprintf(
            /* translators: 1: active show count, 2: plan show limit */
            __( 'Your site has %1$d shows on a plan that allows %2$d. Some shows have been disabled — upgrade your plan or archive a different show to restore them.', 'my-theme' ),
            $active,
            null === $limit ? 0 : (int) $limit
        ) ),
        esc_url( admin_url( 'admin.php?page=benecaster#/shows' ) ),
        esc_html__( 'Open Shows', 'my-theme' )
    );
} );

View on GitHub →

Parameters

Name Type Default Description
$payload array Associative array with three keys: `active_show_count` (int — total published shows at the time of the check), `show_limit` (int|null — your plan's show limit; null on Studio, which is the only plan with no show limit), and `newly_disabled_show_ids` (int[] — WordPress post IDs of the shows that were just auto-disabled in this validation cycle).

Notes

newly_disabled_show_ids is a DELTA — only what changed on this tick — and that is deliberate. A listener that needs "which of my shows are disabled right now" should not accumulate this array across firings, because a missed tick leaves its picture permanently wrong with nothing to correct it.

Read benecaster_get_over_limit_show_ids() for the full current set instead. The two answer different questions: this action tells you when something changed and what moved; the function tells you what is true now. Reading the function on any tick you care about leaves you always current, whatever you missed.

The set is small — it can never exceed the number of shows on the install — so re-reading it is cheap.

show_limit is null on an unlimited plan, not 0.

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