WordPress お問い合わせフォーム完全ガイド【プラグイン・自作対応】

WordPress お問い合わせフォーム完全ガイド【プラグイン・自作対応】

WordPressサイトにお問い合わせフォームを設置することは、ビジネスサイトや個人ブログにとって必須の要素です。訪問者からの貴重な声を集める窓口であり、信頼関係を築く重要なツールとなります。

目次

はじめに — なぜフォームが要る?

WordPressサイトにお問い合わせフォームを設置することは、ビジネスサイトや個人ブログにとって必須の要素です。訪問者からの貴重な声を集める窓口であり、信頼関係を築く重要なツールとなります。

メール直書きのリスク/フォームのメリット(スパム防止・情報整理・UX)

メール直書きのリスク:

  • メールアドレスが丸見えでスパムの標的になる
  • ユーザーがメーラーを起動する手間がかかる
  • 情報の入力漏れが多発
  • 管理者側での整理・分類が困難

フォームのメリット:

  • スパム防止: reCAPTCHAやHoneypotで自動投稿を防げる
  • 情報整理: 必要な項目を事前に設定して抜け漏れを防止
  • UX向上: ブラウザ上で簡単に送信でき、離脱率を下げる
  • データ管理: 送信内容を構造化して保存・検索可能
  • 自動化: 自動返信メールで即座に受付確認

初心者向け — プラグインで最短実装

プラグインを使えば、コードを書かずに本格的なお問い合わせフォームを作成できます。

Contact Form 7(インストール→基本フォーム→ショートコード設置)

インストール手順:

  1. WordPress管理画面→プラグイン→新規追加
  2. 「Contact Form 7」を検索してインストール・有効化
  3. 左メニューに「お問い合わせ」が追加される

設置方法:

  1. フォーム作成後、ショートコードをコピー
  2. 固定ページまたは投稿に

      を貼り付け
    • ページを公開

    WPForms(ドラッグ&ドロップ作成→埋め込み)

    特徴:

    • 直感的なドラッグ&ドロップ操作
    • リアルタイムプレビュー機能
    • テンプレートが豊富

    基本的な使い方:

    1. WPFormsをインストール・有効化
    2. WPForms→新規追加
    3. 「Simple Contact Form」テンプレートを選択
    4. 必要に応じてフィールドを追加・編集
    5. 「埋め込み」からショートコードを取得して設置

    Flamingo(送信データの保存)

    Contact Form 7と組み合わせて使用するデータ保存プラグインです。

    設定手順:

    1. Flamingoをインストール・有効化
    2. 管理画面→Flamingo→受信メッセージで送信内容を確認
    3. アドレス帳機能で送信者情報を自動管理
    4. CSVエクスポート機能で外部システムとの連携も可能

    中級者向け — プラグインなしで自作

    自作フォームなら完全にカスタマイズでき、サイトの読み込み速度向上にも貢献します。

    HTML(必須項目・アクセシビリティ配慮)

    <form method="post" action="">
        <?php wp_nonce_field('contact_form_nonce', 'contact_nonce'); ?>
        
        <div class="form-group">
            <label for="contact_name">お名前 <span class="required">*</span></label>
            <input type="text" id="contact_name" name="contact_name" required aria-describedby="name-error">
            <div id="name-error" class="error-message" role="alert"></div>
        </div>
        
        <div class="form-group">
            <label for="contact_email">メールアドレス <span class="required">*</span></label>
            <input type="email" id="contact_email" name="contact_email" required aria-describedby="email-error">
            <div id="email-error" class="error-message" role="alert"></div>
        </div>
        
        <div class="form-group">
            <label for="contact_subject">件名</label>
            <input type="text" id="contact_subject" name="contact_subject">
        </div>
        
        <div class="form-group">
            <label for="contact_message">メッセージ <span class="required">*</span></label>
            <textarea id="contact_message" name="contact_message" required aria-describedby="message-error"></textarea>
            <div id="message-error" class="error-message" role="alert"></div>
        </div>
        
        <!-- Honeypot(非表示フィールド) -->
        <input type="text" name="honey_pot" style="display:none;">
        
        <button type="submit" name="submit_contact">送信する</button>
    </form>
    
    Code language: HTML, XML (xml)

    PHP(Nonce・サニタイズ・wp_mail()・自動返信)

    <?php
    // functions.phpまたは専用ファイルに追加
    function handle_contact_form() {
        if (!isset($_POST['submit_contact'])) {
            return;
        }
        
        // Nonce検証
        if (!wp_verify_nonce($_POST['contact_nonce'], 'contact_form_nonce')) {
            wp_die('セキュリティエラーが発生しました。');
        }
        
        // Honeypotチェック
        if (!empty($_POST['honey_pot'])) {
            return; // スパムとして無視
        }
        
        // データのサニタイズ
        $name = sanitize_text_field($_POST['contact_name']);
        $email = sanitize_email($_POST['contact_email']);
        $subject = sanitize_text_field($_POST['contact_subject']);
        $message = sanitize_textarea_field($_POST['contact_message']);
        
        // バリデーション
        $errors = array();
        
        if (empty($name)) {
            $errors[] = 'お名前は必須です。';
        }
        
        if (empty($email) || !is_email($email)) {
            $errors[] = 'メールアドレスを正しく入力してください。';
        }
        
        if (empty($message)) {
            $errors[] = 'メッセージは必須です。';
        }
        
        if (!empty($errors)) {
            // エラー表示処理
            return;
        }
        
        // メール送信
        $to = get_option('admin_email');
        $mail_subject = 'お問い合わせ: ' . $subject;
        $mail_message = "お名前: {$name}\n";
        $mail_message .= "メールアドレス: {$email}\n";
        $mail_message .= "件名: {$subject}\n\n";
        $mail_message .= "メッセージ:\n{$message}";
        
        $headers = array(
            'From: ' . $name . ' <' . $email . '>',
            'Reply-To: ' . $email
        );
        
        $sent = wp_mail($to, $mail_subject, $mail_message, $headers);
        
        if ($sent) {
            // 自動返信メール
            $auto_subject = 'お問い合わせを受け付けました';
            $auto_message = $name . "様\n\n";
            $auto_message .= "お問い合わせいただき、ありがとうございます。\n";
            $auto_message .= "内容を確認後、担当者よりご連絡いたします。\n\n";
            $auto_message .= "送信内容:\n" . $mail_message;
            
            wp_mail($email, $auto_subject, $auto_message, 'From: ' . get_bloginfo('name'));
            
            // 成功メッセージ
            echo '<div class="success-message">送信が完了しました。</div>';
        } else {
            echo '<div class="error-message">送信に失敗しました。しばらく後に再度お試しください。</div>';
        }
    }
    add_action('init', 'handle_contact_form');
    ?>
    
    Code language: HTML, XML (xml)

    CSS(最低限の見た目)

    .form-group {
        margin-bottom: 1.5rem;
    }
    
    .form-group label {
        display: block;
        margin-bottom: 0.5rem;
        font-weight: bold;
    }
    
    .required {
        color: #e74c3c;
    }
    
    .form-group input[type="text"],
    .form-group input[type="email"],
    .form-group textarea {
        width: 100%;
        padding: 0.75rem;
        border: 2px solid #ddd;
        border-radius: 4px;
        font-size: 1rem;
    }
    
    .form-group input:focus,
    .form-group textarea:focus {
        outline: none;
        border-color: #3498db;
        box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
    }
    
    .form-group textarea {
        min-height: 120px;
        resize: vertical;
    }
    
    button[type="submit"] {
        background-color: #3498db;
        color: white;
        padding: 1rem 2rem;
        border: none;
        border-radius: 4px;
        font-size: 1rem;
        cursor: pointer;
        transition: background-color 0.3s;
    }
    
    button[type="submit"]:hover {
        background-color: #2980b9;
    }
    
    .error-message {
        color: #e74c3c;
        font-size: 0.9rem;
        margin-top: 0.25rem;
    }
    
    .success-message {
        background-color: #d4edda;
        color: #155724;
        padding: 1rem;
        border-radius: 4px;
        margin-bottom: 1rem;
    }
    
    Code language: CSS (css)

    セキュリティ&スパム対策

    お問い合わせフォームは外部からの入力を受け取るため、セキュリティ対策は必須です。

    reCAPTCHA(CF7/WPFormsの設定ポイント)

    Contact Form 7での設定:

    1. Google reCAPTCHAでサイト登録
    2. サイトキーとシークレットキーを取得
    3. CF7→インテグレーション→reCAPTCHAに設定
    4. フォームに [recaptcha] タグを追加

    WPFormsでの設定:

    1. WPForms→設定→reCAPTCHA
    2. サイトキーとシークレットキーを入力
    3. フォーム編集画面でreCAPTCHAフィールドを追加

    v3とv2の選び方:

    • v3: ユーザー操作不要、スコアベースで判定
    • v2: クリックまたは画像選択が必要、確実性が高い

    CSRF対策(Nonce)/Honeypot/日本語入力チェックの考え方

    Nonce(ナンス):

    // フォーム生成時
    wp_nonce_field('contact_form_nonce', 'contact_nonce');
    
    // 検証時
    if (!wp_verify_nonce($_POST['contact_nonce'], 'contact_form_nonce')) {
        wp_die('不正なリクエストです。');
    }
    
    Code language: PHP (php)

    Honeypot(ハニーポット):

    <!-- 人間には見えないが、ボットが入力してしまうフィールド -->
    <input type="text" name="website" style="display:none;" tabindex="-1" autocomplete="off">
    
    Code language: HTML, XML (xml)

    日本語入力チェック:

    function contains_japanese($text) {
        return preg_match('/[\x{3040}-\x{309F}\x{30A0}-\x{30FF}\x{4E00}-\x{9FAF}]/u', $text);
    }
    
    if (!contains_japanese($message)) {
        $errors[] = 'メッセージは日本語で入力してください。';
    }
    
    Code language: PHP (php)

    実務で効くカスタマイズ

    基本的なフォームから一歩進んで、実務で役立つ機能を追加しましょう。

    自動返信メール(送信者控え/ヘッダー設定)

    HTMLメール対応:

    function send_html_auto_reply($email, $name, $subject, $message) {
        $to = $email;
        $mail_subject = 'お問い合わせを受け付けました - ' . get_bloginfo('name');
        
        $html_message = '
        <html>
        <body>
            <h2>' . $name . '様</h2>
            <p>お問い合わせいただき、ありがとうございます。</p>
            <p>以下の内容で受け付けいたしました。</p>
            
            <table border="1" cellpadding="10">
                <tr><th>お名前</th><td>' . esc_html($name) . '</td></tr>
                <tr><th>件名</th><td>' . esc_html($subject) . '</td></tr>
                <tr><th>メッセージ</th><td>' . nl2br(esc_html($message)) . '</td></tr>
            </table>
            
            <p>担当者より2営業日以内にご連絡いたします。</p>
        </body>
        </html>
        ';
        
        $headers = array(
            'Content-Type: text/html; charset=UTF-8',
            'From: ' . get_bloginfo('name') . ' <noreply@' . parse_url(home_url(), PHP_URL_HOST) . '>'
        );
        
        wp_mail($to, $mail_subject, $html_message, $headers);
    }
    
    Code language: HTML, XML (xml)

    ファイル添付(MIME・容量・保存場所)

    安全なファイルアップロード:

    function handle_file_upload() {
        if (!isset($_FILES['attachment']) || $_FILES['attachment']['error'] !== UPLOAD_ERR_OK) {
            return false;
        }
        
        $file = $_FILES['attachment'];
        
        // ファイルサイズチェック(5MB以下)
        if ($file['size'] > 5 * 1024 * 1024) {
            return new WP_Error('file_too_large', 'ファイルサイズは5MB以下にしてください。');
        }
        
        // MIMEタイプチェック
        $allowed_types = array('image/jpeg', 'image/png', 'application/pdf', 'text/plain');
        $file_type = wp_check_filetype_and_ext($file['tmp_name'], $file['name']);
        
        if (!in_array($file_type['type'], $allowed_types)) {
            return new WP_Error('invalid_file_type', '許可されていないファイル形式です。');
        }
        
        // WordPressのアップロード処理
        if (!function_exists('wp_handle_upload')) {
            require_once(ABSPATH . 'wp-admin/includes/file.php');
        }
        
        $upload_overrides = array('test_form' => false);
        $movefile = wp_handle_upload($file, $upload_overrides);
        
        if ($movefile && !isset($movefile['error'])) {
            return $movefile['url'];
        } else {
            return new WP_Error('upload_failed', $movefile['error']);
        }
    }
    
    Code language: PHP (php)

    送信データの保存(Flamingo or カスタム投稿タイプ)

    カスタム投稿タイプでの保存:

    function save_contact_data($name, $email, $subject, $message) {
        $post_data = array(
            'post_title'   => $subject . ' - ' . $name,
            'post_content' => $message,
            'post_status'  => 'private',
            'post_type'    => 'contact_submission',
            'meta_input'   => array(
                'contact_name'    => $name,
                'contact_email'   => $email,
                'contact_subject' => $subject,
                'submission_date' => current_time('mysql'),
                'user_ip'         => $_SERVER['REMOTE_ADDR'] ?? '',
                'user_agent'      => $_SERVER['HTTP_USER_AGENT'] ?? ''
            )
        );
        
        return wp_insert_post($post_data);
    }
    
    // カスタム投稿タイプを登録
    function register_contact_post_type() {
        register_post_type('contact_submission', array(
            'label'       => 'お問い合わせ',
            'public'      => false,
            'show_ui'     => true,
            'show_in_menu' => true,
            'supports'    => array('title', 'editor'),
            'capabilities' => array(
                'create_posts' => 'do_not_allow'
            ),
            'map_meta_cap' => true
        ));
    }
    add_action('init', 'register_contact_post_type');
    
    Code language: PHP (php)

    トラブルシューティング(症状→原因→直し方)

    よくある問題と解決方法を症状別にまとめました。

    メールが届かない

    症状: フォーム送信後、管理者にメールが届かない

    考えられる原因と対処法:

    1. サーバーのメール機能が無効
      • 解決策: SMTPプラグイン(WP Mail SMTP)を導入
      • Gmail、Outlook等の外部SMTPサービスを利用
    2. スパムフィルターに引っかかっている
      • 解決策: SPF、DKIM、DMARCレコードをDNSに設定
      • 送信者アドレスをサイトドメインと一致させる
    3. wp_mail()が正しく動作していない
      • 確認方法: wp_mail()の戻り値をチェック
      $sent = wp_mail($to, $subject, $message); if (!$sent) { error_log('メール送信に失敗しました'); }

    送信できない(フォームが動作しない)

    症状: 送信ボタンを押してもページが動かない、エラーが出る

    考えられる原因と対処法:

    1. JavaScriptエラー
      • 確認方法: ブラウザの開発者ツールでコンソールをチェック
      • 解決策: プラグインの競合を確認、テーマを一時的にデフォルトに変更
    2. PHPエラー
      • 確認方法: WordPressデバッグログを確認
      // wp-config.phpに追加 define('WP_DEBUG', true); define('WP_DEBUG_LOG', true);
    3. サーバーのリソース不足
      • 解決策: メモリ制限を増やす、実行時間を延長する

    reCAPTCHAが動かない

    症状: reCAPTCHAが表示されない、または認証に失敗する

    考えられる原因と対処法:

    1. APIキーの設定ミス
      • 確認項目: サイトキーとシークレットキーが正しく入力されているか
      • ドメインが正しく登録されているか
    2. HTTPSの問題
      • 解決策: サイト全体をHTTPS化する
      • WordPressの設定でサイトURLをhttps://に変更
    3. キャッシュプラグインの影響
      • 解決策: reCAPTCHA部分をキャッシュ対象から除外

    403エラー(Nonce検証失敗)

    症状: フォーム送信時に403エラーまたは「不正なリクエスト」と表示

    考えられる原因と対処法:

    1. Nonceの有効期限切れ
      • 解決策: ページのキャッシュ時間を短縮、Ajax更新でNonceを再取得
    2. セキュリティプラグインの誤作動
      • 確認項目: Wordfence、SiteGuard等の設定を確認
      • 解決策: フォームURLをホワイトリストに追加
    3. サーバーレベルのセキュリティ
      • 解決策: .htaccessやmod_securityの設定を確認

    ファイルが弾かれる

    症状: 添付ファイルがアップロードできない

    考えられる原因と対処法:

    1. ファイルサイズ制限
      • 確認方法: phpinfo()でupload_max_filesize、post_max_sizeをチェック
      • 解決策: php.iniまたは.htaccessで制限値を変更
    2. MIME タイプ制限
      • 解決策: WordPressのアップロード可能ファイル形式を拡張
      function allow_additional_file_types($mimes) { $mimes['pdf'] = 'application/pdf'; return $mimes; } add_filter('upload_mimes', 'allow_additional_file_types');
    3. ディレクトリの権限不足
      • 確認項目: wp-content/uploadsディレクトリの権限(755または775)
      • 解決策: FTPまたはサーバー管理画面から権限を変更

    仕上げチェックリスト

    フォーム設置後、以下の項目を確認して完成度を高めましょう。

    機能チェック

    • [ ] フォーム送信が正常に動作する
    • [ ] 必須項目の入力チェックが機能している
    • [ ] 管理者に通知メールが届く
    • [ ] 自動返信メールが送信者に届く
    • [ ] エラーメッセージが適切に表示される
    • [ ] 送信完了メッセージが表示される
    • [ ] ファイル添付機能(使用する場合)が正常動作

    表示チェック

    • [ ] PC・タブレット・スマホで正しく表示される
    • [ ] フォームのデザインがサイトに馴染んでいる
    • [ ] 入力フィールドが使いやすい
    • [ ] エラーメッセージが見やすい位置に表示
    • [ ] 必須項目が明確に示されている
    • [ ] フォーカス時のスタイルが適用されている

    セキュリティチェック

    • [ ] Nonce検証が実装されている
    • [ ] 入力データのサニタイズが行われている
    • [ ] SQLインジェクション対策済み
    • [ ] CSRF対策済み
    • [ ] スパム対策(reCAPTCHA/Honeypot)が有効
    • [ ] ファイルアップロード時の検証が実装されている
    • [ ] XSS対策でデータ出力時にエスケープ処理

    速度・パフォーマンス

    • [ ] フォーム読み込み時間が適切(3秒以内)
    • [ ] JavaScriptファイルサイズが最適化されている
    • [ ] 不要なCSSが読み込まれていない
    • [ ] 画像ファイルが最適化されている
    • [ ] キャッシュプラグインとの競合がない

    ログ・分析

    • [ ] 送信データの保存設定が完了している
    • [ ] エラーログの設定が有効
    • [ ] Google Analyticsでフォーム送信を追跡設定
    • [ ] 送信率の計測方法が確立されている

    バックアップ・復旧

    • [ ] フォーム設定のバックアップが取られている
    • [ ] 送信データのバックアップ設定が完了
    • [ ] 復旧手順が文書化されている
    • [ ] 定期的なバックアップスケジュールが設定済み

    まとめ(今日できる次の一歩)

    WordPressのお問い合わせフォームは、サイトの信頼性を高め、訪問者との重要なコミュニケーション手段となります。この記事で紹介した内容を参考に、あなたのサイトに最適なフォームを実装してください。

    今日から始められる具体的なアクション:

    初心者の方:

    1. Contact Form 7をインストールして基本フォームを作成
    2. Flamingoで送信データの保存設定
    3. reCAPTCHA v3の導入でスパム対策

    中級者の方:

    1. 自作フォームでサイトの読み込み速度向上
    2. 自動返信メールのHTMLメール化
    3. カスタム投稿タイプでのデータ管理システム構築

    上級者の方:

    1. 高度なバリデーション機能の実装
    2. 外部CRMシステムとの API 連携
    3. A/Bテストによる送信率最適化

    お問い合わせフォームは一度設置して終わりではありません。定期的な動作確認、セキュリティアップデート、ユーザビリティの改善を継続的に行い、訪問者にとって使いやすく、管理者にとって運用しやすいフォームを維持していきましょう。

    何か不明な点があれば、WordPressコミュニティやサポートフォーラムを活用し、常に最新の情報をキャッチアップしながらフォーム運用のスキルを向上させていってください。

    お問い合わせ

      この記事も読まれています
      記事一覧へ