質問に答えることで結果を表示する「診断チャート」をWordPressで作成する方法を紹介します。
診断チャートを利用することでお客様ごとに最適な提案が可能となり、例えば商品を販売しているようなサイトでは売上アップにつながるかもしれません。
なお、それほど時間をかけて制作していないので、間違いがあるかもしれません。もしも参考にする場合は自己責任でお願いします。
診断チャートのサンプル
サンプルとして、おすすめのWordPressテーマを紹介する診断チャートを作成しました。
デモ画面
以下は、診断チャートの最初の画面です。
「どのようなサイトにWordPressテーマを使用するか」といった質問に答えていきます。「ブログ」や「ホームページ」といった回答をクリックすると次の質問に移動して、最初からやり直すことも可能です。
最後の質問に答えると、最終結果としておすすめのテーマが表示されます。
管理画面
次に、診断チャートをページに埋め込む方法を紹介します。
記事の編集ページに「診断チャート」というブロックがあるので、それをクリックします。
すると、診断チャートのブロックが埋め込まれて、上のようにタイトル、説明、質問、結果などを入力する項目が表示されます。
それぞれの項目に入力していきます。「行を追加」をクリックすると、質問や回答、結果を好きな数だけ増やせます。
診断チャートの結果に関しては、上のように「結果ID」と「結果」という入力項目があります。
「結果ID」の数字は左から順に選択された回答の番号を表しており、選択された回答と結果を紐づける役割があります。
回答のパターンだけ登録する必要があるため、簡易的な診断チャートを想定しています。複雑な診断チャートは後述する別のやり方も検討してみてください。
そして、「結果」の入力項目は、最終結果に表示したい画像や文章、リンクなどをビジュアルエディターかテキストエディターを使って設定できます。
診断チャートの作り方
診断チャートは「Advanced Custom Fields」というプラグインの有料版を使用します。まずは、インストールと有効化を行いましょう。
1. 診断チャートのブロックを登録
Advanced Custom Fieldsを使うと、WordPressのブロックを自作できます。
function custom_acf_block_types() {
if(function_exists('acf_register_block_type')) {
acf_register_block_type(array(
'name' => 'qa_chart',
'title' => '診断チャート',
'description' => '診断チャートを挿入します。',
'render_template' => 'qa-chart.php',
'category' => 'common',
'icon' => 'admin-generic',
'keywords' => array('qa_chart', '診断チャート'),
'mode' => 'auto',
));
}
}
add_action('acf/init', 'custom_acf_block_types');
acf_register_block_typeという専用の関数が用意されているので、functions.phpに記述します。一部のパラメーターについて以下に補足します。
- render_template
ブロックが表示されるときに呼ばれるテンプレートファイル。 - category
ブロックの一覧表示で使われる分類。標準では、common、formatting、layout、widgets、embedが用意されており、自作のブロックカテゴリーを登録することも可能。 - icon
ブロックの一覧表示で使われるアイコン。「Dashicons」というWordPressで用意されているアイコンを使うか、自作のSVGアイコンを指定できます。 - keywords
ブロックを検索するときのキーワード。 - mode
記事の編集画面におけるブロックの表示モード。
preview:常にブロックのプレビュー(実際の画面)が表示され、編集画面のサイドバーに入力欄が表示される。
auto:ブロックのプレビューが表示されるが、ブロックをクリックすると入力欄に変わる。
edit:常にブロックの入力欄が表示され、プレビューは表示されない。
その他にも、いくつかパラメーターが用意されています。詳しくは公式ホームページをご確認ください。
2. 診断チャートのカスタムフィールドを登録
以下のように、Advanced Custom Fieldsを使ってカスタムフィールドを登録します。位置のルールでは、「1. 診断チャートのブロックを登録」の手順で登録したブロックを選択します。
カスタムフィールドの内容は以下の通りです。
・フィールド名:qa_title
・フィールドタイプ:テキスト
・必須か?:はい
・フィールド名:qa_description
・フィールドタイプ:テキストエリア
・必須か?:はい
・行数:2
・フィールド名:qa_question_list
・フィールドタイプ:繰り返しフィールド
・必須か?:はい
・サブフィールド:質問(※1)
・サブフィールド:回答の一覧(※2)
・レイアウト:行
・フィールド名:qa_question
・フィールドタイプ:テキスト
・必須か?:はい
・フィールド名:qa_answer_list
・フィールドタイプ:繰り返しフィールド
・必須か?:はい
・サブフィールド:回答(※3)
・レイアウト:行
・フィールド名:qa_answer
・フィールドタイプ:テキスト
・必須か?:はい
・フィールド名:qa_result_list
・フィールドタイプ:繰り返しフィールド
・必須か?:はい
・サブフィールド:結果ID(※4)
・サブフィールド:結果(※5)
・レイアウト:行
・フィールド名:qa_result_id
・フィールドタイプ:数値
・必須か?:はい
・フィールド名:qa_result
・フィールドタイプ:Wysiwygエディタ
・必須か?:はい
3. 診断チャートを表示するプログラムを作成
<?php
if(have_rows('qa_question_list')) :
?>
<div class="qa-chart">
<p class="qa-chart__title"><?php the_field('qa_title'); ?></p>
<p class="qa-chart__description"><?php the_field('qa_description'); ?></p>
<?php
$question_count = 1;
while(have_rows('qa_question_list')) :
the_row();
?>
<div id="<?php echo $question_count; ?>" class="qa-chart__question">
<p><?php the_sub_field('qa_question'); ?></p>
<?php
if(have_rows('qa_answer_list')) :
?>
<ul>
<?php
$answer_count = 1;
while(have_rows('qa_answer_list')) :
the_row();
?>
<li data-answer="<?php echo $answer_count; ?>"><?php the_sub_field('qa_answer'); ?></li>
<?php
$answer_count++;
endwhile;
?>
</ul>
<?php
endif;
?>
</div>
<?php
$question_count++;
endwhile;
?>
<?php
if(have_rows('qa_result_list')) :
while(have_rows('qa_result_list')) :
the_row();
?>
<div data-result="<?php the_sub_field('qa_result_id'); ?>" class="qa-chart__result">
<p class="qa-chart__result-title">最終結果</p>
<p><?php the_sub_field('qa_result'); ?></p>
</div>
<?php
endwhile;
endif;
?>
<div class="qa-chart__error">申し訳ありませんが、結果が見つかりませんでした。</div>
<p class="qa-chart__re-start">最初からやり直す</p>
</div>
<?php
endif;
?>
<script type="text/javascript">
jQuery(function($){
let answerAll = '';
const questionCount = $('.qa-chart__question').length;
$('.qa-chart li').click(function() {
$(this).closest('div').hide();
const currentQuestion = parseInt($(this).closest('div').attr('id'));
const answer = $(this).data('answer');
answerAll += answer;
if(questionCount == currentQuestion) {
if($('[data-result="' + answerAll + '"]').length) {
$('[data-result="' + answerAll + '"]').fadeIn();
}else {
$('.qa-chart__error').fadeIn();
}
}else {
$('#' + (currentQuestion + 1)).fadeIn();
}
return false;
})
$('.qa-chart__re-start').click(function() {
$('.qa-chart > div').hide();
answerAll = '';
$('.qa-chart__question:first-of-type').fadeIn();
return false;
})
});
</script>
<style type="text/css">
:root {
--color-qa-chart: #fdb6b6;
--color-qa-chart_bg: #fef0f0;
}
.qa-chart{
margin:0 auto 2rem;
padding: 2.5em 2em;
max-width: 600px;
background-color: var( --color-qa-chart_bg);
box-shadow: 0 3px 5px rgba(0,0,0,.07);
font-size: 0.9em;
}
.qa-chart__title {
background-color: var( --color-qa-chart);
color: #fff;
font-weight: bold;
padding: 0.8em 1em;
margin-bottom: 1.5em !important;
text-align:center;
}
.qa-chart__description {
margin-bottom: 2em !important;
}
.qa-chart > div {
display: none;
}
.qa-chart__question:first-of-type {
display: block;
}
.qa-chart__question > p {
margin: 2em 0 0 !important;
padding: 0.8em 1em 0.8em 4.3em !important;
background: #fff;
position: relative;
}
.qa-chart__question > p:before{
content: "Q";
background-color: var( --color-qa-chart);
position: absolute;
left: 0;
top: 0;
color: #fff;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 1.1em;
min-width: 48px;
}
.qa-chart__question > ul {
margin: 2em 0 0 !important;
padding-left: 1.5em !important;
list-style: none;
}
.qa-chart__question > ul li {
cursor: pointer;
background: #fff;
display: block;
margin-top: 2em !important;
padding: 0.8em !important;
box-shadow: 0 3px 5px rgba(0,0,0,.07);
}
.qa-chart__question > ul li:hover{
outline: 3px solid var( --color-qa-chart);
}
.qa-chart__result{
background:#fff;
padding:1.6em 2em 2em;
}
.qa-chart__result p {
margin-bottom: 0.3em;
font-size: 1.05em;
}
.qa-chart__result img {
margin-bottom: 0.3em;
}
.qa-chart__result-title {
color: var( --color-qa-chart);
font-size: 1.1em;
font-weight:bold;
padding-bottom: 0.8em;
margin: 0 0 1.4em !important;
border-bottom: 1px solid var( --color-qa-chart);
}
.qa-chart__re-start {
text-align: center;
margin: 2.5em 5em !important;
box-shadow: 0 3px 5px rgba(0,0,0,.15);
color: #fff;
font-weight: bold;
padding: 0.6em 0;
border-radius: 3px;
cursor: pointer;
background: var( --color-qa-chart);
}
.qa-chart__re-start:hover{
opacity: 0.8;
}
.qa-chart__error {
background: #fff;
padding: 1em;
}
@media screen and (max-width: 560px) {
.qa-chart{
padding: 1.8em 1.3em !important;
}
.qa-chart__description {
margin-bottom: 1.5em !important;
}
.qa-chart__question > p {
margin-bottom: 1.5em !important;
padding: 0.8em 1em 0.8em 3.3em !important;
}
.qa-chart__question > p:before{
min-width: 32px;
}
.qa-chart__question > ul {
margin: 1.4em 0 0 !important;
}
.qa-chart__question > ul li {
margin-top: 1.5em !important;
}
.qa-chart__result {
padding: 1.2em 1.4em 1.4em !important;
}
.qa-chart__re-start {
margin: 1.8em 5em 3em !important;
}
}
</style>
上記のファイルをテーマにアップロードすれば、診断チャートが表示されると思います。
どのような処理をしているか簡単に補足します。上から順に大きく3つの内容に分かれています。
Advanced Custom Fieldsの関数を使ってカスタムフィールドの値を表示しています。
the_fieldでタイトルや説明などの値を表示して、the_sub_fieldで質問や回答など繰り返しフィールドの値を表示しています。
回答がクリックされたら、現在の質問をhideで非表示にして、次の質問をfadeInで表示しています。その際に、answerAllという変数にクリックされた回答の番号を文字列として結合しています。
そして、最後の質問の回答をクリックしたときに、answerAllと結果IDが等しい結果をfadeInで表示しています。
もしも、answerAllと等しい結果IDが見つからない場合、エラーメッセージを表示しています。
CSSは使用しているテーマによって多少変わるかもしれません。
診断チャートのカスタマイズ
これまでの手順で診断チャートを表示させることができました。しかし、場合によっては問題点もあります。
例えば、今回のやり方は回答と結果の紐づけをクライアントサイドで行っているため、ブラウザの開発者ツールなどを利用してソースを見れば、アルゴリズムがばれてしまいます。
そこで、サーバーサイドで結果を決めるやり方を採用したのが以下のデモサイトです。化粧品のメーカーを想定しており、診断チャートでおすすめの化粧品を提案します。
診断チャートのデザインは基本的に同じですが、質問の戻るボタンと進むボタンを追加しています。そして、最後の質問に回答すると、以下のように診断結果とおすすめの化粧品ページが表示されます。
診断チャートの作り方はそれほど変わりません。大きな違いは、formタグを使い、選択した回答をPOSTするところです。
サーバー側でPOSTされた回答をもとに、結果のページを決定します。if文などを使って自由に結果を導けるので、最初のやり方のように全ての回答パターンを登録する必要はありません。