WordPress Plugin: Swap Your Content At A Specific Date & Time With This Shortcode

If you’ve ever needed to show a registration form or a teaser before an event and automatically swap it for a recap or recording page the moment the event begins, you know how awkward that transition can be to manage manually. The Date Gate Shortcode plugin solves this cleanly — you write both versions of your content once, set a deadline, and WordPress handles the rest.
The plugin works entirely on the server side. There’s no JavaScript countdown, no page refresh, no live gate. When a visitor loads the page before your deadline, they see the before content — whether that’s a registration form, a teaser, a countdown graphic, or an early-bird offer. When they load it afterward, they see the after-content. The switch happens naturally on the next page load once the pivot date and time have passed.
It also handles caching automatically. Most WordPress caching plugins serve a cached copy of the page rather than regenerating it on each visit, so the content may appear stale after your deadline passes. The Date Gate plugin schedules a background task using WP-Cron to purge the cache for that specific post at the exact moment of the transition, covering WP Rocket, W3 Total Cache, WP Super Cache, LiteSpeed Cache, SG Optimizer, Kinsta, Nginx Helper, Autoptimize, and the Cloudflare plugin.
Using the Shortcode
The shortcode wraps two inner blocks —
[date_gate date="2025-09-15 10:00:00"]
[before_date]
<h2>Join Us Live on September 15th</h2>
<p>Our annual marketing technology roundtable kicks off at 10am. Reserve your seat below — or keep reading for a preview of what we'll be covering.</p>
<a href="/register" class="button">Register Now</a>
[/before_date]
[after_date]
<h2>Thanks for Joining Us</h2>
<p>The live session has ended. Watch the full recording below, and download the slide deck from the link underneath.</p>
<a href="/recording" class="button">Watch the Recording</a>
[/after_date]
[/date_gate] The date and time use the timezone configured in your WordPress site under Settings → General, so no additional configuration is needed. The [before_date] and [after_date] blocks support full HTML and any other shortcodes your theme or plugins provide.
Installing the Plugin
Download the file below as date-gate-shortcode.php and upload it to your wp-content/plugins/date-gate-shortcode/ directory, then activate it from the Plugins screen in your WordPress dashboard. No settings page is required — the shortcode is ready to use immediately.
<?php
/**
* Plugin Name: Date Gate Shortcode
* Description: Display different content before and after a specific date/time, with automatic cache clearing at the pivot moment via WP-Cron.
* Version: 1.1.0
* Author: Douglas Karr
* Author URI: https://dknewmedia.com
*/
if ( ! defined( 'ABSPATH' ) ) { exit; }
// Inner shortcodes are no-ops; the outer shortcode parses the raw content itself
add_shortcode( 'before_date', 'date_gate_inner_noop' );
add_shortcode( 'after_date', 'date_gate_inner_noop' );
function date_gate_inner_noop( $atts, $content = '' ) {
return '';
}
// Register the outer [date_gate date="..." timezone="..."] shortcode
add_shortcode( 'date_gate', 'date_gate_shortcode' );
function date_gate_shortcode( $atts, $content = '' ) {
$atts = shortcode_atts( array( 'date' => '', 'timezone' => '' ), $atts, 'date_gate' );
// Resolve timezone — falls back to the WordPress site timezone setting
$tz_string = trim( $atts['timezone'] );
if ( $tz_string === '' ) {
$tz_string = get_option( 'timezone_string' );
if ( empty( $tz_string ) ) {
$tz_string = date_gate_offset_to_timezone( (float) get_option( 'gmt_offset', 0 ) );
}
}
try { $tz = new DateTimeZone( $tz_string ); } catch ( Exception $e ) { $tz = new DateTimeZone( 'UTC' ); }
// Bail with a debug comment if the date attribute is missing or unparseable
$date_string = trim( $atts['date'] );
if ( $date_string === '' ) { return date_gate_error( 'date_gate: missing required "date" attribute.' ); }
try { $pivot = new DateTime( $date_string, $tz ); } catch ( Exception $e ) { return date_gate_error( 'date_gate: could not parse date "' . esc_html( $date_string ) . '".' ); }
$now = new DateTime( 'now', $tz );
// While before the pivot, schedule a one-time WP-Cron event to clear the cache at the exact moment
if ( $now < $pivot ) {
$post_id = get_the_ID();
$pivot_utc = $pivot->getTimestamp(); // WP-Cron operates in UTC Unix time
if ( $post_id && ! date_gate_cron_scheduled( $post_id, $pivot_utc ) ) {
wp_schedule_single_event( $pivot_utc, 'date_gate_clear_cache', array( $post_id, $pivot_utc ) );
}
}
// Extract and return the appropriate inner block
$before_content = date_gate_extract_inner( $content, 'before_date' );
$after_content = date_gate_extract_inner( $content, 'after_date' );
return do_shortcode( $now < $pivot ? $before_content : $after_content );
}
// WP-Cron hook: purge the post cache across all major caching plugins
add_action( 'date_gate_clear_cache', 'date_gate_clear_post_cache', 10, 2 );
function date_gate_clear_post_cache( $post_id, $pivot_utc ) {
$post_url = get_permalink( $post_id );
if ( function_exists( 'wp_cache_post_change' ) ) { wp_cache_post_change( $post_id ); } // WP Super Cache
if ( function_exists( 'w3tc_flush_post' ) ) { w3tc_flush_post( $post_id ); } // W3 Total Cache
if ( function_exists( 'rocket_clean_post' ) ) { rocket_clean_post( $post_id ); } // WP Rocket
if ( function_exists( 'kinsta_cache_purge_by_url' ) ) { kinsta_cache_purge_by_url( $post_url ); } // Kinsta
if ( function_exists( 'sg_cachepress_purge_cache' ) ) { sg_cachepress_purge_cache( $post_url ); } // SG Optimizer
if ( function_exists( 'rt_nginx_helper_purge_url' ) ) { rt_nginx_helper_purge_url( $post_url ); } // Nginx Helper
if ( class_exists( 'LiteSpeed_Cache_API' ) && method_exists( 'LiteSpeed_Cache_API', 'purge' ) ) { LiteSpeed_Cache_API::purge( $post_url ); } // LiteSpeed
if ( class_exists( 'autoptimizeCache' ) && method_exists( 'autoptimizeCache', 'clearall' ) ) { autoptimizeCache::clearall(); } // Autoptimize
if ( class_exists( 'CF\WordPress\Hooks' ) ) { do_action( 'cloudflare_purge_by_url', array( $post_url ) ); } // Cloudflare
clean_post_cache( $post_id ); // WordPress core fallback
}
// Returns true if a cache-clear cron is already queued for this post + pivot combination
function date_gate_cron_scheduled( $post_id, $pivot_utc ) {
return ( wp_next_scheduled( 'date_gate_clear_cache', array( $post_id, $pivot_utc ) ) !== false );
}
// On deactivation, remove all pending date_gate cron events
register_deactivation_hook( __FILE__, 'date_gate_deactivate' );
function date_gate_deactivate() {
$crons = _get_cron_array();
if ( empty( $crons ) ) { return; }
foreach ( $crons as $timestamp => $hooks ) {
if ( isset( $hooks['date_gate_clear_cache'] ) ) {
foreach ( $hooks['date_gate_clear_cache'] as $key => $event ) {
wp_unschedule_event( $timestamp, 'date_gate_clear_cache', $event['args'] ?? array() );
}
}
}
}
// Extract the raw inner content of a named shortcode tag using regex
function date_gate_extract_inner( $content, $tag ) {
if ( preg_match( '/\[' . preg_quote( $tag, '/' ) . '[^\]]*\](.*?)\[\/' . preg_quote( $tag, '/' ) . '\]/is', $content, $matches ) ) {
return trim( $matches[1] );
}
return '';
}
// Convert a numeric UTC offset (e.g. -5) to a PHP timezone string (e.g. Etc/GMT+5)
function date_gate_offset_to_timezone( $offset ) {
if ( $offset === 0.0 || $offset !== (float)(int) $offset ) { return 'UTC'; } // fractional offsets not supported by Etc/GMT
return 'Etc/GMT' . ( $offset > 0 ? '-' : '+' ) . abs( (int) $offset );
}
// Output an HTML comment on WP_DEBUG sites, nothing in production
function date_gate_error( $message ) {
return ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? '<!-- ' . esc_html( $message ) . ' -->' : '';
} 






