はじめに
週2くらいの頻度でよく夢を見るのですが、
夢日記の記録や占いが地味に手間でした。
- メモ帳だと読み返しにくい
- AIに占ってもらうとログが流れて残らない
- アプリの夢診断はAI部分が有料
「じゃあ自分で自動化しよう」と思い、
Googleフォーム × GAS × Gemini の無料ツールを作りました。
同じような不満を抱えている方の参考になれば幸いです
目次
作ったもの・技術スタック
- Googleフォームに夢日記を送信
- Geminiが夢占いをし【キーワード+夢のまとめ】を自動生成
- 占い結果をメールで通知
- 過去の夢はスプレッドシートで一覧化
という自動ツールです。
以下の3つだけで実現できます:
- Googleフォーム
- Googleスプレッドシート
- Google Apps Script
外部サーバー不要。無料で完結します。
全体構成
- ユーザーがGoogleフォームで夢日記を送信
↓ - 夢日記がスプレッドシートに追加
↓ - Apps Script(onFormSubmit)が自動起動
↓ - Gemini APIへ夢の内容を送信して解析
↓ - 解析結果をスプレッドシートへ書き込み
↓ - AI解析結果をメール送信(通知ONの場合)
※Apps Scriptのトリガー機能がすべて自動実行してくれます。
画面イメージ
実装手順まとめ
① Googleフォームを作る
https://forms.google.com/
項目は3つだけでOKです。
- 夢を見た日(Date)
- タイトル(任意)
- 夢の内容(段落)
フォームURLは「自分専用」で使うため、誰にも公開しなくてOKです。
② 送信先スプレッドシートを作成
Googleフォームの「スプレッドシートに保存」を押すと自動生成されます。
https://docs.google.com/spreadsheets/
列構成:
| 列 | 内容 |
|---|---|
| A | 送信日時(自動) |
| B | 夢を見た日 |
| C | タイトル |
| D | 夢の内容 |
| E | 夢占い結果(AI分析)←GASが自動で書き込む |
このシートが “夢日記のアーカイブ” になります。
③ Apps Script の準備
Googleスプレッドシート → 拡張機能 → Apps Script を開きます。
スクリプトプロパティに以下3つを登録:
-
GEMINI_API_KEY(APIキーはhttps://aistudio.google.com/app/apikey から取得。無料枠でOK) -
FIXED_EMAIL(占い結果を通知するメールアドレス ~@Gmail.com) -
FORM_URL(夢日記送信用のGoogleフォームURL)
メアド・フォームURLはファイルにベタ書きでも問題ないと思います。
今回はQiitaにコードを載せるためスクリプトプロパティに記載しました。
サンプルコード:ここをクリック
/**
* 夢の内容をGeminiに投げて夢占い結果を返す
*/
function callGeminiForDream_(dreamContent) {
const apiKey = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
if (!apiKey) {
throw new Error('GEMINI_API_KEY がスクリプトプロパティに設定されていません。');
}
// モデル名は必要に応じて変更
const url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent';
const prompt = `
あなたは日本人の夢占い師です。
以下の夢の内容を読み、その夢が象徴している心理状態やメッセージを分析してください。
出力は必ず次のフォーマットだけにしてください。
・あいさつや前置き、まとめの一言などは書かないこと
・指定していない余計な文章や見出しは出力しないこと
【キーワード】
- キーワード1:このキーワードが象徴する意味を短く説明
- キーワード2:このキーワードが象徴する意味を短く説明
(キーワードの数は2〜4個程度で調整してください)
【夢のまとめ】
この夢全体から読み取れる心理状態やメッセージを、
前向きなアドバイスも含めて、3〜6文程度で日本語でまとめてください
【夢の内容】
${dreamContent}
`.trim();
const payload = {
contents: [
{ parts: [{ text: prompt }] }
]
};
const params = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(url + '?key=' + encodeURIComponent(apiKey), params);
const text = response.getContentText();
let data;
try {
data = JSON.parse(text);
} catch (e) {
throw new Error('Gemini APIレスポンスのJSON解析に失敗しました: ' + text);
}
const candidates = data.candidates;
if (!candidates || !candidates[0] || !candidates[0].content) {
throw new Error('Gemini APIから有効なレスポンスが得られませんでした: ' + text);
}
const parts = candidates[0].content.parts || [];
const resultText = parts.map(p => p.text || '').join('\n').trim();
return resultText || '(AIの応答を取得できませんでした)';
}
function onFormSubmit(e) {
const sheet = e.range.getSheet();
const row = e.range.getRow();
const lastCol = sheet.getLastColumn();
const values = sheet.getRange(row, 1, 1, lastCol).getValues()[0];
const timestamp = values[0]; // A: 送信日時
const dreamDate = values[1]; // B: 夢を見た日(Date型のことが多い)
const dreamTitle = values[2]; // C: タイトル
const dreamContent = values[3]; // D: 内容
// スプレッドシート全体のオブジェクト
const ss = SpreadsheetApp.getActiveSpreadsheet();
// 占い結果送信先メールアドレス(スクリプトプロパティから)
const FIXED_EMAIL = PropertiesService.getScriptProperties().getProperty('FIXED_EMAIL');
// GoogleフォームURL(スクリプトプロパティから)
const FORM_URL = PropertiesService.getScriptProperties().getProperty('FORM_URL');
// GoogleスプレッドシートURL
const sheetUrl = ss.getUrl();
// 「夢を見た日」をyyyy/MM/dd形式にする
const tz = Session.getScriptTimeZone();
const dreamDateObj = (dreamDate instanceof Date) ? dreamDate : new Date(dreamDate);
const dreamDateStr = Utilities.formatDate(dreamDateObj, tz, 'yyyy/MM/dd');
// 「設定」シートからメール通知フラグ取得
const settingsSheet = ss.getSheetByName('設定');
let mailFlag = 'OFF'; // デフォルト
if (settingsSheet) {
mailFlag = String(settingsSheet.getRange('B1').getValue()).trim().toUpperCase();
}
// 1. Geminiで夢占い結果を生成
let result;
try {
result = callGeminiForDream_(dreamContent);
} catch (err) {
result = '【エラー】夢占い結果の取得に失敗しました:' + err.message;
}
// 2. シートE列に結果を書き込み
const RESULT_COL = 5;
sheet.getRange(row, RESULT_COL).setValue(result);
// 3. 通知フラグONの場合のみメール送信
if (mailFlag === 'ON' && FIXED_EMAIL) {
const subject = `【夢占い結果_自動通知_${dreamDateStr}】`;
const body =
'▼夢を見た日\n' + dreamDateStr + '\n\n' +
'▼夢のタイトル\n' + (dreamTitle || '(タイトルなし)') + '\n\n' +
'▼夢の内容\n' + dreamContent + '\n\n' +
'▼夢占い結果(AI分析)\n' + result + '\n\n' +
'▼過去の夢日記一覧(スプレッドシート)\n' + sheetUrl + '\n\n' +
'▼新しく夢日記をつける(Googleフォーム)\n' + FORM_URL + '\n\n' +
'※このメールは、Apps Scriptで自動生成されています。';
MailApp.sendEmail(FIXED_EMAIL, subject, body);
}
}
AIへの出力はこのフォーマットに統一
【キーワード】
XXX:意味
XXX:意味
【夢のまとめ】
XXXXX
余計な説明や挨拶は出さないようプロンプトで固定しています。
④ フォーム送信時のトリガーを設定
- Apps Script左側メニューの「トリガー」(時計アイコン)をクリック
- 右下の「トリガーを追加」を押す
- 以下のように設定する
| 項目 | 設定内容 |
|---|---|
| 実行する関数 | onFormSubmit |
| 実行するデプロイ | ヘッド(デフォルトのまま) |
| イベントのソース | スプレッドシートから |
| イベントの種類 | フォーム送信時 |
- 「保存」をクリック
- 最初だけ Google が権限を確認してくるので「許可する」を押す
これで、フォーム送信時に以下の処理が自動実行されます。
- フォーム入力情報の取得
- GeminiへAPIリクエスト
- Googleスプレッドシートへの書き込み
- メール通知
⑤メール通知ON・OFFもシートで切替可能に
スプレッドシートに「設定」シートを新規作成し、
| A1 | B1 |
|---|---|
| メール通知 | ON |
とするだけで、
-
ON→ メール送る -
OFF→ ログを残すだけ
を切替できます。
普段はON、深夜にテストするときはOFF、など運用が楽になります。
私がものぐさで設定をいじるのが手間なので追加しました。
トリガー設定、ファイル修正でも問題ないです
まとめ
今回は、日常の小さな困りごとだった
「夢日記を続けたいけど、占い・記録・管理が手間」
を、Googleフォーム、スプレッドシート、Apps Script、Geminiの組み合わせで自動化しました。
- キーワード&まとめが読み返しやすい
- 過去の夢はシートで一覧化できる
この2点は私にとって大きなメリットとなり、
ほんのちょっと、
日常がラクになりました。


