Amazonで商品を見る セール会場へ

Snow Monkey Forms│お問い合わせ内容をスプレッドシートに書き込む方法

お問い合わせフォーム用のプラグインSnow Monkey Formsですが、基本、お問い合わせ内容はメールで送信されます。

それだけでなく、スプレッドシートにも書き込みたいときに役に立つカスタマイズを紹介します。

Snow Monkey Forms の設定・カスタマイズ方法はこちらにまとめています。

目次

著者

WEB制作をしているデジタルノマド
WordPressのカスタマイズが好きで、色々と自作しています。

WordPressのカスタマイズに困ったらご相談ください!

Snow Monkey Formsでお問い合わせ内容をスプレッドシートに書き込むカスタマイズ

やり方は意外と簡単です。

Snow Monkey Formsの作成

普通にプラグインを入れてお問い合わせフォームを作ります。

Snow Monkey Formsのプラグインを使って作成したお問い合わせフォームの編集画面。

お問い合わせ項目に合わせてNAME属性に名前をつけておきましょう。

お問い合わせフォームの項目に合わせてNAME属性を設定している画面。

今回は以下に設定しました。

項目NAME
お名前your-name
Eメールyour-email
メッセージyour-message

スプレッドシートの作成

スプレッドシートを用意します。

シート名はお問い合わせにしました。

専用シートの1行目を「リクエストID、日時、フォームID、お名前、メールアドレス、メッセージ」の6列にします。既存データへ上書きせず、テスト用の別シートを用意してください。

リクエストID日時フォームIDお名前メールアドレスメッセージ

GASの作成

スプレッドシートの拡張機能からApps Scriptを選択

スプレッドシートの拡張機能メニューからApps Scriptを選択する手順。

以下はPOST専用の受信コードです。既存の実データを使わず、まずテスト用シートで確認してください。

いか、詳細です。

まずは下記のコードをコピペします。

シート名はお問い合わせにしています。

function output_(value) {
  return ContentService.createTextOutput(JSON.stringify(value)).setMimeType(ContentService.MimeType.JSON);
}
function doGet() { return output_({ok: false}); }
function doPost(e) {
  let lock;
  try {
    if (!e || !e.postData || e.postData.contents.length > 20000) return output_({ok: false});
    const data = JSON.parse(e.postData.contents);
    const props = PropertiesService.getScriptProperties();
    const secret = props.getProperty('WAZA_SMF_SECRET');
    if (!secret || !/^[0-9a-f]{64}$/i.test(secret) || data.secret !== secret) return output_({ok: false});
    if (!/^[0-9a-f-]{36}$/i.test(data.request_id || '') || data.form_id !== 115) return output_({ok: false});
    for (const [key, max] of [['name',200],['email',320],['message',5000]]) {
      if (typeof data[key] !== 'string' || data[key].length > max) return output_({ok: false});
    }
    const sheetId = props.getProperty('WAZA_SMF_SHEET_ID');
    if (!sheetId) return output_({ok: false});
    lock = LockService.getScriptLock();
    if (!lock.tryLock(5000)) return output_({ok: false});
    const sheet = SpreadsheetApp.openById(sheetId).getSheetByName('お問い合わせ');
    if (!sheet) return output_({ok: false});
    const last = sheet.getLastRow();
    if (last > 1 && sheet.getRange(2,1,last-1,1).createTextFinder(data.request_id).matchEntireCell(true).findNext()) {
      return output_({ok: true, duplicate: true});
    }
    const text = value => /^[\s]*[=+@-]/.test(value) ? "'" + value : value;
    sheet.appendRow([data.request_id,new Date(),data.form_id,text(data.name),text(data.email),text(data.message)]);
    SpreadsheetApp.flush();
    return output_({ok: true});
  } catch (_) {
    return output_({ok: false}); // 本文や秘密値をログに出さない
  } finally {
    if (lock && lock.hasLock()) lock.releaseLock();
  }
}

コードがコピペできたのであれば、新しいデプロイを選択。

Apps Scriptで新しいデプロイを選択する画面。

ウェブアプリの種類を選択

WordPressから非ログインのHTTPリクエストを受ける構成です。公開前に、スクリプトプロパティへ WAZA_SMF_SECRET(安全な乱数で生成した64桁の16進文字列)と WAZA_SMF_SHEET_ID(保存先のスプレッドシートID)を登録します。コードは秘密値が一致しないPOSTと、すべてのGETを拒否します。組織で匿名Webアプリを許可していない場合は、この構成を使わないでください。

最後にデプロイボタンを押します。

デプロイ時の実行者・アクセス範囲・スプレッドシートへの権限を確認してください。シート自体を一般公開する必要はありません。

デプロイ時に求められるアクセス承認の画面。

承認が終わるとウェブアプリのURLが発行されます。

URLはコピーしてメモしておきましょう。

デプロイ完了後に発行されたウェブアプリのURL画面。

functions.phpの設定

WordPressに戻ります。

バックアップ後、子テーマのfunctions.phpへ以下を追加します。対象フォームIDの115はPHPとGASの両方で変更してください。PHPではskipフィルターの判定、after_sendの判定、送信データのform_idの3か所をそろえます。メールをスキップするフィルターがある場合は、その処理を先に登録してください。スキップが有効な送信はシートへコピーしません。秘密値やGASのURLをフロント側JavaScriptへ出力しません。

エラーが怖い人はCode Snippetsのプラグインを入れて、そこからコードを挿入しましょう。

wp-config.phpの編集終了行より前に、次の定数を定義します。URLは自分の /exec URL、秘密値はGASと同じ64桁の乱数へ置き換えます。例のプレースホルダーのままでは送信されません。公開リポジトリに秘密値を保存しないでください。

WordPressのテーマエディタやCode Snippetsでコードを挿入する設定画面。
define( 'WAZA_SMF_GAS_URL', 'https://script.google.com/macros/s/REPLACE_WITH_DEPLOYMENT_ID/exec' );
define( 'WAZA_SMF_GAS_SECRET', 'REPLACE_WITH_RANDOM_64_HEX_CHARACTERS' );
// 同じ送信処理のスキップ結果を保持する(リクエスト内だけ)。
$waza_smf_sheet_state = new SplObjectStorage();
add_filter( 'snow_monkey_forms/administrator_mailer/skip', function ( $skip, $responser, $setting ) use ( $waza_smf_sheet_state ) {
    if ( 115 === (int) $setting->get( 'form_id' ) ) {
        $waza_smf_sheet_state[ $responser ] = (bool) $skip;
    }
    return $skip;
}, PHP_INT_MAX, 3 );

add_action( 'snow_monkey_forms/administrator_mailer/after_send', function ( $sent, $responser, $setting, $parser ) use ( $waza_smf_sheet_state ) {
    if ( ! $sent || 115 !== (int) $setting->get( 'form_id' ) ) return;

    if ( ! $waza_smf_sheet_state->contains( $responser ) ) return;
    $skipped = $waza_smf_sheet_state[ $responser ];
    $waza_smf_sheet_state->detach( $responser );
    if ( $skipped ) return; // スキップの true をメール成功として扱わない。
    if ( ! defined( 'WAZA_SMF_GAS_URL' ) || ! defined( 'WAZA_SMF_GAS_SECRET' ) || ! preg_match( '/^[0-9a-f]{64}$/i', WAZA_SMF_GAS_SECRET ) ) return;
    if ( ! preg_match( '~^https://script\.google\.com/macros/s/[A-Za-z0-9_-]+/exec$~', WAZA_SMF_GAS_URL ) ) return;
    $values = $responser->get_all();
    $payload = array( 'secret' => WAZA_SMF_GAS_SECRET, 'request_id' => wp_generate_uuid4(), 'form_id' => 115 );
    foreach ( array( 'name' => 'your-name', 'email' => 'your-email', 'message' => 'your-message' ) as $key => $field ) {
        $value = $values[ $field ] ?? '';
        if ( ! is_string( $value ) ) return;
        $payload[ $key ] = $value;
    }
    $response = wp_remote_post( WAZA_SMF_GAS_URL, array(
        'timeout' => 10,
        'headers' => array( 'Content-Type' => 'application/json' ),
        'body' => wp_json_encode( $payload ),
    ) );
    $ok = ! is_wp_error( $response ) && 200 === wp_remote_retrieve_response_code( $response );
    $body = $ok ? json_decode( wp_remote_retrieve_body( $response ), true ) : null;
    if ( ! is_array( $body ) || true !== ( $body['ok'] ?? false ) ) {
        error_log( 'WAZA SMF sheet copy failed. Request: ' . $payload['request_id'] );
    }
}, 10, 4 );

テスト

以上の設定が終わったらテストしましょう。

設定完了後にお問い合わせフォームからテスト送信を行う画面。

架空の名前・example.comのアドレスで送信し、メール成功後にシートへ1行入ること、秘密値が違う要求は書き込まれないこと、同じリクエストIDの再送は重複しないことを確認します。先頭が「=」などの値は数式化を避けるため文字列として保存します。

まとめ

まとめると今回のカスタマイズは以下のことをやっています。

  • Snow Monkey Forms のお問い合わせフォーム送信を検知
  • 入力された内容(名前・メール・メッセージ)とフォームIDを取得
  • Google Apps Script(GAS)を通じて、Googleスプレッドシートに自動で1行ずつ書き込み

このカスタマイズをベースにAIなど使って応用してみてください。

検証範囲:ローカルWordPressで送信失敗時・別フォームの除外とPOST本文の構築、GAS相当のスタブで認証・型・長さ・重複・数式対策を確認しました。実GASへのデプロイ、リダイレクトを含む通信、シート保存・実メール送信は未検証です。

この例はメール成功後のコピーで、シート書込失敗をフォームの送信失敗には変えません。自動再送キューはなく、PHPフックが別の呼び出しとして再実行されると新しいIDになります。厳密な一度だけの保存や欠損ゼロを保証しません。失敗時はリクエストIDだけをログに残します。停止する場合はPHPフックを削除し、使わなくなったWebアプリのデプロイを停止します。共有先と保存期間も運用で決めてください。

仕様参照:GoogleのWebアプリ仕様、LockService。

  • URLをコピーしました!

プラグインの設定でお困りなら

プラグインの導入・カスタマイズ代行

プラグインの選定から設定、競合の解消、動作に合わせた追加実装まで承ります。1時間 ¥8,000〜(税込)。

WAZAの有料記事のサブスクリプションも開始しました。

サービス

Service

WordPressサイトのカスタマイズのサービスに関心がありましたら、ぜひ詳細をご覧ください。

目次