Skip to main content

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.

Code

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

Hooks Used

  • benecaster-show-limit-exceeded
  • benecaster-show-limit-recovered

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