「テイクアウト岐阜」というウェブサービスを立ち上げた経緯と仕組みとコード

2020年4月13日に、「テイクアウト岐阜(https://takeout-gifu.com)」というウェブサービスを公開しました。

この記事では、このウェブサービス(なぜウェブサービスと呼んでいるのかも含めて)を立ち上げたのか、裏側はどうなっているのか(見る人が見ればわかるだろうけど)、どんな仕組みになっていて、どんなコードを書いているのかをご紹介していこうと思います。

立ち上げまでの経緯

個人的に新型コロナウイルスの感染拡大のニュースを1月末くらいから追いかけていました。

というのも、CoderDojo岐阜やGifu WordPress Meetupの開催の是非を検討しないといけないので、止むを得ずチェックという感じでした。

プライベートでも、長男の保育所卒園と小学校入学などもあり、そちらも関係して継続的な情報収集を行なっていました。

海外の情報収集

また、ロンドンに2年住んでいたことがあり、その時に友人などからSNS経由で状況を見せてもらえることもあり、日本国内の状況に加えて、欧米における感染拡大からのロックダウン、経済活動ストップ、店舗経営者の対応方法なども、自然と情報を収集できていました。

その流れで、海外の飲食店さんの動きに関する情報も得ていました。ロンドンやニューヨークなどで飲食店がテイクアウトのみの営業は可能だという情報なども得ていましたので、日本でもこういう動きがくるのかなぁと漠然と考えていました。

外出自粛の流れが日本にも来た

遅かれ早かれではありましたが、日本にも本格的な外出自粛の流れを感じられるようになってきました。そのあたりのタイミングで、確かGoogle Trendsなどでテイクアウトに関する検索ボリュームを一通り調べた記憶があります。

この週くらいに、こういう数字を確認していた記憶があります。

やるかやらないか

こちらの結果から、日本での検索ボリュームでも増加が予想されます。また、同様のサービスも乱立が予想されました。

そこで迷ったのが「やるかやらないか」です。何事も分岐点はありますが、まず最初の分岐点はこれです。

しかし、やらなければ何も得られないので、成功・失敗は考えず「まずはやってみる」ことにしました。こういった判断はいつも難しいし、腰が重いです。そして、やらない理由を常に考えてしまいます。

しかし、今回はなぜか素早く動けました。何かに背中を押されたのかもしれませんね。

裏側はどうなっているのか

まず、ソースコードを見れば誰でもわかる範囲で言うと、

  • WordPressを使っている
  • テーマは「SWELL」で子テーマにてカスタマイズ

という作りで出来ています。

このウェブサービスでできること

このウェブサービスでは以下のことができるようになっています。

  1. 岐阜県下のテイクアウト情報を閲覧できる
  2. 飲食店経営者が無料アカウントを作ることで自身店舗ページの情報を自由に編集することができる(クーポン発行も可能)

この2つ目の機能を有しているため、敢えてウェブサービスと呼ぶようにしています。

利用方法

岐阜県下のテイクアウト情報を閲覧できる

こちらは通常のウェブメディアとして利用するのと一緒なので、ウェブサイトを閲覧することで情報収集をすることができます。

また、店舗情報はカスタム投稿ではなく投稿で管理していて、市町村情報はカテゴリーで分別しています。ジャンルに関してはタグを利用して分別できるようにしています。

飲食店経営者がアカウントを作りページを編集できるようになるまでの流れ

  1. 無料アカウントを作成(独自に作った店舗情報管理者用権限にてWordPress新規ユーザー作成)
  2. 管理画面にログイン
  3. 管理画面内にある「新規ページ作成依頼」ボタンを押すとGoogleフォームに遷移し店舗情報を入力
  4. ウェブサービス管理者Slackに情報が通知される
  5. 送信されてきた情報をもとに店舗ページを作成し、管理権限を依頼者に付与

使用しているプラグイン一覧

Adminimize

権限ごとに管理画面内メニューの表示・非表示を管理するために使用しています。

Akismet Anti-Spam 

言わずもがな。

All-in-One WP Migration

下の有料エクステンションを利用してバックアップを自動作成しています。

All-in-One WP Migration Dropbox Extension

細かいスケジューリングも指定できて、Dropboxにバックアップデータを指定したリビジョン分保管しておくことができます。

Disable Comments

とりあえずコメント機能を活用することは考えていないので、こいつでサクッと機能を停止しておきます。

Google XML Sitemaps

親テーマにSWELLを利用していますが、そちらではサイトマップ送信にこちらを推奨しているようでしたので採用しました。

SEO SIMPLE PACK

SWELL作者が作成しているSEO設定用プラグインです。GOOD。

Show Current Template

コアに組み込まれても良いのでは?と思っている鉄板プラグインです。表示しているページがどんなテンプレートファイルを読み込んでいるかを確認できる優れもの。

Site Kit by Google

各種Googleのサービス情報を管理画面などで確認することもできるもの。

SiteGuard WP Plugin

ログインURLを公開するので、ログイン画面のURL変更とログイン時のひらがな画像認証を入れたかったので導入しました。

User Role Editor

みなさんご存知のWordPressユーザー権限を管理する鉄板プラグインです。functions.phpに書いてもいいんですが、こちらを使ってサクッとやることも多いです。

WP Revisions Control

WordPressを普段利用されていない方もユーザー登録されることも予想されるので、リビジョンがあまりにも貯まらないように管理するために入れました。

リビジョンというのは、ページの保存履歴を残しておくもので、リビジョンが残っていれば過去の状態に戻すことができるものです。便利は便利なんですが、あまりにもデータを持っておくと重くなるので。

WP User Avatar

ユーザー登録していただいた方がみなさんスムーズにユーザー画像をGravatorで設定できるとは思えなかったので、簡単に画像を設定できるようにこちらを採用しています。

裏側で使用しているソースコードなど

ここからはプラグインでは実装せずコードにて取り入れた機能とサンプルコードの紹介をしていこうと思います。

子テーマ作成

まずは子テーマを作成して、style.cssにこのように記述します。

/**
Theme Name: takeout-gifu.com
Author: Koji Kuno
Description: 岐阜テイクアウト情報まとめウェブサイト用の子テーマ
Template: swell
 */

あとはfunctions.phpを用意しておきましょう。

タスクを回す部分

npmとgulpでタスクを管理しています。

package.jsonのスクリプト部分はこんな感じです。

{
  ....
  "scripts": {
    "block:clean": "rimraf blocks/build",
    "block:build:js": "wp-scripts build blocks/src/blocks.js --output-path=blocks/build",
    "block:build:css": "node-sass blocks/src/blocks.scss -o blocks/build && postcss blocks/build/*.css -r",
    "block": "npm run block:clean && npm-run-all -s block:build:*",
    "start": "gulp"
  },
  ....
}

段落ブロックに拡張スタイルを利用しているので@wordpress/scriptを利用しています。あとはGulpですね。

タスクランナーに使用しているgulpfile.jsについては別記事で紹介しているような内容なので割愛します。

子テーマ側からスタイルシートの読み込み

add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
function theme_enqueue_styles() {
	wp_enqueue_style(
		'parent-style',
		get_template_directory_uri() . '/style.css' );

	wp_enqueue_style(
		'child-style',
		get_stylesheet_directory_uri() . '/css/style.min.css',
		array( 'parent-style' )
	);
}

鉄板ですね。コピペでご利用いただけるかと思います。

ただ、Gulpでコンパイルしたスタイルはcssディレクトリに保存するようにしているため、読み込みファイルパスはルートのstyle.cssにはなっていませんので悪しからず。

管理画面用スタイルを読み込む

function tog_admin_css() {
	wp_enqueue_style( 'tog_admin_style', get_stylesheet_directory_uri() . '/css/admin.min.css' );
	if ( ! current_user_can( 'administrator' ) ) {
		wp_enqueue_style(
			'shop-owner-style',
			get_stylesheet_directory_uri() . '/css/shop-owner.min.css'
		);
	}
}
add_action( 'admin_enqueue_scripts', 'tog_admin_css' );

ログイン画面カスタマイズ用スタイルを読み込む

function tog_login_style() {
	wp_enqueue_style(
		'login-style',
		get_stylesheet_directory_uri() . '/css/login.min.css'
	);
}
add_action( 'login_enqueue_scripts', 'tog_login_style' );

管理者バー(アドミンバー)のカスタマイズ

function tog_remove_adminbar_menus( $wp_admin_bar ) {
	if ( current_user_can( 'administrator' ) ) {
		return;
	}
	$wp_admin_bar->remove_menu( 'wp-logo' );
	$wp_admin_bar->remove_menu( 'new-content' );
}
add_action( 'admin_bar_menu', 'tog_remove_adminbar_menus', 99 );

WordPressに慣れていないユーザーが迷わないように、できることをやるために最低限必要な選択肢だけを残すためのカスタマイズをしています。

管理画面ダッシュボードのカスタマイズ

function tog_remove_dashboard_widget() {
	remove_meta_box( 'dashboard_activity', 'dashboard', 'normal' );
	remove_meta_box( 'dashboard_primary', 'dashboard', 'side' );
	remove_meta_box( 'dashboard_right_now', 'dashboard', 'normal' );
	remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );
}
add_action( 'wp_dashboard_setup', 'tog_remove_dashboard_widget' );

とりあえずサクッと消してあります。

ダッシュボードに自作ウィジェットを設置

function tog_custom_dashboard_widget() {
	wp_add_dashboard_widget(
		'tog_dashboard_news_widget',
		'運営からのお知らせ',
		'tog_dashboard_news'
	);
	wp_add_dashboard_widget(
		'tog_dashboard_new_page_order_widget',
		'新規ページ作成依頼はこちら',
		'tog_dashboard_new_page_order'
	);
	wp_add_dashboard_widget(
		'tog_dashboard_owner_menu_widget',
		'店舗情報管理者専用メニュー',
		'tog_dashboard_owner_menu'
	);
	wp_add_dashboard_widget(
		'tog_dashboard_owner_manual_widget',
		'操作マニュアル',
		'tog_dashboard_owner_manual'
	);
}
add_action( 'wp_dashboard_setup', 'tog_custom_dashboard_widget' );

大きく分けて4つのウィジェットが用意されています。

  • 運営からのお知らせ(投稿カテゴリー「お知らせ」の投稿のみリスト表示)
  • 新規ページ作成依頼はこちら(Googleフォームへ遷移)
  • 店舗情報管理者専用メニュー(投稿一覧閲覧とプロフィール編集へリンク)
  • 操作マニュアル(SWELLの基本的な操作方法マニュアルへのリンク)

各ウィジェットに関してはこのような単純な記述です。

function tog_dashboard_new_page_order() {
	echo '<p>テイクアウト岐阜では新規ページの作成は運営側で行います。<br>複数店舗の掲載をご希望の方は各店舗ごとの申請が必要となります。</p>';

	...
}

お知らせをリスト表示させるウィジェットはこんな感じで書いています。

function tog_dashboard_news() { ?>
	<ul>
     <?php
          global $post;
          $args = array(
          		'numberposts' => 10,
	            'category_name' => 'news',
		  );

          $myposts = get_posts( $args );
        foreach( $myposts as $post ) :  setup_postdata($post); ?>
            <li><? the_date('Y年n月d日'); ?> <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
      <?php endforeach; ?>
   </ul>

<?php }

クイック編集を出来なくする

function hide_quickedit( $actions ) {
	unset( $actions['inline hide-if-no-js'] );
	return $actions;
}
add_filter( 'post_row_actions', 'hide_quickedit' );

ユーザーが迷うのを避けるためにクイック編集機能を止めます。

ユーザー登録画面の文言を変更

function custom_gettext( $translated, $text, $domain ) {
	$custom_translates = array(
		'default' => array(
			'このブログに登録' => 'テイクアウト岐阜に新規登録する',
		)
	);
	if ( isset( $custom_translates[$domain] ) ) {
		$translated = str_replace( array_keys( $custom_translates[$domain] ), $custom_translates[$domain], $translated );
	}
	return $translated;
}
add_filter( 'gettext', 'custom_gettext', 10, 3 );

デフォルトだと「このブログに登録」とか出るんですが、わかりやすいように文言を変更しておきます。

自分がアップロードした画像以外は表示させない

function tog_display_only_self_uploaded_medias( $query ) {
	if ( ( $user = wp_get_current_user() ) && ! current_user_can( 'administrator' ) ) {
		$query['author'] = $user->ID;
	}
	return $query;
}
add_action( 'ajax_query_attachments_args', 'tog_display_only_self_uploaded_medias' );

他のお店の画像を使えたりするのはよくないので、そもそも選べないようにしています。

店舗情報管理者がパーマリンクやカテゴリー、タグなどを変更できないようにする

function tog_gutenberg_register_files() {
	if ( current_user_can( 'shop-owner' ) ) {
		// script file
		wp_register_script(
			'block-script',
			get_stylesheet_directory_uri() . '/js/block-script.js', // adjust the path to the JS file
			array( 'wp-blocks', 'wp-edit-post' )
		);
		// register block editor script
		register_block_type( 'cc/ma-block-files', array(
			'editor_script' => 'block-script'
		) );
	}
}
add_action( 'init', 'tog_gutenberg_register_files' );
"use strict";

wp.data.dispatch('core/edit-post').removeEditorPanel('taxonomy-panel-category');
wp.data.dispatch('core/edit-post').removeEditorPanel('taxonomy-panel-post_tag');
wp.data.dispatch('core/edit-post').removeEditorPanel('featured-image');
wp.data.dispatch('core/edit-post').removeEditorPanel('post-link');
wp.data.dispatch('core/edit-post').removeEditorPanel('page-attributes');
wp.data.dispatch('core/edit-post').removeEditorPanel('post-excerpt');
wp.data.dispatch('core/edit-post').removeEditorPanel('discussion-panel');

標準ブロックに拡張スタイルを設定

require_once get_stylesheet_directory(). '/blocks/blocks.php';
function extending_blocks_enqueue() {
	wp_enqueue_script(
		'extending-blocks-script',
		get_stylesheet_directory_uri() . '/blocks/build/blocks.js',
		array( 'wp-blocks' )
	);
}
add_action( 'enqueue_block_editor_assets', 'extending_blocks_enqueue' );

function extending_blocks_styles() {
	wp_enqueue_style(
		'extending-blocks-style',
		get_stylesheet_directory_uri() . '/blocks/build/blocks.css'
	);
}
add_action( 'enqueue_block_assets', 'extending_blocks_styles' );

ビルドされた拡張スタイル用のJSとCSSを読み込んでいます。ビルドする前のソースは、

wp.blocks.registerBlockStyle(
    'core/paragraph',
    {
        name: 'coupon-ticket',
        label: 'クーポンチケット'
    }
);
.is-style-coupon-ticket {
  position: relative;
  padding: 40px 20px 20px;
  border: 1px solid #ffa639;
  border-radius: 5px;
  &:after {
    content: "クーポン情報";
    display: inline-block;
    position: absolute;
    top: 0;
    left: 0;
    background-color: #ffa639;
    padding: 5px 15px;
    border-radius: 3px;
    font-size: 14px;
    color: white;
    line-height: 1;
  }
}

こちらのソースをpackage.jsonscriptで指定してあるblockを実行することで、buildディレクトリにビルドされるという感じになります。拡張スタイル作るのは鬼楽です。

まとめ

ここまで、テイクアウト岐阜を立ち上げた経緯と技術的なことを書いてきました。これらのソースコードを元に組めば同じようなサイトを作ることは難しくないでしょう。どんどん人のためになるのであれば使っていただければと思います。

しかし、岐阜のテイクアウト情報に関しては地域の大きなWeb制作会社さんも参入してきたりと、情報が混沌としている状況かなと感じています。

個人が本業の空いた時間にコツコツを進めているペースト、法人が隙間時間に開発するのでは、リソースの違いは明らかだしアイデアの閉鎖感も個人の方が強いでしょう。

個人でこういったものを作る際には、常日頃方色々な方と意見交換をできる関係を持っておくべきだと強く感じました。

今後のビジョンとしては、テイクアウト情報をマンパワーで掲載を続けると共に「テイクアウトの先」に関する情報も提供できるように発信していきたいと思います。

具体的には、個人的な感覚ですが飲食店さんがテイクアウトサービスを提供する期間は今後も続くだろうと考えています。加えて、店舗内での飲食される客足というのは見込めないでしょう。そうなると、テイクアウトだけで以前のような売り上げを計上しようとすることは難しいです。

それに変わる何かを早急に考えないと、然るべき段階で営業ができなくなる恐れすらあります。ですので、そういった点も情報収集して、いろいろなことを飲食店さんが考えられるようなきっかけになる情報を提供できればと考えています。

そういう意味では「テイクアウト」に固執しているわけではありません。ニーズに沿った情報発信を心がけていきたいと思います。

よろしければ、岐阜県下のお近くの飲食店さんにご紹介いただければ幸いです。

書籍を出版しました!

WordPress デフォルトテーマ Twenty Twenty-Four を使って、シンプルなブログやポートフォリオサイト、そしてコーポレートサイトを作りながら、ブロックテーマやサイトエディターの基本を理解することができます。