Web3Formsの使い方

2026/02/25

概要

管理しているサイトに閲覧者からのメールを受けるフォームを設置している。これまではpostmailを使用していたが、10数年前の無料アプリで、最近不具合が出るようになった。

Geminiが薦めるformspreeを導入したが、テストをすると時々メールの未達が発生する。

問い合わせメールは仕組みは簡単だが、ユーザーとの接点のため場合によってはコンピュータ・ウィルスの汚染源ともなる。

代替えアプリとしてGeminiに相談しweb3formsを使うことにした。

Web3Formsは、サーバーサイドのコード(PHPなど)を一切書かずに、HTMLのフォームから直接メールを送信できるサーバーレス型のメール送信サービスです。 技術者や開発者からの評判は非常に高く、特に以下の点が評価されています。 良い評判・メリット 圧倒的な手軽さ: Qiita*のガイドでも紹介されている通り、action属性に専用のURLを指定するだけでフォームが完成します。(*Qiitaはエンジニアに関する知識を記録・共有するためのサービス) 静的サイトとの相性: NetlifyやVercelなどで構築した、バックエンドを持たない静的サイトにフォームを追加する際の最適解の一つとされています。 無料プランの充実: 月間250件の送信まで無料で利用でき、クレジットカード登録も不要なため、小規模プロジェクトやポートフォリオに最適です。 柔軟なカスタマイズ: 外部のウィジェットを埋め込むタイプ(Googleフォーム等)と異なり、自作のHTML/CSSデザインをそのまま使えるため、サイトのトーン&マナーを崩しません。 注意点・デメリット 日本語ドキュメントの少なさ: 公式サイトや設定画面が英語中心であるため、翻訳ツールが必要な場合があります。 高度なデータ管理: データの蓄積や分析機能は WEBCAS formulator のような国内SaaSに比べるとシンプルで、あくまで「メールで通知を受け取る」ことが主目的のツールです。 結論: デザインを自由に制御したい開発者や、手軽に問い合わせフォームを自作したい初心者には「神ツール」として支持されています。一方で、本格的な顧客管理(CRM)やアンケート分析を行いたい場合は、formrun などの多機能ツールが向いています。

無料版の機能  Unlimited Forms  250 Monthly Submissions  Unlimited Domains  Advanced Spam Protection  hCaptcha Integration  Custom Redirect Page  All Basic Features  Create your form  No credit card required

最初は問い合わせ者が必要情報を入力し「送信」ボタンを押すと何も表示せずに終わる。これでは物足りなく、" メッセージを送りました!お問い合わせありがとうございます。 " と サンクスメッセージを出すようにした。

フォーム設定

Web3Formsサイト

サイトに登録し、サインイン。コンタクトフォームを作成。Form Access Key がサンプルのHTMLにセットされるのでそのままコピー。

フォームの名前、送られるメールアドレス設定

サンプルhtml

黄色部分はメール送信後のメッセージ表示のJavascriptコード

<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" type="text/css" href="../css2025/akacom5.css"> <title>メールフォーム</title> <style> body { background-color:lavender; width:90%; margin:10px auto; } form label, form input, form textarea, form button { display: block; /* 要素を縦に並べる指定 */ margin-bottom: 10px; /* 下に余白を作る */ } h1 { color:black; } </style> </head> <body> <h1>Hitoshi Diaryメールフォーム</h1> <form action="https://api.web3forms.com/submit" method="POST" id="contact-form"> <input type="hidden" name="access_key" value="4aed5c7a-ab8c-7c7s-64cf-c286g8g472f4"> <input type="hidden" name="redirect" value="https://redrb.heteml.net/profile/profile.html"> <input type="hidden" name="subject" value="Hitoshi Diaryからのお問い合わせ"> <label>お名前</label> <input type="text" name="name" required> <label>メールアドレス</label> <input type="email" name="email" required> <label>メッセージ</label> <textarea name="message" style="width: 80%; height: 100px;" required></textarea> <input type="checkbox" name="botcheck" style="display: none;"> <button type="submit">送信する</button> </form> <p id="result-message" style="display: none; color: green; margin-top: 10px;"></p> <script> const form = document.getElementById('contact-form'); const result = document.getElementById('result-message'); form.addEventListener('submit', function(e) { e.preventDefault(); // デフォルトのページ遷移を防ぐ const formData = new FormData(form); const object = Object.fromEntries(formData); const json = JSON.stringify(object); result.style.display = "block"; result.style.color = "gray"; result.innerHTML = "送信中..."; fetch('https://api.web3forms.com/submit', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: json }) .then(async (response) => { let json = await response.json(); if (response.status == 200) { // 成功時のメッセージ result.style.color = "green"; result.innerHTML = "メッセージを送りました!お問い合わせありがとうございます。"; form.reset(); // フォームの中身を空にする } else { // APIからエラーが返ってきた場合 result.style.color = "red"; result.innerHTML = json.message || "送信に失敗しました。"; } }) .catch(error => { // ネットワークエラーなどの場合 console.log(error); result.style.color = "red"; result.innerHTML = "エラーが発生しました。時間を置いて再度お試しください。"; }) .then(function() { // 5秒後にメッセージをスッと消す(お好みで) setTimeout(() => { result.style.display = "none"; }, 5000); }); }); </script> <!----- return to top --------------------> <div id="modoru"> <a href="profile.html">戻る</a> </div> </body> </html>


Javascriptコードの説明

JavaScriptのコードは、「ページを移動させずに裏側でWeb3Formsにデータを送り、その結果を画面に表示する」という一連の処理(非同期通信 / AJAXと呼ばれます)を行っています。

それぞれの行がどのような役割を持っているのか、いくつかのブロックに分けて詳しく解説します。

1. メッセージ表示用のHTMLと要素の取得
HTML

まず、HTML側でメッセージを表示するための場所(

タグ)を用意しています。最初は display: none; で隠してあります。 JavaScript const form = document.getElementById('contact-form'); const result = document.getElementById('result-message'); JavaScriptの最初で、操作対象となる「フォーム本体(contact-form)」と「メッセージ表示エリア(result-message)」をHTMLから見つけ出し、それぞれ form と result という変数に格納して扱いやすくしています。 2. 送信ボタンが押されたときの処理の開始 JavaScript form.addEventListener('submit', function(e) { e.preventDefault(); // デフォルトのページ遷移を防ぐ addEventListener('submit', ...): ユーザーが「送信する」ボタンを押した瞬間に、この中の処理を実行するように待機(リスニング)します。 e.preventDefault();: 通常、フォームを送信するとブラウザは別のページ(または同じページ)に画面を切り替えようとします。この1行はその標準動作をキャンセルし、ページ遷移を防ぐための非常に重要なコードです。 3. 入力データの変換(JSON形式への整理) JavaScript const formData = new FormData(form); const object = Object.fromEntries(formData); const json = JSON.stringify(object); Web3FormsのAPI(データを受け取る窓口)は、「JSON(ジェイソン)」というデータ形式を好みます。 ここでは、以下の3ステップでデータを変換しています。 FormData(form) で、フォームに入力された全データ(名前、メールアドレス、本文など)をガサッと集めます。 Object.fromEntries() で、それをJavaScriptで扱いやすいオブジェクト(辞書のような形式)に変換します。 JSON.stringify() で、それをWeb3Formsに送るための文字列(JSONフォーマット)に変換します。 4. 「送信中」メッセージの表示 JavaScript result.style.display = "block"; result.style.color = "gray"; result.innerHTML = "送信中..."; データを送る直前に、隠していた

タグを表示(display = "block")にし、文字色をグレーにして「送信中...」というテキストを画面に出します。これでユーザーは「ちゃんと動いているな」と安心できます。 5. Web3Formsへのデータ送信(Fetch API) JavaScript fetch('https://api.web3forms.com/submit', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: json }) fetch(...): ここが実際に通信を行う部分です。Web3Formsの指定URLへデータを送ります。 method: 'POST': データを「送る」という通信方法を指定しています。 headers: 「これから送るデータはJSON形式ですよ」という手紙の宛名書きのような情報を添えています。 body: json: ここで、手順3で作った入力データの中身(JSON)を実際に送っています。 6. 送信結果の受け取りと画面への反映 JavaScript .then(async (response) => { let json = await response.json(); if (response.status == 200) { // 成功時のメッセージ result.style.color = "green"; result.innerHTML = "メッセージを送りました!お問い合わせありがとうございます。"; form.reset(); // フォームの中身を空にする } else { // APIからエラーが返ってきた場合 result.style.color = "red"; result.innerHTML = json.message || "送信に失敗しました。"; } }) .then(...): 通信が終わった後、Web3Formsからの「お返事(response)」を受け取って処理します。 if (response.status == 200): 通信が「大成功」だった場合のステータスコードが200です。成功したら文字を緑色にし、完了メッセージを出し、form.reset() で入力欄をすべて空っぽ(初期状態)に戻します。 else: アクセスキーが間違っているなど、Web3Forms側で何らかのエラーが起きた場合の処理です。文字を赤色にしてエラーメッセージを表示します。 7. 通信エラーの処理と、メッセージの自動非表示 JavaScript .catch(error => { // ネットワークエラーなどの場合 console.log(error); result.style.color = "red"; result.innerHTML = "エラーが発生しました。時間を置いて再度お試しください。"; }) .then(function() { // 5秒後にメッセージをスッと消す(お好みで) setTimeout(() => { result.style.display = "none"; }, 5000); }); }); .catch(...): ユーザーのスマホが圏外だったり、Wi-Fiが切れたりして、そもそもWeb3Formsまで通信が届かなかった場合の処理です。 最後の .then(...) と setTimeout: 成功・失敗にかかわらず、最後に実行される処理です。setTimeout を使い、「5000ミリ秒(=5秒)経過したら、メッセージエリアを再び display: none にして隠す」というタイマーをセットしています。 コード全体の流れとしては、「送信ストップ」→「データ準備」→「送信中表示」→「通信」→「結果表示」→「5秒後に消す」という、非常にユーザーフレンドリーな設計になっています。

hCaptchaコード

スパム対策として人間かロボットかを判別するhCaptchaも使える。Googleが提供する有名なサービス「reCAPTCHA」の強力な代替手段として、Googleに依存しないとして近年多くのウェブサイトで採用が広がっているという。hCaptcha Developer Guide

Web3FormsのサイトでsettingメニューからhCaptchaを選ぶ。Google reCaptchaは有料プラン。

<div class="h-captcha" data-captcha="true"></div> というコードに data-captcha="true" を付与することで、Web3Forms側が用意したhCaptchaのAPIキー(サイトキーおよびシークレットキー)が自動的に適用される。これによりhCaptchaのアカウントを登録しシークレットキーを取得する必要がない。但し非常に可能性は低いが将来仕様が変わる可能性があるとgeminiの見解。

htmlにhCaptchaコードを追加

<html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" type="text/css" href="../css2025/akacom5.css"> <title>メールフォーム</title> <style> body { background-color:lavender; width:90%; margin:10px auto; } form label, form input, form textarea, form button { display: block; /* 要素を縦に並べる指定 */ margin-bottom: 10px; /* 下に余白を作る */ } h1 { color:black; } </style> </head> <body> <h1>Hitoshi Diaryメールフォーム</h1> <form action="https://api.web3forms.com/submit" method="POST" id="contact-form"> <input type="hidden" name="access_key" value="4aed5c7a-ab8c-7c7s-64cf-c286g8g472f4"> <input type="hidden" name="redirect" value="https://redrb.heteml.net/profile/profile.html"> <input type="hidden" name="subject" value="Hitoshi Diaryからのお問い合わせ"> <label>お名前</label> <input type="text" name="name" required> <label>メールアドレス</label> <input type="email" name="email" required> <label>メッセージ</label> <textarea name="message" style="width: 80%; height: 100px;" required></textarea> <input type="checkbox" name="botcheck" style="display: none;"> <!-- h-captcha --> <div class="h-captcha" data-captcha="true"></div> <button type="submit">送信する</button> </form> <p id="result-message" style="display: none; color: green; margin-top: 10px;"></p> <script> const form = document.getElementById('contact-form'); const result = document.getElementById('result-message'); form.addEventListener('submit', function(e) { e.preventDefault(); // デフォルトのページ遷移を防ぐ const formData = new FormData(form); // ▼▼▼ 追加した部分:hCaptchaにチェックが入っているか確認 ▼▼▼ const hCaptchaResponse = formData.get('h-captcha-response'); if (!hCaptchaResponse) { result.style.display = "block"; result.style.color = "red"; result.innerHTML = "「私はロボットではありません」にチェックを入れてください。"; return; // チェックがない場合はここで送信をストップする } // ▲▲▲ 追加した部分 ここまで ▲▲▲ const object = Object.fromEntries(formData); const json = JSON.stringify(object); result.style.display = "block"; result.style.color = "gray"; result.innerHTML = "送信中..."; fetch('https://api.web3forms.com/submit', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: json }) .then(async (response) => { let json = await response.json(); if (response.status == 200) { // 成功時のメッセージ result.style.color = "green"; result.innerHTML = "メッセージを送りました!お問い合わせありがとうございます。"; form.reset(); // フォームの中身を空にする // ▼▼▼ 追加した部分:送信成功後にhCaptchaのチェックマークを元に戻す ▼▼▼ if (typeof hcaptcha !== 'undefined') { hcaptcha.reset(); } // ▲▲▲ 追加した部分 ここまで ▲▲▲ } else { // APIからエラーが返ってきた場合 result.style.color = "red"; result.innerHTML = json.message || "送信に失敗しました。"; } }) .catch(error => { // ネットワークエラーなどの場合 console.log(error); result.style.color = "red"; result.innerHTML = "エラーが発生しました。時間を置いて再度お試しください。"; }) .then(function() { // 5秒後にメッセージをスッと消す(お好みで) setTimeout(() => { result.style.display = "none"; }, 5000); }); }); </script> <!-- hCaptcha --> <script src="https://web3forms.com/client/script.js" async defer></script> <!----- return to top --------------------> <div id="modoru"> <a href="profile.html">戻る</a> </div> </body> </html>


画面サンプル

hCaptcha画面

感想

簡単に設置できて使いやすい。無料でも割り切れれば使える。htmlのソースコードが見えるためアクセスキーが盗まれる懸念があるが、キーを盗んでもメールアドレスは変えられないので大きな被害は無いと思われる。ドメイン制限(Allowed Domains:指定したドメインしか設置出来ない)は「Proプラン(有料)」専用の機能。

戻る