はじめに
キャンペーンバナーや期間限定のお知らせを表示する際、指定した時間になったら自動で表示・非表示を切り替えたいケースはよくあります。
以下の記事では、「カスタムHTML」ウィジェットごとに開始日時と終了日時を設定し、その指定期間だけコンテンツを表示させる方法を紹介しました。
今回は、独自の設定画面から期間ごとに「カスタムHTML」ウィジェットのパターンを置き換え表示します。
この記事では、この方法について説明します。
ウィジェット個別設定と一括管理の比較
ウィジェットごとに表示日時を設定する方法と、専用の設定ページを設けて一括管理する方法には、それぞれ以下のようなメリット・デメリットがあります(表1参照)。
| 項目 | 一括管理 | 個別設定 |
|---|---|---|
| 運用・確認のしやすさ | 非常に楽 1つの画面で全スケジュールの俯瞰・変更が可能 | 大変 各ウィジェットを開いて個別に設定・確認が必要) |
| 入力ミスのリスク | 低い 設定画面で一覧比較・一括保存できる | 高い 複数ウィジェット間で設定の重複や漏れが起きやすい |
| 表示位置の柔軟性 | 1箇所のみ 全エリアで同一のスケジュールが動く | 複数可能 サイドバーとフッターで別のタイマーを動かせる |
完成イメージ

使用方法
以下にショートコードを示します。
パターンを自動切り替え表示したい位置に配置します。
[my_pattern_switcher]
実装手順
以下のコードをfunctions.phpに追加します。
// 管理画面からの設定データ更新処理
add_action('admin_init', function () {
// nonceチェック
if (isset($_POST['action']) && $_POST['action'] === 'add_pattern') {
check_admin_referer('pattern_switcher_action', 'pattern_switcher_nonce');
}
if (isset($_GET['action']) && $_GET['action'] === 'delete_pattern') {
check_admin_referer('pattern_switcher_action', 'pattern_switcher_nonce');
}
// 権限チェック
if (!current_user_can('manage_options')) {
return;
}
// 新規データの保存処理
if (isset($_POST['action']) && $_POST['action'] === 'add_pattern') {
$options = get_option('my_pattern_switcher', []);
$patterns = is_array($options) ? $options : [];
$pattern_id = isset($_POST['pattern_id'])
? sanitize_text_field($_POST['pattern_id'])
: '';
$st_date = isset($_POST['st_date'])
? sanitize_text_field($_POST['st_date'])
: '';
$ed_date = isset($_POST['ed_date'])
? sanitize_text_field($_POST['ed_date'])
: '';
// パターンIDを確認
if ($pattern_id === '') {
return;
}
$patterns[] = [
'id' => $pattern_id,
'st_date' => $st_date,
'ed_date' => $ed_date,
];
update_option('my_pattern_switcher', array_values($patterns));
set_transient('my_admin_notice', [
'type' => 'success',
'message' => 'パターンを追加しました。',
], 30);
wp_safe_redirect(admin_url('admin.php?page=pattern-switcher'));
exit;
}
// 登録データの削除処理
if (isset($_GET['action']) && $_GET['action'] === 'delete_pattern' && isset($_GET['index'])) {
$options = get_option('my_pattern_switcher', []);
$patterns = is_array($options) ? $options : [];
$index = absint($_GET['index']);
// インデックスを確認
if (isset($patterns[$index])) {
unset($patterns[$index]);
update_option('my_pattern_switcher', array_values($patterns));
set_transient('my_admin_notice', [
'type' => 'success',
'message' => 'パターンを削除しました。',
], 30);
wp_safe_redirect(admin_url('admin.php?page=pattern-switcher'));
exit;
}
}
});
// 管理画面にメニューを追加
add_action('admin_menu', function () {
add_menu_page(
'パターンスイッチャー設定',
'パターンスイッチャー',
'manage_options',
'pattern-switcher',
'render_pattern_switcher',
'dashicons-clock',
20
);
});
// 通知メッセージを出力
add_action('admin_notices', function () {
if ($notice = get_transient('my_admin_notice')) {
echo '<div class="notice notice-' . esc_attr($notice['type']) . ' is-dismissible"><p>' . esc_html($notice['message']) . '</p></div>';
delete_transient('my_admin_notice');
}
});
/**
* 管理画面設定ページを出力
*
* @return void
*/
if (!function_exists('render_pattern_switcher')):
function render_pattern_switcher() {
// 権限チェック
if (!current_user_can('manage_options')) {
return;
}
// 保存済みの設定値を取得
$options = get_option('my_pattern_switcher', []);
$patterns = is_array($options) ? $options : [];
?>
<div class="wrap pattern-switcher">
<h1 class="wp-heading-inline">パターンスイッチャー設定</h1>
<hr class="wp-header-end">
<p>各パターンIDと表示期間を設定してください。ウィジェット内の <code>[my_pattern_switcher]</code>を通じて自動切り替えされます。</p>
<form method="post" action="" class="pattern-switcher__form">
<?php wp_nonce_field('pattern_switcher_action', 'pattern_switcher_nonce'); ?>
<input type="hidden" name="action" value="add_pattern">
<table class="form-table">
<tr>
<th scope="row"><label for="pattern_id">パターンID</label></th>
<td><input type="text" name="pattern_id" id="pattern_id" class="regular-text" placeholder="例: 123" required></td>
</tr>
<tr>
<th scope="row"><label for="st_date">開始日時</label></th>
<td><input type="datetime-local" name="st_date" id="st_date"></td>
</tr>
<tr>
<th scope="row"><label for="ed_date">終了日時</label></th>
<td><input type="datetime-local" name="ed_date" id="ed_date"></td>
</tr>
</table>
<?php submit_button('パターンを追加'); ?>
</form>
<hr>
<h2 class="pattern-switcher__heading">設定済み一覧</h2>
<table class="wp-list-table widefat fixed striped table-view-list pattern-switcher__list">
<thead>
<tr>
<th scope="col" style="width: 30%;">パターンID</th>
<th scope="col" style="width: 30%;">開始日時</th>
<th scope="col" style="width: 30%;">終了日時</th>
<th scope="col" style="width: 10%; text-align: center;">操作</th>
</tr>
</thead>
<tbody>
<?php if (!empty($patterns)): ?>
<?php foreach ($patterns as $index => $item): ?>
<?php
$pattern_id = !empty($item['id']) ? $item['id'] : '';
$st_date = !empty($item['st_date']) ? $item['st_date'] : '';
$ed_date = !empty($item['ed_date']) ? $item['ed_date'] : '';
$delete_url = wp_nonce_url(
admin_url('admin.php?page=pattern-switcher&action=delete_pattern&index=' . $index),
'pattern_switcher_action',
'pattern_switcher_nonce'
);
?>
<tr>
<td><?= esc_html($pattern_id); ?></td>
<td><?= esc_html($st_date); ?></td>
<td><?= esc_html($ed_date); ?></td>
<td style="text-align: center;"><a href="<?= esc_url($delete_url); ?>" class="button button-link-delete" onclick="return confirm('本当に削除しますか?');">削除</a></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td colspan="4">設定されたパターンはありません。</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<?php
}
endif;
// カスタムHTMLウィジェットの内容を変更
add_filter('widget_custom_html_content', function ($content, $instance, $widget) {
// 保存済みの設定値を取得
$options = get_option('my_pattern_switcher', []);
// コンテンツ内に目的のショートコードが存在する場合のみ処理
if (strpos($content, '[my_pattern_switcher]') !== false) {
$rendered_html = '';
if (!empty($options) && is_array($options)) {
foreach ($options as $item) {
// パターンIDが空の場合は処理対象外
if (empty($item['id'])) {
continue;
}
$pattern_id = esc_attr($item['id']);
$st_date = !empty($item['st_date']) ? esc_attr($item['st_date']) : '';
$ed_date = !empty($item['ed_date']) ? esc_attr($item['ed_date']) : '';
// パターンコンテンツを取得
$pattern_shortcode = '[pattern id="' . $pattern_id . '"]';
$pattern_content = do_shortcode($pattern_shortcode);
// 表示期間を設定
$rendered_html .= '<div class="pattern-switcher__item-content" data-start="' . $st_date . '" data-end="' . $ed_date . '" style="display:none;">' . $pattern_content . '</div>';
}
}
$wrapper_html = '<div class="pattern-switcher">' . $rendered_html . '</div>';
// ショートコードを置換
$content = str_replace('[my_pattern_switcher]', $wrapper_html, $content);
}
// 残りのショートコードを実行
return do_shortcode($content);
}, 10, 3);
// フロント用JS・CSSを追加
add_action('wp_enqueue_scripts', function () {
ob_start();
?>
jQuery(function ($) {
$('.pattern-switcher').each(function () {
const wrapper = $(this);
// パターンコンテンツを取得
const items = wrapper.find('.pattern-switcher__item-content');
/**
* 日時をタイムスタンプに変換
*
* @param {string|null} str 日時文字列
* @returns {number|null} タイムスタンプ
*/
const parseDate = function (str) {
if (!str) {
return null;
}
return new Date(str.replace(' ', 'T')).getTime();
};
/**
* パターンの表示状態を更新
*
* @returns {void}
*/
function updateSwitcher() {
// 現在時刻を取得
const now = new Date().getTime();
let activeItem = null;
let fallbackItem = null;
// タイマー設定ありを優先して判定
items.each(function () {
const item = $(this);
const start = parseDate(item.data('start'));
const end = parseDate(item.data('end'));
// タイマー設定なしを予備として保持
if (!start && !end) {
if (!fallbackItem) {
fallbackItem = item;
}
return;
}
// 開始日時を判定
const isStarted = !start || now >= start;
// 終了日時を判定
const isNotEnded = !end || now < end;
// 表示期間を確認
if (isStarted && isNotEnded && !activeItem) {
activeItem = item;
}
});
// タイマー設定ありを表示
if (activeItem) {
if (!activeItem.is(':visible')) {
items.hide().removeClass('is-active');
activeItem.show().addClass('is-active');
}
return;
}
// タイマー設定なしを表示
if (fallbackItem) {
if (!fallbackItem.is(':visible')) {
items.hide().removeClass('is-active');
fallbackItem.show().addClass('is-active');
}
return;
}
// 対象がない場合は非表示
items.hide().removeClass('is-active');
}
updateSwitcher();
// 1秒間隔で更新
setInterval(updateSwitcher, 1000);
});
});
<?php
wp_add_inline_script('jquery', ob_get_clean());
});
補足
各パターンIDと表示期間を設定してください。ウィジェット内の[my_pattern_switcher]を通じて自動切り替えされます。
設定したパターンは、ページのリロード時にスケジュールが判定され、該当するパターンが表示されます。
また、タイマー設定のあるパターンが優先され、表示期間内のパターンがある場合は、タイマー設定のないパターンより優先して表示されます(表2参照)。
| パターン | 開始日時 | 終了日時 | 09:00 | 12:00 | 15:00 | 18:00 |
|---|---|---|---|---|---|---|
| 通常パターン | – | – | 表示 | 表示 | 表示 | 表示 |
| パターンA | 10:00 | 12:00 | 表示 | |||
| パターンB | 14:00 | 16:00 | 表示 |
同じ時間帯に複数のタイマー設定がある場合は、登録順で判定され、先に該当したパターンが表示されます。
さいごに
今回紹介した方法を使えば、独自の設定画面から簡単に「カスタムHTML」ウィジェットの表示パターンや切り替えスケジュールを一括管理できます。
サイドバーやヘッダーなどの重要枠で、手動更新の手間をかけずにリアルタイムなタイムセール告知や期間限定キャンペーンを展開したい場合に非常に効果的です。
