診断チャートをWordPressのブロックで作成する方法

質問に答えることで結果を表示する「診断チャート」をWordPressで作成する方法を紹介します。

診断チャートを利用することでお客様ごとに最適な提案が可能となり、例えば商品を販売しているようなサイトでは売上アップにつながるかもしれません。

なお、それほど時間をかけて制作していないので、間違いがあるかもしれません。もしも参考にする場合は自己責任でお願いします。

参考
診断チャートを作るにあたって以下の記事を参考にしています。「Useful Blocks」というブロックエディター専用の便利なプラグインを共同開発している方のブログです。

診断チャートのサンプル

サンプルとして、おすすめのWordPressテーマを紹介する診断チャートを作成しました。

デモ画面

以下は、診断チャートの最初の画面です。

診断チャートのデモ画面

「どのようなサイトにWordPressテーマを使用するか」といった質問に答えていきます。「ブログ」や「ホームページ」といった回答をクリックすると次の質問に移動して、最初からやり直すことも可能です。

診断チャートの最終結果のデモ画面

最後の質問に答えると、最終結果としておすすめのテーマが表示されます。

管理画面

次に、診断チャートをページに埋め込む方法を紹介します。

診断チャートのWordPressのブロック

記事の編集ページに「診断チャート」というブロックがあるので、それをクリックします。

診断チャートのWordPressのブロックを追加

すると、診断チャートのブロックが埋め込まれて、上のようにタイトル、説明、質問、結果などを入力する項目が表示されます。

診断チャートのブロックの質問を入力

それぞれの項目に入力していきます。「行を追加」をクリックすると、質問や回答、結果を好きな数だけ増やせます。

診断チャートのブロックの結果を入力

診断チャートの結果に関しては、上のように「結果ID」と「結果」という入力項目があります。

「結果ID」の数字は左から順に選択された回答の番号を表しており、選択された回答と結果を紐づける役割があります。

例えば、結果IDに「11」と入力した場合、一つ目の質問で一つ目の回答を選択、二つ目の質問で一つ目の回答を選択した場合に表示される結果を意味します。
同様に、結果IDに「322」と入力した場合、一つ目の質問で三つ目の回答を選択、二つ目の質問で二つ目の回答を選択、三つ目の質問で二つ目の回答を選択した場合に表示される結果を意味します。

回答のパターンだけ登録する必要があるため、簡易的な診断チャートを想定しています。複雑な診断チャートは後述する別のやり方も検討してみてください。

そして、「結果」の入力項目は、最終結果に表示したい画像や文章、リンクなどをビジュアルエディターかテキストエディターを使って設定できます。

診断チャートの作り方

診断チャートは「Advanced Custom Fields」というプラグインの有料版を使用します。まずは、インストールと有効化を行いましょう。

1. 診断チャートのブロックを登録

Advanced Custom Fieldsを使うと、WordPressのブロックを自作できます。

functions.php
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に記述します。一部のパラメーターについて以下に補足します。

診断チャートのWordPressのブロックを登録

  • 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)
・レイアウト:行
・フィールドラベル:質問(※1)
・フィールド名:qa_question
・フィールドタイプ:テキスト
・必須か?:はい
・フィールドラベル:回答の一覧(※2)
・フィールド名:qa_answer_list
・フィールドタイプ:繰り返しフィールド
・必須か?:はい
・サブフィールド:回答(※3)
・レイアウト:行
・フィールドラベル:回答(※3)
・フィールド名:qa_answer
・フィールドタイプ:テキスト
・必須か?:はい
・フィールドラベル:結果の一覧
・フィールド名:qa_result_list
・フィールドタイプ:繰り返しフィールド
・必須か?:はい
・サブフィールド:結果ID(※4)
・サブフィールド:結果(※5)
・レイアウト:行
・フィールドラベル:結果ID(※4)
・フィールド名:qa_result_id
・フィールドタイプ:数値
・必須か?:はい
・フィールドラベル:結果(※5)
・フィールド名:qa_result
・フィールドタイプ:Wysiwygエディタ
・必須か?:はい
補足
「質問の一覧」のサブフィールドに「回答の一覧」というように、繰り返しフィールドが入れ子になっています。

3. 診断チャートを表示するプログラムを作成

qa-chart.php
<?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つの内容に分かれています。

・診断チャートの質問や結果を表示するPHPとHTML

Advanced Custom Fieldsの関数を使ってカスタムフィールドの値を表示しています。

the_fieldでタイトルや説明などの値を表示して、the_sub_fieldで質問や回答など繰り返しフィールドの値を表示しています。

・回答をクリックしたときに、次の質問に移動したり、結果を表示するjQuery

回答がクリックされたら、現在の質問をhideで非表示にして、次の質問をfadeInで表示しています。その際に、answerAllという変数にクリックされた回答の番号を文字列として結合しています。

そして、最後の質問の回答をクリックしたときに、answerAllと結果IDが等しい結果をfadeInで表示しています。

もしも、answerAllと等しい結果IDが見つからない場合、エラーメッセージを表示しています。

・診断チャートのデザインを整えるCSS

CSSは使用しているテーマによって多少変わるかもしれません。

参考
jQueryとCSSはacf_register_block_typeで「enqueue_style」と「enqueue_script」のパラメーターを指定することで、外部ファイルを呼び出すことも可能です。今回は、外部ファイルを呼び出すとパフォーマンスが劣化するという考えから、同一ファイル内に記載しています。

診断チャートのカスタマイズ

これまでの手順で診断チャートを表示させることができました。しかし、場合によっては問題点もあります。

例えば、今回のやり方は回答と結果の紐づけをクライアントサイドで行っているため、ブラウザの開発者ツールなどを利用してソースを見れば、アルゴリズムがばれてしまいます。

そこで、サーバーサイドで結果を決めるやり方を採用したのが以下のデモサイトです。化粧品のメーカーを想定しており、診断チャートでおすすめの化粧品を提案します。

化粧品メーカーの診断チャート

診断チャートのデザインは基本的に同じですが、質問の戻るボタンと進むボタンを追加しています。そして、最後の質問に回答すると、以下のように診断結果とおすすめの化粧品ページが表示されます。

化粧品メーカーの診断チャートの診断結果

診断チャートの作り方はそれほど変わりません。大きな違いは、formタグを使い、選択した回答をPOSTするところです。

サーバー側でPOSTされた回答をもとに、結果のページを決定します。if文などを使って自由に結果を導けるので、最初のやり方のように全ての回答パターンを登録する必要はありません。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA