はじめに
Cocoonには、「カスタムHTML」ブロックとは別に、投稿ごと・固定ページごとにCSSやJavaScriptを直接記述できる機能が標準で用意されています。
ページ単位で細かな調整ができる点は便利ですが、実運用では次のような問題に直面することが少なくありません。
- どのページにCSSやJavaScriptを設定したのか、管理画面から分からない
- 同じCSSやJavaScriptを複数ページで使いたい場合、各ページに同じコードをコピーする必要がある
- 修正が入った際、全てのページを探して更新しなければならない
これらは、サイト規模が大きくなるほど管理コストやミスの原因になります。
そこで、CSS・JavaScriptを専用の管理画面で一覧管理し、投稿ID・固定ページID・カテゴリー・タグ条件に応じて自動出力する仕組みを追加します。
この方法を使えば、どのコードがどのページで使われているかを一目で把握でき、同一のCSSやJavaScriptを複数ページで安全に再利用できるようになります。
この記事では、この方法について説明します。
完成イメージ


実装手順
以下のコードをfunctions.phpに追加します。
// カスタム投稿タイプを追加
add_action('init', function () {
register_post_type('my_asset_snippet', [
'label' => 'JS・CSS管理',
'public' => false,
'show_ui' => true,
'menu_icon' => 'dashicons-media-code',
'supports' => ['title'],
]);
});
// メタボックスを追加
add_action('add_meta_boxes', function () {
add_meta_box(
'asset_snippet',
'JS / CSS 設定',
'render_asset_snippet',
'my_asset_snippet',
'normal',
'high'
);
});
/**
* メタボックスの入力フォームを出力
*
* @param WP_Post $post 投稿オブジェクト
* @return void
*/
if (!function_exists('render_asset_snippet')):
function render_asset_snippet($post) {
// nonceフィールドを出力
wp_nonce_field('asset_snippet_action', 'asset_snippet_nonce');
// 設定を取得
$type = get_post_meta($post->ID, 'my_asset_snippet_type', true) ?: 'css';
$code = get_post_meta($post->ID, 'my_asset_snippet_code', true);
$pages = get_post_meta($post->ID, 'my_asset_snippet_pages', true);
$cats = get_post_meta($post->ID, 'my_asset_snippet_cats', true);
$tags = get_post_meta($post->ID, 'my_asset_snippet_tags', true);
$enable = get_post_meta($post->ID, 'my_asset_snippet_enable', true);
?>
<p>
<strong>種別</strong><br>
<label>
<input type="radio" name="asset-type" value="css" <?php checked($type, 'css'); ?>>
CSS(head出力)
</label>
<label>
<input type="radio" name="asset-type" value="js" <?php checked($type, 'js'); ?>>
JavaScript(footer出力)
</label>
</p>
<p>
<strong>コード</strong>
<textarea name="asset-code" style="width:100%;height:200px;"><?= esc_textarea($code); ?></textarea>
</p>
<p>
<strong>投稿・固定ページID(カンマ区切り)</strong><br>
<input type="text" name="asset-pages" value="<?= esc_attr($pages); ?>" style="width:100%;">
</p>
<p>
<strong>カテゴリーID(カンマ区切り)</strong><br>
<input type="text" name="asset-cats" value="<?= esc_attr($cats); ?>" style="width:100%;">
</p>
<p>
<strong>タグID(カンマ区切り)</strong><br>
<input type="text" name="asset-tags" value="<?= esc_attr($tags); ?>" style="width:100%;">
</p>
<p>
<label>
<input type="checkbox" name="asset-enable" value="1" <?php checked($enable, '1'); ?>>
有効にする
</label>
</p>
<?php
}
endif;
// 投稿データを保存
add_action('save_post_my_asset_snippet', function ($post_id) {
// nonceチェック
if (!isset($_POST['asset_snippet_nonce']) || !wp_verify_nonce($_POST['asset_snippet_nonce'], 'asset_snippet_action')) {
return;
}
// 自動保存チェック
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// リビジョンは除外
if (wp_is_post_revision($post_id)) {
return;
}
// 権限チェック
if (!current_user_can('edit_post', $post_id)) {
return;
}
// 値を保存
update_post_meta($post_id, 'my_asset_snippet_type', sanitize_text_field($_POST['asset-type'] ?? 'css'));
update_post_meta($post_id, 'my_asset_snippet_code', $_POST['asset-code'] ?? '');
update_post_meta($post_id, 'my_asset_snippet_pages', sanitize_text_field($_POST['asset-pages'] ?? ''));
update_post_meta($post_id, 'my_asset_snippet_cats', sanitize_text_field($_POST['asset-cats'] ?? ''));
update_post_meta($post_id, 'my_asset_snippet_tags', sanitize_text_field($_POST['asset-tags'] ?? ''));
update_post_meta($post_id, 'my_asset_snippet_enable', isset($_POST['asset-enable']) ? '1' : '0');
});
/**
* 表示対象を判定
*
* @param int $snippet_id スニペットの投稿ID
* @return bool
*/
if (!function_exists('asset_snippet_is_target')):
function asset_snippet_is_target($snippet_id) {
// 設定を取得
$pages = array_filter(array_map('intval', explode(',', get_post_meta($snippet_id, 'my_asset_snippet_pages', true))));
$cats = array_filter(array_map('intval', explode(',', get_post_meta($snippet_id, 'my_asset_snippet_cats', true))));
$tags = array_filter(array_map('intval', explode(',', get_post_meta($snippet_id, 'my_asset_snippet_tags', true))));
// 指定なしは終了
if (empty($pages) && empty($cats) && empty($tags)) {
return true;
}
// 現在のページIDを取得
$current_id = get_queried_object_id();
// 投稿・固定ページ単位を確認
if (!empty($pages) && in_array($current_id, $pages, true)) {
return true;
}
// カテゴリー単位を確認
if (is_category() && !empty($cats) && in_array($current_id, $cats, true)) {
return true;
}
// タグ単位を確認
if (is_tag() && !empty($tags) && in_array($current_id, $tags, true)) {
return true;
}
return false;
}
endif;
/**
* スニペットを出力
*
* @param string $type css|js
* @return void
*/
if (!function_exists('render_asset_snippets')):
function render_asset_snippets($type) {
if (is_admin()) {
return;
}
// 有効かつ指定種別を取得
$snippets = get_posts([
'post_type' => 'my_asset_snippet',
'posts_per_page' => -1,
'meta_query' => [
['key' => 'my_asset_snippet_type', 'value' => $type],
['key' => 'my_asset_snippet_enable', 'value' => '1'],
],
]);
foreach ($snippets as $snippet) {
// 表示対象外は処理対象外
if (!asset_snippet_is_target($snippet->ID)) {
continue;
}
// コードを取得
$code = get_post_meta($snippet->ID, 'my_asset_snippet_code', true);
if (!$code) {
continue;
}
// 種別に応じたタグを設定
$tag = ($type === 'css') ? 'style' : 'script';
echo "\n\n<{$tag}>\n{$code}\n</{$tag}>\n";
}
}
endif;
// headタグ内でCSSを出力
add_action('wp_head', function () {
render_asset_snippets('css');
}, 100);
// footerタグ内でJSを出力
add_action('wp_footer', function () {
render_asset_snippets('js');
}, 100);
// 管理画面一覧にカラムを追加
add_filter('manage_my_asset_snippet_posts_columns', function ($columns) {
$new = [];
foreach ($columns as $key => $label) {
$new[$key] = $label;
if ($key === 'title') {
$new['asset_enable'] = '有効 / 無効';
$new['asset_type'] = '種別';
}
}
return $new;
});
// 管理画面一覧のカラムにデータを表示
add_action('manage_my_asset_snippet_posts_custom_column', function ($column, $post_id) {
switch ($column) {
// 有効・無効を表示
case 'asset_enable':
echo get_post_meta($post_id, 'my_asset_snippet_enable', true) === '1' ? '有効' : '無効';
break;
// 種別を表示
case 'asset_type':
echo strtoupper(get_post_meta($post_id, 'my_asset_snippet_type', true) ?: 'css');
break;
}
}, 10, 2);
さいごに
今回紹介した方法を使えば、投稿や固定ページごとに分散しがちなCSS・JavaScriptを、専用の管理画面で一元的に把握・制御できるようになります。
どのコードがどのページで使われているのかが明確になり、同じCSSやJavaScriptを何度も書き直す必要もありません。
Cocoon標準機能やカスタムHTMLブロックの弱点を補いながら、保守性と安全性を高められる点が、この仕組みの最大のメリットです。
サイト規模が大きくなってきた場合や、将来的な修正コストを減らしたい場合に、特に効果を発揮するでしょう。
