WPウィジェットのカスタマイザーにボタン追加して広告表示を切り替える
CATEGORIES HTML/CSS PHP WORDPRESS

ウィジェットに設定した Google 広告を、「外観」→「カスタマイズ」のチェックで表示・非表示に切り替える方法。ウィジェットの広告 HTML は消さずに残るので、チェックを戻せば元どおり表示される。

「WordPressログインでタグを表示非表示にさせる」では、ログイン中だけ広告を隠していたのだが、ログイン中の仕組みは残したまま、訪問者向けの切り替えを追加する。WordPress のウィジェットには一時的に止める設定がなく、止めるにはウィジェットを削除するか PHP を書き換えるしかないため。

状態ごとの表示

状態チェックありチェックなし
ログイン中NO ADSNO ADS / OFF
ログアウト中広告を表示何も表示しない

※ ログイン中は、どちらの状態でも広告を表示しない。自分のアクセスで広告の表示回数が増えないようにするため。
※ 「/ OFF」は、チェックなしの状態をログインしたまま確認するための表示。

前提

クラシックテーマ(「外観」→「カスタマイズ」があるテーマ)で、広告の HTML をウィジェットエリアに設定している場合の方法。

ウィジェットエリアは、テーマの functions.php で register_sidebar() を使って用意するもので、id はテーマごとに違う。記事では ad-area として書いているので、テーマの register_sidebar() の 'id' を確認して置き換える。

functions.php でウィジェットエリアを用意している部分の例

// ウィジェットエリアを用意する(widgets_init のタイミングで登録)
function mytheme_widgets_init() {
	register_sidebar(
		array(
			'name'          => '広告エリア',           // 「外観」→「ウィジェット」に表示される名前
			'id'            => 'ad-area',              // ★ 記事のコードで使う値
			'before_widget' => '<div class="widget">',
			'after_widget'  => '</div>',
			'before_title'  => '<h2 class="widget-title">',
			'after_title'   => '</h2>',
		)
	);
}
add_action( 'widgets_init', 'mytheme_widgets_init' );

※ 'id' を記述していない場合は、WordPress が sidebar-1、sidebar-2 のように順番に id を決める。
※ テーマがウィジェットエリアを用意していない場合は、「外観」に「ウィジェット」のメニューが表示されない。

functions.php

テーマ(子テーマを使っている場合は子テーマ)の functions.php の末尾に追記。

/* =====================================================================
   ウィジェットの広告を、カスタマイザーのチェックで表示/非表示にする
   ・「外観」→「カスタマイズ」→「広告の表示」にチェックボックスを追加
   ・OFF のエリアは、公開画面で広告を出力しない。ウィジェットの設定は残るので、ON に戻せば元どおり
   ・ウィジェットのデータ自体には触らない(ウィジェット編集画面で空に見えて、保存で消える事故を防ぐため)
   ・保存時のノンス・権限(edit_theme_options)のチェックはカスタマイザー側で行われる
   ===================================================================== */

/**
 * 切り替えの対象にするウィジェットエリア(★ id => カスタマイザーに表示する名前)
 * ・register_sidebar() の 'id' と同じ値にする。エリアを増やすときは1行足す
 *
 * @return array
 */
function adtoggle_areas() {
	return array(
		'ad-area' => '広告エリア(ad-area)を表示する',
	);
}

/**
 * そのエリアの広告を表示するか
 *
 * @param string $index ウィジェットエリアの id。
 * @return bool 表示するなら true(対象外のエリアは常に true)。
 */
function adtoggle_is_on( $index ) {
	$areas = adtoggle_areas();
	if ( ! isset( $areas[ $index ] ) ) {
		return true;
	}
	return (bool) get_theme_mod( 'adtoggle_show_' . $index, true );
}

/**
 * カスタマイザーに「広告の表示」セクションとチェックボックスを追加する
 *
 * @param WP_Customize_Manager $wp_customize カスタマイザー本体。
 */
function adtoggle_customize_register( $wp_customize ) {
	$wp_customize->add_section(
		'adtoggle',
		array(
			'title'       => '広告の表示',
			'description' => 'チェックを外したエリアは、公開画面で広告を出力しない。ウィジェットの設定は残る。',
			'priority'    => 160,
		)
	);

	foreach ( adtoggle_areas() as $index => $label ) {
		$wp_customize->add_setting(
			'adtoggle_show_' . $index,
			array(
				'default'           => true,
				'type'              => 'theme_mod',
				'capability'        => 'edit_theme_options',
				'sanitize_callback' => 'rest_sanitize_boolean', // true / false 以外は保存しない
			)
		);
		$wp_customize->add_control(
			'adtoggle_show_' . $index,
			array(
				'label'   => $label,
				'section' => 'adtoggle',
				'type'    => 'checkbox',
			)
		);
	}
}
add_action( 'customize_register', 'adtoggle_customize_register' );

/**
 * dynamic_sidebar() の出力を始める直前:OFF のエリアなら出力の溜め込みを始める
 * ・dynamic_sidebar_before / dynamic_sidebar_after は必ず対で呼ばれる
 * ・テンプレートを adtoggle_is_on() で囲んでいない箇所で呼ばれても、広告を出力しないため
 *
 * @param string $index ウィジェットエリアの id。
 */
function adtoggle_buffer_start( $index ) {
	if ( ! is_admin() && ! adtoggle_is_on( $index ) ) {
		ob_start();
	}
}
add_action( 'dynamic_sidebar_before', 'adtoggle_buffer_start' );

/**
 * dynamic_sidebar() の出力が終わった直後:溜めた出力(広告)を捨てる
 *
 * @param string $index ウィジェットエリアの id。
 */
function adtoggle_buffer_end( $index ) {
	if ( ! is_admin() && ! adtoggle_is_on( $index ) ) {
		ob_end_clean();
	}
}
add_action( 'dynamic_sidebar_after', 'adtoggle_buffer_end' );

※ チェックの状態は、カスタマイザーの設定(theme_mod)として保存する。保存のときの権限・ノンスのチェックは、カスタマイザーが行うため。
※ ウィジェットのデータは書き換えず、表示のときに出力を捨てている。ウィジェットのデータを空にすると、ウィジェットの編集画面でも空に見えて、編集画面で保存すると広告の HTML が消えるため。

テンプレート

広告を表示しているテンプレート(single.php など)の、ウィジェットエリアを呼び出している箇所を変更。

変更前(「WordPressログインでタグを表示非表示にさせる」の形)

<?php if ( is_user_logged_in() ) : ?>
<p>NO ADS</p>
<?php else : ?>
<?php dynamic_sidebar( 'ad-area' ); ?>
<?php endif; ?>

変更後

<?php if ( is_user_logged_in() ) : ?>
<div class="ad ad--dummy">
<p>NO ADS<?php echo adtoggle_is_on( 'ad-area' ) ? '' : ' / OFF'; ?></p>
</div>
<?php elseif ( adtoggle_is_on( 'ad-area' ) ) : ?>
<div class="ad">
<?php dynamic_sidebar( 'ad-area' ); ?>
</div>
<?php endif; ?>

else を elseif ( adtoggle_is_on( 'ad-area' ) ) に変える。チェックなしのときは、広告を囲む div ごと出力しないため。囲む div に余白を設定している場合も、すき間が残らない。

ログイン中の NO ADS は div class="ad ad--dummy" で囲む。広告と同じくらいの大きさの枠を表示して、広告が表示される位置と大きさを、ログインしたまま確認できるようにするため。

CSS

テーマの CSS(style.css など)に追記。好きなデザインで。

/* ===== ここから CSS ===== */
/* 広告を囲む div の余白 */
.ad {
  margin: 40px 0;
}

/* ログイン中に広告の代わりに表示する枠(地色・点線の枠・対角線) */
.ad--dummy {
  display: flex;
  align-items: center;      /* 文字を上下の中央に */
  justify-content: center;  /* 文字を左右の中央に */
  min-height: 280px;        /* ★ 広告の高さ(PC) */
  background-color: #e0e5e9; /* ★ 地色 */
  /* 対角線(×):枠と同じ色の 1px の線を2本。枠の大きさが変わっても角から角へ引かれる */
  background-image:
    linear-gradient(to top right, transparent calc(50% - 0.5px), #bcbcbc calc(50% - 0.5px), #bcbcbc calc(50% + 0.5px), transparent calc(50% + 0.5px)),
    linear-gradient(to bottom right, transparent calc(50% - 0.5px), #bcbcbc calc(50% - 0.5px), #bcbcbc calc(50% + 0.5px), transparent calc(50% + 0.5px));
  border: 1px dashed #bcbcbc; /* ★ 枠の色 */
}
.ad--dummy p {
  margin: 0;
  padding: 4px 12px;
  background-color: #e0e5e9; /* 文字の後ろだけ対角線を隠して読みやすくする */
}

/* スマホ */
@media (max-width: 767px) {
  .ad--dummy {
    min-height: 250px;      /* ★ 広告の高さ(スマホ) */
  }
}
/* ===== ここまで CSS ===== */

※ 対角線は画像を使わず、背景のグラデーションで描いている。枠の幅や高さが変わっても、いつも角から角まで線が引かれるため。 ※ 広告の高さは、広告の種類と画面の幅で変わる。広告が表示されている状態で、広告を右クリック →「検証」で ins.adsbygoogle の height を確認し、min-height に入力する。

※ テンプレートを変更しない箇所でも、functions.php の設定だけで広告は出力されなくなる。ただし、囲む div は空のまま残る。

使い方

  1. 管理画面の「外観」→「カスタマイズ」を開く
  2. 「広告の表示」を開く
  3. 「バナーエリア(ad-area)を表示する」のチェックを外す
  4. 「公開」を押す

※ カスタマイザーはログインした状態で開くので、プレビューでは「NO ADS / OFF」と表示される。広告が表示されない場合は、ログアウトするかブラウザのプライベートウィンドウで確認する。

変更する場合

変えたい項目変更箇所
ウィジェットエリアを増やすadtoggle_areas() の配列に1行追記('id' => 'カスタマイザーに表示する名前',)
ログイン中の表示テンプレートの NO ADS と ' / OFF'
枠の高さCSS の min-height(PC 280px/スマホ 250px)
枠の色CSS の background-color と #bcbcbc(枠と対角線)
スマホに切り替える幅CSS の @media (max-width: 767px)
カスタマイザーでの並び順'priority' => 160(小さいほど上)

既存の設定がある場合

カスタマイザーの設定はテーマごとに保存される。別のテーマ(バージョン違いのコピーも含む)に切り替えると、最初はチェックありの状態に戻るので、切り替えたあとに確認すること。

ページキャッシュのプラグインを使っている場合は、切り替えたあとにキャッシュを削除する。削除するまでは、前の表示のページが表示されるため。
※ AdSense の自動広告(<head> に追記したスクリプト)を使っている場合は、ウィジェットの広告ではないので、この方法では止まらない。自動広告は AdSense の管理画面で切り替える。

表示環境によって動きの見え方が異なる場合があるため、本番に反映する前に確認してね。

NOTICES

  • 記事内容は実装させたものがほとんどですが自己責任で参考にしてください。