どうも、記事も書かずにSEO対策のことばかり考えているシェフです。
「元も子もない」ってこういうことを言うんでしょうね。
さて、以前公開したこちらの記事。
タイトル通り、プラグインを使わずにキーワードやディスクリプションの設定などのSEO対策ができるコードを紹介していて、ニーズがあるのかけっこう読まれています。
ただ、記事を公開してから時間が経っていることもあり、コードがあまりスマートじゃありません。
しかも、TwitterやFacebookの「OGP設定」もないんですよね。
ということで今回は、改良版ということでOGP対応のコードをご紹介します。
- タイトルタグの書き換え
- OGP用のタイトルに書き換え
- FacebookアプリIDの付与
- 文字数カウンター付き
なども盛り込んだボリューム満点の内容になっているので(コードだけで1万文字オーバー!)、ぜひご活用いただければと思います。
ちなみに、先日コメントいただきましたが、オリジナルテーマなどに組み込んでいただいて全然OKです:)
ご自由にお使いください!
(もちろん、「使ったよー!」などのコメントは大歓迎です!)
コピペしてすぐに使えるコードですが、いくつか補足があるので最後までお読みいただければ幸いです。
以下、コードのご紹介です。
これでSEOプラグインも不要!コピペで使えるコード
以下のコードをfunctions.phpにコピペするだけで記事の編集画面にカスタムフィールドが生成され、アーカイブページなどにも自動的にディスクリプションが出力されます。
//カスタムフィールドの設定
class Custom_Field_4536 {
function __construct() {
add_filter( 'document_title_parts', [ $this, 'title_update' ] );
if(!is_admin()) return;
add_action( 'add_meta_boxes', [ $this, 'init' ] );
add_action( 'transition_post_status', [ $this, 'save' ], 10, 3 );
}
function init() {
$list = [
'SEO対策' => 'seo_custom_fields',
];
$args = [
'public' => true,
'_builtin' => false,
];
$post_types = get_post_types( $args, 'names' );
foreach($list as $title => $id) {
add_meta_box( $id, $title, $id, 'post', 'normal', 'high');
add_meta_box( $id, $title, $id, 'page', 'normal', 'high');
foreach ( $post_types as $post_type ) {
add_meta_box( $id, $title, $id, $post_type, 'normal', 'high');
}
}
}
function save($new_status, $old_status, $post) {
if (($old_status == 'auto-draft'
|| $old_status == 'draft'
|| $old_status == 'pending'
|| $old_status == 'future')
&& $new_status == 'publish') {
return $post;
} else {
add_action('save_post', function($post_id) {
$list = [
'keywords',
'description',
'noindex',
'nofollow',
'sns_title',
'seo_title',
];
foreach($list as $name) {
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id;
if(isset($_POST['action']) && $_POST['action'] == 'inline-save') return $post_id;
if(!empty($_POST[$name]))
update_post_meta($post_id, $name, $_POST[$name] );
else delete_post_meta($post_id, $name);
}
});
}
}
function title_update($title) {
global $post;
$seo_title = get_post_meta($post->ID,'seo_title',true);
if(is_singular() && $seo_title) $title['title'] = $seo_title;
return $title;
}
}
new Custom_Field_4536();
// 設定項目の作成
function seo_custom_fields() {
global $post;
$list = [
'seo_title' => 'SEO用タイトル(タイトルタグ書き換え)',
'sns_title' => 'SNS用タイトル',
];
foreach($list as $name => $description) { ?>
<div class="input-wrapper-4536">
<div id="<?php echo $name; ?>-counter" class="counter"></div>
<label for="<?php echo $name; ?>" class="label-4536"><?php echo $description; ?></label>
<input name="<?php echo $name; ?>" id="<?php echo $name; ?>" value="<?php echo esc_html(get_post_meta($post->ID, $name, true)); ?>" size="60" class="input-4536" type="text" />
<div style="clear:both;"></div>
</div>
<?php } ?>
<div class="input-wrapper-4536">
<div id="description-counter" class="counter"></div>
<label for="description" class="label-4536">ページの説明(推奨:160文字ほど)※何も入力しない場合、先頭の文字が自動で使われます。</label>
<textarea name="description" id="description" cols="60" rows="6" class="input-4536"><?php echo esc_html(get_post_meta($post->ID, 'description', true)); ?></textarea>
<div style="clear:both;"></div>
</div>
<?php $list = [
'keywords' => 'キーワード(コンマ区切り)',
];
foreach($list as $name => $description) { ?>
<div class="input-wrapper-4536">
<label for="<?php echo $name; ?>" class="label-4536"><?php echo $description; ?></label>
<input name="<?php echo $name; ?>" id="<?php echo $name; ?>" value="<?php echo esc_html(get_post_meta($post->ID, $name, true)); ?>" size="60" class="input-4536" type="text" />
<div style="clear:both;"></div>
</div>
<?php }
$list = [
'noindex' => 'NOINDEX(検索結果への表示をブロックします)',
'nofollow' => 'NOFOLLOW(リンクを除外します)ほとんどの場合、チェックを入れる必要はありません。',
];
foreach($list as $name => $description) {
$check = (get_post_meta($post->ID, $name ,true) == 1) ? 'checked' : '/' ; ?>
<div class="input-wrapper-4536">
<label for="<?php echo $name; ?>" class="label-4536"><?php echo $description; ?></label>
<span class="checkbox-4536">
<input type="checkbox" name="<?php echo $name; ?>" id="<?php echo $name; ?>" value="1" <?php echo $check; ?> >
</span>
<div style="clear:both;"></div>
</div>
<?php } ?>
<style>
.input-wrapper-4536 {
margin: 20px 0;
position: relative;
}
.label-4536 {
float: left;
margin: 0;
width: 37%;
padding: 3px 30px 3px 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.input-4536 {
float: left;
width: 63%;
margin: 0;
}
.checkbox-4536 {
float: left;
margin-top: 3px;
}
.counter {
text-align: right;
width: 100%;
}
.title-counter-length-over {
color: #f00;
font-weight: bold;
}
</style>
<?php }
// 設定の反映
add_action( 'wp_head', function() {
global $post;
$keywords = get_post_meta($post->ID,'keywords',true);
$noindex = get_post_meta($post->ID,'noindex',true);
$nofollow = get_post_meta($post->ID,'nofollow',true);
$robots = '';
if($noindex && $nofollow) $robots = '<meta name="robots" content="noindex,nofollow">';
if($noindex && !$nofollow) $robots = '<meta name="robots" content="noindex,follow">';
if(!$noindex && $nofollow) $robots = '<meta name="robots" content="nofollow">';
if(description_4536()) echo '<meta name="description" content="'.description_4536().'">';
if(is_singular()) { //記事ページ
echo $robots;
if($keywords) echo '<meta name="keywords" content="'.$keywords.'">';
}
});
// 文字数カウンター
function text_counter_4536() { ?>
<script type="text/javascript">
var list = [
'#seo_title',
'#description',
'#sns_title'
];
$(function() {
$.each(list, function(index,value) {
function counter_4536() {
var length = $(value).val().length;
$(value + '-counter').html(length);
}
counter_4536();
$(value).on('keydown keyup keypress change', counter_4536);
});
});
</script>
<?php }
add_action( 'admin_head-post.php', 'text_counter_4536' );
add_action( 'admin_head-post-new.php', 'text_counter_4536' );
//ディスクリプション設定
function description_4536() {
if(is_home()) {
$description = get_bloginfo('description') ;
} elseif(is_singular() || is_front_page()) { // 記事ページ
//カスタムフィールドで設定したディスクリプション
$custom_description = get_post_meta(get_the_ID(), 'description', true);
$custom_description = strip_tags(str_replace(array("\r\n", "\r", "\n"), '', $custom_description));
$custom_description = mb_strimwidth($custom_description, 0, 320, "...", "utf-8");
$auto_description = get_post(get_the_ID())->post_content;
$auto_description = strip_tags(str_replace(array("\r\n", "\r", "\n"), '', $auto_description));
$auto_description = mb_strimwidth($auto_description, 0, 320, "...", "utf-8");
//条件によって読み込むディスクリプションを変更
$post_description = ($custom_description) ? $custom_description : $auto_description ;
$description = $post_description;
} elseif(is_category()) { // カテゴリーページ
if(term_description()) { //カテゴリーの説明を入力している場合
$description = term_description();
} else { //カテゴリーの説明がない場合
$description = single_cat_title('', false).'の記事一覧';
}
} elseif(is_tag()) { // タグページ
if(term_description()) { //タグの説明を入力している場合
$description = term_description();
} else { //タグの説明がない場合
$description = single_tag_title('', false).'の記事一覧';
}
} elseif(is_day()) {
$description = get_the_time('Y年m月d日').'の記事一覧';
} elseif(is_month()) {
$description = get_the_time('Y年m月').'の記事一覧';
} elseif(is_year()) {
$description = get_the_time('Y年').'の記事一覧';
} elseif(is_author()) {
$description = get_queried_object()->display_name.'の記事一覧';
}
if($description) return esc_html($description);
}
// ユーザー設定に項目を追加
add_filter('user_contactmethods', function($sns) {
$sns['twitter'] = 'Twitter(twitter.com/以降)';
$sns['fb_app_id'] = 'FacebookアプリID';
return $sns;
});
// OGP設定
add_action('wp_head', 'ogp_setting_4536');
function ogp_setting_4536() {
$fb_app_id = get_the_author_meta('fb_app_id',$user_ID);
$twitter = get_the_author_meta('twitter',$user_ID);
$no_img = get_template_directory_uri().'/img/4536_logo.png'; // テーマに合わせてURL変更
global $post;
$title = wp_get_document_title();
preg_match('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $match);
$first_img = ($match) ? $match[1] : '';
if(is_singular() && get_post_meta($post->ID,'sns_title',true)) $title = get_post_meta($post->ID,'sns_title',true);
if( has_post_thumbnail() ) {
$thumbnail = wp_get_attachment_url( get_post_thumbnail_id() ); // サムネイル取得
} elseif ($first_img) {
$thumbnail = $first_img; // 記事の1番上の画像取得
} elseif ( get_site_icon_url() ) {
$thumbnail = get_site_icon_url(); // サイトアイコン取得
} else {
$thumbnail = $no_img; // NOイメージ
}
//タイトル
echo '<meta property="og:title" content="'.$title.'">'
.'<meta name="twitter:title" content="'.$title.'">';
//ディスクリプション
if(description_4536()) {
echo '<meta property="og:description" content="'.description_4536().'">'
.'<meta name="twitter:description" content="'.description_4536().'">';
}
//デフォルト画像をアイコンにしておく
$og_img = (get_site_icon_url()) ? '<meta property="og:image" content="'.get_site_icon_url().'">' : '<meta property="og:image" content="'.$no_img.'">' ;
$twitter_img = (get_site_icon_url()) ? '<meta name="twitter:image" content="'.get_site_icon_url().'">' : '<meta name="twitter:image" content="'.$no_img.'">' ;
//その他の設定を出力
echo '<meta property="og:site_name" content="'.get_bloginfo('name').'">'
.'<meta property="og:locale" content="ja_JP">';
$og_type = '<meta property="og:type" content="website">';
if($fb_app_id) echo '<meta property="fb:app_id" content="'.$fb_app_id.'">';
echo '<meta name="twitter:card" content="summary">'; //summaryをsummary_large_imageにすると画像大
if($twitter) echo '<meta name="twitter:site" content="@'.$twitter.'">';
if(is_home()) { //トップページ
$home_url = get_home_url();
echo '<meta property="og:url" content="'.$home_url.'">';
echo '<meta name="twitter:url" content="'.$home_url.'">';
} elseif(is_singular() || is_front_page()) { //記事ページ
echo '<meta property="og:url" content="'.get_the_permalink().'">';
$og_type = '<meta property="og:type" content="artcle">';
$og_img = '<meta property="og:image" content="'.$thumbnail.'">';
echo '<meta name="twitter:url" content="'.get_the_permalink().'">';
$twitter_img = '<meta name="twitter:image" content="'.$thumbnail.'">';
} else { // その他
$http = is_ssl() ? 'https://' : 'http://';
$url = esc_url($http . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
echo '<meta property="og:url" content="'.$url.'">';
echo '<meta name="twitter:url" content="'.$url.'">';
}
echo $og_type.$og_img.$twitter_img;
}
設定項目について
このコードをコピペした後のカスタムフィールド欄がこちら。
- SEO用タイトルはタイトルタグの書き換え(
<title>この部分を書き換え</title>
) - SNSタイトルはFacebook、Twitterでシェアされる時のタイトルを書き換えます。
- ページの説明はmeta description
- キーワードはmeta keywords
- NOINDEXとNOFOLLOWはそれぞれmeta robots
といった内容です。
動作確認しておりますが、念のためテスト環境での動作確認を推奨します。
OGPの画像について
OGP画像は以下の順番で画像の取得を試みます。
- アイキャッチ画像が設定されている場合はアイキャッチ画像を使用
- アイキャッチ画像がない場合は記事中の1番上の画像を使用
- 記事に画像がない場合はサイトアイコンを使用
- サイトアイコンもない場合はテーマ側で用意している画像を使用
今使っているテーマが誰かが開発しているテーマであれば特にやることはありませんが、オリジナルテーマに今回ご紹介したコードを使う場合は4のパス(URL)だけ変更してください。
コピペ直後は以下のようになっています。
$no_img = get_template_directory_uri().'/img/4536_logo.png'; // テーマに合わせてURL変更
FacebookのアプリIDとTwitterのviaについて
コードをコピペすると、ユーザー→あなたのプロフィールの画面に「Twitterの@以降の文字列」と「FacebookのアプリID」を入力する項目が追加されます。
どちらもOGPに使います。
Twitterは@以降の文字列を(僕の場合は「chef_moriawase」)。
FacebookのアプリIDについてはこちらの記事でご紹介しています。
まとめ
以上、WordPressプラグインなしでSEO対策をする方法(改良版)のご紹介でした!
All in SEO Packあたりの有名なSEOプラグインも便利ですが、けっこう余計な機能があったりするので、プラグインに不満がある方はこの機会に脱プラグインしてみてはいかがでしょうか?