Skip to content

Instantly share code, notes, and snippets.

@arenagroove
Created December 18, 2025 06:18
Show Gist options
  • Select an option

  • Save arenagroove/2ff7e8fc4bac68b445af650882635e5a to your computer and use it in GitHub Desktop.

Select an option

Save arenagroove/2ff7e8fc4bac68b445af650882635e5a to your computer and use it in GitHub Desktop.
A lightweight, secure WordPress plugin that displays a customizable Coming Soon page to non-logged-in users while maintaining proper HTTP status codes and SEO protection.

LR Coming Soon Page

A lightweight, secure WordPress plugin that displays a customizable Coming Soon page to non-logged-in users while maintaining proper HTTP status codes and SEO protection.

Features

  • βœ… Clean Implementation: Minimal, well-documented codebase
  • πŸ”’ Secure Preview Access: Time-safe key comparison for preview functionality
  • πŸ‘ Admin Preview Mode: View Coming Soon page while logged in via admin bar button
  • 🎯 Proper HTTP Status: Returns 503 (Service Unavailable) with retry headers
  • 🚫 SEO Protection: Automatic noindex/nofollow headers
  • 🎨 Template Customization: Support for custom theme templates
  • πŸ‘₯ Admin-Friendly: Clear admin interface with persistent status warning
  • ⚑ Performance Optimized: Early exit strategies, no unnecessary processing
  • πŸ”§ WordPress Best Practices: Uses standard APIs and hooks

Installation

As Must-Use Plugin (Recommended)

  1. Copy lr-coming-soon-page.php to /wp-content/mu-plugins/
  2. The plugin activates automatically
  3. Configure via Settings β†’ LR Coming Soon

As Regular Plugin

  1. Copy lr-coming-soon-page.php to /wp-content/plugins/lr-coming-soon/
  2. Activate via Plugins menu
  3. Configure via Settings β†’ LR Coming Soon

Configuration

Basic Setup

  1. Navigate to Settings β†’ LR Coming Soon in WordPress admin
  2. Create a published page with your Coming Soon content
  3. Select the page from the dropdown
  4. Enable "Coming Soon Mode"
  5. (Optional) Set a preview key for sharing access

Admin Preview

When Coming Soon mode is active, administrators can preview the Coming Soon page while logged in:

Option 1: Admin Bar Button

  • Look for the "πŸ‘ Preview Coming Soon" button in the admin bar
  • Click to see exactly what visitors see
  • Only visible to users with manage_options capability

Option 2: Direct URL

https://yoursite.com/?lr_preview_coming_soon=1

This allows you to test the Coming Soon page without logging out or using incognito mode.

Settings Explained

Enable Coming Soon Mode

  • Active: Non-logged-in users see the Coming Soon page
  • Inactive: Normal site operation

Coming Soon Page

  • Select any published page from your site
  • This page's content will be displayed to visitors
  • Must be published (drafts won't work)

Preview Key

  • Optional secret key for bypassing Coming Soon mode
  • Share with clients/stakeholders: https://yoursite.com/?lr_preview=YOUR_KEY
  • Uses time-safe comparison (prevents timing attacks)

How It Works

User Access Logic

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Request arrives                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
                       β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Preview key?   │───Yes──→ Show normal site
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚ No
                       β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Force preview? │───Yes──→ Show Coming Soon
              β”‚ (admin only)   β”‚          (even if logged in)
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚ No
                       β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Logged in?     │───Yes──→ Show normal site
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚ No
                       β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Mode enabled?  │───No───→ Show normal site
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚ Yes
                       β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Show Coming    β”‚
              β”‚ Soon page      β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

What Gets Bypassed

The plugin never interferes with:

  • Logged-in users
  • Preview key holders
  • Admin area
  • AJAX requests
  • Cron jobs
  • RSS feeds
  • REST API requests

HTTP Headers Sent

When Coming Soon page is shown:

HTTP/1.1 503 Service Unavailable
X-Robots-Tag: noindex, nofollow
Retry-After: 86400
Cache-Control: no-cache, must-revalidate, max-age=0

Template Customization

Template Priority

The plugin searches for templates in this order:

  1. coming-soon.php (theme root)
  2. templates/coming-soon.php
  3. parts/page/coming-soon.php
  4. Default fallback template

Creating a Custom Template

Create coming-soon.php in your theme root:

<?php
/**
 * Custom Coming Soon Template
 */
?>
<!doctype html>
<html <?php language_attributes(); ?>>
<head>
    <meta charset="<?php bloginfo('charset'); ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <?php wp_head(); ?>
</head>
<body <?php body_class('coming-soon'); ?>>

<?php while (have_posts()) : the_post(); ?>
    
    <main class="coming-soon-content">
        <?php the_content(); ?>
    </main>

<?php endwhile; ?>

<?php wp_footer(); ?>
</body>
</html>

Using Page Builder Content

The plugin works seamlessly with:

  • Gutenberg blocks
  • Elementor
  • Beaver Builder
  • Divi
  • Any page builder

Just create your page normally and select it in the settings.

Code Architecture

Key Design Decisions

  1. Early Preview Check: Preview bypass is checked first with hash_equals() for security
  2. Guard Clauses: Multiple early returns prevent unnecessary processing
  3. Query Replacement: Swaps global $wp_query cleanly without side effects
  4. Template Hierarchy: Respects WordPress template system
  5. HTTP Compliance: Proper 503 status with retry-after headers

Filters & Actions Used

  • redirect_canonical - Disables canonical redirect for preview URLs
  • admin_menu - Registers settings page
  • admin_init - Registers settings
  • admin_notices - Shows active mode warning
  • template_redirect - Main interception logic

Use Cases

Pre-Launch Site

Perfect for sites under development that need to show a "Coming Soon" or "Under Construction" page while allowing:

  • Developers (logged in) to work normally
  • Client preview access via secret key
  • Search engines to see maintenance status

Temporary Maintenance

Quick maintenance mode without heavy plugins. Set proper HTTP headers so search engines know it's temporary.

Controlled Launch

Share preview access with specific people before public launch using the preview key feature.

Security Features

  • βœ… Time-safe key comparison (hash_equals)
  • βœ… Input sanitization on all settings
  • βœ… Capability checks (manage_options)
  • βœ… Nonce verification (WordPress handles via options.php)
  • βœ… Page status validation (must be published)
  • βœ… Direct access prevention

Performance

  • Minimal overhead: Early exits prevent unnecessary processing
  • No database queries: Uses cached options
  • No external dependencies: Pure WordPress core
  • Template caching: Respects WordPress template caching
  • Query cleanup: Restores original query state

Troubleshooting

Coming Soon page not showing

  1. Verify mode is enabled in settings
  2. Check selected page is published
  3. Test in incognito/private window (you might be logged in)
  4. Clear WordPress cache if using caching plugin

Preview key not working

  1. Verify key is saved in settings (check for typos)
  2. Use exact URL format: ?lr_preview=YOUR_KEY
  3. Check that canonical redirect filter is working

Template not loading

  1. Check file exists in theme directory
  2. Verify file name matches exactly (case-sensitive)
  3. Check file permissions (should be readable)
  4. Clear theme cache

Admin warning not showing

  • This is normal behavior - it's dismissible
  • Will reappear when settings are saved

Browser Compatibility

Works with all modern browsers. The plugin itself has no JavaScript dependencies.

WordPress Compatibility

  • Minimum WordPress: 5.0
  • Minimum PHP: 7.4
  • Tested up to: 6.7
  • Multisite: Compatible

Credits

Author: Luis Martinez
Company: Less Rain GmbH
License: GPL v2 or later

Changelog

1.7.0 (Current)

  • Added admin preview mode (view Coming Soon page while logged in)
  • Added admin bar button for easy preview access
  • Comprehensive documentation
  • Improved code comments
  • Security hardening with hash_equals()
  • Enhanced admin interface with usage instructions
  • Removed unnecessary Text Domain

Earlier versions

  • Core functionality and template system

Support

For bug reports or feature requests, please open an issue on the GitHub Gist.

License

This plugin is licensed under the GPL v2 or later.

Copyright (C) 2024 Luis Martinez / Less Rain GmbH

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
<?php
/**
* Plugin Name: LR Coming Soon Page
* Plugin URI: https://gist.github.com/yourusername/
* Description: Displays a customizable Coming Soon page to non-logged-in users while allowing authenticated users and preview access via a secret key. Maintains proper HTTP 503 status and SEO headers.
* Version: 1.7.0
* Requires at least: 5.0
* Requires PHP: 7.4
* Author: Luis Martinez
* Author URI: https://www.lessrain.com
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*
* @package LR_Coming_Soon
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
/**
* Disable canonical redirect when preview parameter is present.
*
* Prevents WordPress from redirecting when using the lr_preview parameter,
* allowing the preview functionality to work correctly.
*
* @param string|false $redirect_url The redirect URL.
* @return string|false Modified redirect URL or false to prevent redirect.
*/
add_filter('redirect_canonical', function ($redirect_url) {
if (isset($_GET['lr_preview']) && $_GET['lr_preview'] !== '') {
return false;
}
return $redirect_url;
});
/* ==========================================================================
ADMIN INTERFACE
========================================================================== */
/**
* Register admin settings page.
*
* Adds a submenu under Settings for configuring the Coming Soon page.
*/
add_action('admin_menu', function () {
add_options_page(
'LR Coming Soon', // Page title
'LR Coming Soon', // Menu title
'manage_options', // Capability
'lr-coming-soon', // Menu slug
'lr_render_coming_soon_settings' // Callback
);
});
/**
* Add preview button to admin bar.
*
* When Coming Soon mode is active, adds a button to the admin bar that
* allows administrators to preview the Coming Soon page while logged in.
*/
add_action('admin_bar_menu', function ($wp_admin_bar) {
// Only show if Coming Soon is enabled and user can manage options
if (!get_option('lr_coming_soon_enabled')) return;
if (!current_user_can('manage_options')) return;
$wp_admin_bar->add_node([
'id' => 'preview-coming-soon',
'title' => 'πŸ‘ Preview Coming Soon',
'href' => home_url('/?lr_preview_coming_soon=1'),
'meta' => [
'title' => 'Preview the Coming Soon page as visitors see it',
],
]);
}, 999);
/**
* Render the admin settings page.
*
* Displays the configuration interface for enabling/disabling the Coming Soon mode,
* selecting the page to display, and setting the preview key.
*/
function lr_render_coming_soon_settings() {
?>
<div class="wrap">
<h1>Coming Soon Page Settings</h1>
<p>Configure your Coming Soon page settings below. Non-logged-in users will see the selected page when Coming Soon mode is active.</p>
<form method="post" action="options.php">
<?php
settings_fields('lr-coming-soon');
do_settings_sections('lr-coming-soon');
?>
<table class="form-table">
<tr>
<th scope="row">Enable Coming Soon Mode</th>
<td>
<label>
<input type="checkbox"
name="lr_coming_soon_enabled"
value="1"
<?php checked(1, get_option('lr_coming_soon_enabled')); ?>>
Active
</label>
<p class="description">When enabled, non-logged-in users will see the Coming Soon page.</p>
</td>
</tr>
<tr>
<th scope="row">Coming Soon Page</th>
<td>
<?php
wp_dropdown_pages([
'name' => 'lr_coming_soon_page_id',
'selected' => get_option('lr_coming_soon_page_id'),
'show_option_none' => 'β€” Select Page β€”',
'option_none_value' => 0
]);
?>
<p class="description">Select the published page to display as your Coming Soon content. Must be a published page.</p>
</td>
</tr>
<tr>
<th scope="row">Preview Key</th>
<td>
<input type="text"
name="lr_coming_soon_preview_key"
value="<?php echo esc_attr(get_option('lr_coming_soon_preview_key')); ?>"
class="regular-text"
placeholder="Enter a secret key">
<p class="description">
Optional: Set a secret key to bypass Coming Soon mode.<br>
Share this URL: <code><?php echo esc_url(home_url('/?lr_preview=YOUR_KEY')); ?></code>
</p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
<hr>
<h2>How It Works</h2>
<ul>
<li><strong>Logged-in users:</strong> See the normal site (unaffected)</li>
<li><strong>Non-logged-in users:</strong> See the Coming Soon page (when enabled)</li>
<li><strong>Preview access:</strong> Anyone with the preview URL can view the normal site</li>
<li><strong>HTTP 503 status:</strong> Proper status code for maintenance mode</li>
<li><strong>SEO protection:</strong> noindex/nofollow headers prevent search engine indexing</li>
</ul>
<h2>Template Customization</h2>
<p>The plugin looks for custom templates in this order:</p>
<ol>
<li><code>coming-soon.php</code> (theme root)</li>
<li><code>templates/coming-soon.php</code></li>
<li><code>parts/page/coming-soon.php</code></li>
</ol>
<p>If no custom template is found, it uses a minimal default template with the selected page's content.</p>
</div>
<?php
}
/* ==========================================================================
SETTINGS REGISTRATION
========================================================================== */
/**
* Register plugin settings.
*
* Registers three settings:
* - lr_coming_soon_enabled: Boolean toggle for Coming Soon mode
* - lr_coming_soon_page_id: ID of the page to display
* - lr_coming_soon_preview_key: Secret key for preview access
*/
add_action('admin_init', function () {
// Enable/disable toggle
register_setting('lr-coming-soon', 'lr_coming_soon_enabled', 'absint');
// Preview key
register_setting('lr-coming-soon', 'lr_coming_soon_preview_key', 'sanitize_text_field');
// Page selection with validation
register_setting('lr-coming-soon', 'lr_coming_soon_page_id', [
'type' => 'integer',
'sanitize_callback' => function ($value) {
$value = absint($value);
// Ensure selected page is published
if ($value && get_post_status($value) !== 'publish') {
add_settings_error(
'lr-coming-soon',
'invalid-page',
'Selected page must be published.'
);
return get_option('lr_coming_soon_page_id');
}
return $value;
}
]);
});
/* ==========================================================================
ADMIN NOTICES
========================================================================== */
/**
* Display admin notice when Coming Soon mode is active.
*
* Shows a persistent warning in the admin area to remind administrators
* that the site is in Coming Soon mode.
*/
add_action('admin_notices', function () {
if (get_option('lr_coming_soon_enabled')) {
echo '<div class="notice notice-warning is-dismissible">';
echo '<p><strong>⚠ Coming Soon mode is active.</strong> Non-logged-in users see the Coming Soon page.</p>';
echo '</div>';
}
});
/* ==========================================================================
FRONTEND INTERCEPTION
========================================================================== */
/**
* Intercept frontend requests and display Coming Soon page.
*
* This is the core functionality that:
* 1. Checks for preview key bypass
* 2. Validates conditions (logged in, enabled, etc.)
* 3. Sets proper HTTP headers (503, no-cache, no-index)
* 4. Replaces the main query with the Coming Soon page
* 5. Renders the appropriate template
*
* @return void Exits after rendering if conditions are met.
*/
add_action('template_redirect', function () {
// =========================================================================
// PREVIEW BYPASS - Checked first with time-safe comparison
// =========================================================================
$preview_key = get_option('lr_coming_soon_preview_key');
if (
$preview_key &&
isset($_GET['lr_preview']) &&
hash_equals($preview_key, (string) $_GET['lr_preview'])
) {
return; // Allow normal site access
}
// =========================================================================
// LOGGED-IN PREVIEW MODE - Allow admins to preview Coming Soon page
// =========================================================================
$force_preview = isset($_GET['lr_preview_coming_soon']) &&
$_GET['lr_preview_coming_soon'] === '1' &&
current_user_can('manage_options');
// =========================================================================
// GUARD CONDITIONS - Exit early if Coming Soon should not be shown
// =========================================================================
// Logged-in users see normal site (unless forcing preview)
if (is_user_logged_in() && !$force_preview) return;
// Coming Soon mode must be enabled
if (!get_option('lr_coming_soon_enabled')) return;
// Don't interfere with admin area
if (is_admin()) return;
// Don't interfere with AJAX or cron
if (wp_doing_ajax() || wp_doing_cron()) return;
// Allow RSS feeds to work normally
if (is_feed()) return;
// Allow REST API requests
if (defined('REST_REQUEST') && REST_REQUEST) return;
// Page must be configured and published
$page_id = (int) get_option('lr_coming_soon_page_id');
if (!$page_id) return;
$post = get_post($page_id);
if (!$post || $post->post_status !== 'publish') return;
// =========================================================================
// HTTP HEADERS - Set proper status and SEO directives
// =========================================================================
status_header(503); // Service Unavailable
nocache_headers(); // Prevent caching
header('X-Robots-Tag: noindex, nofollow'); // Prevent indexing
header('Retry-After: 86400'); // Suggest retry in 24h
// =========================================================================
// QUERY REPLACEMENT - Swap main query with Coming Soon page
// =========================================================================
global $wp_query, $wp_the_query;
// Store original queries for restoration
$old_wp_query = $wp_query;
$old_wp_the_query = $wp_the_query;
// Create new query for Coming Soon page
$wp_query = $wp_the_query = new WP_Query([
'post_type' => 'page',
'p' => $page_id,
'posts_per_page' => 1,
]);
// Set query flags for proper template hierarchy
$wp_query->is_home = false;
$wp_query->is_front_page = false;
$wp_query->is_page = true;
$wp_query->is_singular = true;
// =========================================================================
// TEMPLATE RENDERING - Use custom template or fallback
// =========================================================================
ob_start();
// Look for custom template in theme
$template = locate_template([
'coming-soon.php',
'templates/coming-soon.php',
'parts/page/coming-soon.php',
]);
if ($template) {
// Use custom template
include $template;
} else {
// Fallback: minimal default template
echo '<!doctype html><html><head>';
wp_head();
echo '</head><body>';
while (have_posts()) {
the_post();
the_content();
}
wp_footer();
echo '</body></html>';
}
echo ob_get_clean();
// Restore original queries (cleanup, though script exits)
$wp_query = $old_wp_query;
$wp_the_query = $old_wp_the_query;
exit; // Stop execution
});

Quick Start Guide

Installation (2 minutes)

Option A: Must-Use Plugin (Recommended)

# Upload to your WordPress installation
wp-content/mu-plugins/lr-coming-soon-page.php

That's it! The plugin is automatically active.

Option B: Regular Plugin

# Create plugin directory
wp-content/plugins/lr-coming-soon/lr-coming-soon-page.php

# Then activate via WordPress admin

Setup (3 steps)

1. Create Your Coming Soon Page

  • Go to Pages β†’ Add New
  • Create your coming soon content (use any page builder)
  • Publish the page

2. Configure Plugin

  • Go to Settings β†’ LR Coming Soon
  • Select your page from dropdown
  • Enable "Coming Soon Mode"
  • Save Changes

3. Test It

# Open incognito/private window
https://yoursite.com

# You should see your Coming Soon page

# Meanwhile, logged-in admin sees normal site

4. Preview as Admin (Optional)

Want to see the Coming Soon page while logged in?

Easy way: Click "πŸ‘ Preview Coming Soon" in the admin bar

Direct URL: https://yoursite.com/?lr_preview_coming_soon=1

Optional: Preview Access

Set Preview Key

Settings β†’ LR Coming Soon β†’ Preview Key
Enter: "secret123"
Save

Share Preview URL

https://yoursite.com/?lr_preview=secret123

Anyone with this URL sees the normal site (no login required).

Quick Troubleshooting

"I don't see the Coming Soon page"

  • Are you logged in? (Try incognito window)
  • Is mode enabled? (Check settings)
  • Is page published? (Not draft/pending)

"Preview key doesn't work"

  • Check for typos in key
  • Use exact format: ?lr_preview=KEY
  • No extra spaces in key

"Need custom styling"

  • Create coming-soon.php in theme
  • See example-coming-soon-template.php
  • Or style via page builder

Common Scenarios

Pre-Launch Site

βœ“ Enable Coming Soon
βœ“ Share preview key with client
βœ“ Work normally while logged in

Quick Maintenance

βœ“ Enable Coming Soon
βœ“ Make changes
βœ“ Disable when done

Controlled Release

βœ“ Create launch page
βœ“ Share preview with testers
βœ“ Collect feedback
βœ“ Public launch (disable mode)

Need Help?

  1. Check README.md for detailed docs
  2. Review example template file
  3. Open issue on GitHub Gist
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment