我が家の日用品はほぼ全てがヨドバシカメラの通販で賄われていますが、家計簿ソフトのZaimやマネーフォワードと一切連携できないのが困りもの。
マネーフォワードは分かりませんが、ZaimならAPIを公開してくれているので自作アプリでなんとか自動連携が実現できそうなので作っちゃいました。
2026年現在のZaim API最新仕様(OAuthエンドポイントの変更)に対応済みの完全版ガイドです。
1. 事前準備:Zaim APIの登録
まず、Zaimのデータを外部から操作するための「鍵」を取得します。
- Zaim Developersにログインします。
- 「新しいアプリケーションを追加」をクリック。
- 以下の通り設定して保存します。
- 名称: ヨドバシGAS連携(任意)
- アクセス権限: 全てチェック
- URL:
https://google.com(後で書き換えるので仮でOK)
- 発行された コンシューマ ID と コンシューマ ID をメモしておきます。
2. Gmailの設定(ラベルとフィルタ)
特定のメールだけをGASが読み取れるように設定します。
ラベルの作成
Gmailで以下の2つのラベルを作成してください。
親ラベルとして「Zaim」を作成。その子ラベルとして「待機中」と「完了」を作成。以下の2ラベルが作成されていればOK。大文字小文字も厳格に。
Zaim/待機中Zaim/完了
フィルタの設定
以下の条件でフィルタを作成し、自動でラベルが付くようにします。
- From:
thanks_gochuumon@yodobashi.com - 件名:
ヨドバシ・ドット・コム:ご注文ありがとうございます - 操作: 「ラベル『Zaim/待機中』を付ける」
3. GASのセットアップ
Googleドライブから新しいGoogle Apps Scriptを作成し、以下の準備を行います。
ライブラリの追加
認証に必要な以下の oAuth1 ライブラリを検索して追加します。
- スクリプトID:
1sq6B_97XI9I_T6xc07SIdK_Z7p7mkvYFvO86p0asJ6U-Wp_S_vOALh8B - バージョン: 最新を選択
カテゴリIDとジャンルIDの取得
listZaimCategoriesAndGenres関数を作っておいたので、この関数を実行すればログ欄に一覧で表示されます。記録時のデフォルトカテゴリを決めておいてください。
スクリプトプロパティの設定
「設定(歯車アイコン)」>「スクリプトプロパティ」に以下を追加します。
ZAIM_CONSUMER_KEYZAIM_CONSUMER_SECRETZAIM_CATEGORY_ID:102(好みに合わせて変更)ZAIM_GENRE_ID:10201(好みに合わせて変更)
以下のコードを コード.gs に貼り付けてください。認証用と調査用と実行用の機能を統合しています。
/**
* ヨドバシカメラ×Zaim 自動連携スクリプト (2026 Edition)
*/
const PROPERTIES = PropertiesService.getScriptProperties();
function syncYodobashiToZaim() {
const LABEL_WAITING = "Zaim/待機中";
const LABEL_DONE = "Zaim/完了";
const SEARCH_QUERY = `label:"${LABEL_WAITING}" after:2026/01/01`;
const labelWaiting = GmailApp.getUserLabelByName(LABEL_WAITING);
const labelDone = GmailApp.getUserLabelByName(LABEL_DONE);
const threads = GmailApp.search(SEARCH_QUERY);
threads.forEach(thread => {
thread.getMessages().forEach(message => {
if (message.getDate().getFullYear() < 2026) return;
const data = parseYodobashiEmail(message.getPlainBody());
if (data) {
postToZaim(data);
console.log(`登録成功: ${data.item} - ${data.amount}円`);
}
});
thread.removeLabel(labelWaiting).addLabel(labelDone);
});
}
function parseYodobashiEmail(body) {
const amountMatch = body.match(/今回のお買い物合計金額\s+([\d,]+)\s*円/);
const dateMatch = body.match(/ご注文日\s+(\d{4})年(\d{2})月(\d{2})日/);
const itemMatch = body.match(/【ご注文商品】[\s\S]*?・「([\s\S]*?)」/);
if (!amountMatch) return null;
return {
amount: parseInt(amountMatch[1].replace(/,/g, ''), 10),
date: dateMatch ? `${dateMatch[1]}-${dateMatch[2]}-${dateMatch[3]}` : null,
item: itemMatch ? itemMatch[1].replace(/\n/g, '').trim().substring(0, 50) : "ヨドバシ注文"
};
}
function postToZaim(data) {
const service = getZaimService();
const url = "https://api.zaim.net/v2/home/money/payment";
const payload = {
mapping: 1,
category_id: PROPERTIES.getProperty('ZAIM_CATEGORY_ID'),
genre_id: PROPERTIES.getProperty('ZAIM_GENRE_ID'),
amount: data.amount,
date: data.date,
place: "ヨドバシカメラ",
comment: data.item
};
service.fetch(url, { method: "post", payload: payload });
}
function getZaimService() {
return OAuth1.createService('Zaim')
.setAccessTokenUrl('https://api.zaim.net/v2/auth/access')
.setRequestTokenUrl('https://api.zaim.net/v2/auth/request')
.setAuthorizationUrl('https://auth.zaim.net/users/auth')
.setConsumerKey(PROPERTIES.getProperty('ZAIM_CONSUMER_KEY'))
.setConsumerSecret(PROPERTIES.getProperty('ZAIM_CONSUMER_SECRET'))
.setAccessToken(PROPERTIES.getProperty('ZAIM_ACCESS_TOKEN'), PROPERTIES.getProperty('ZAIM_ACCESS_TOKEN_SECRET'));
}
// 認証用URL生成
function runAuth() {
const service = getZaimService();
service.reset();
console.log("認証URL: " + service.authorize());
}
/**
* ZaimのカテゴリIDとジャンルIDをログに出力する
*/
function listZaimCategoriesAndGenres() {
const service = getZaimService();
if (!service.hasAccess()) {
console.error("認証が通っていません。先に認証(runAuth)を済ませてください。");
return;
}
// カテゴリ一覧を取得
const catResponse = service.fetch("https://api.zaim.net/v2/home/category");
const categories = JSON.parse(catResponse.getContentText()).categories;
// ジャンル一覧を取得
const genreResponse = service.fetch("https://api.zaim.net/v2/home/genre");
const genres = JSON.parse(genreResponse.getContentText()).genres;
console.log("--- Zaim カテゴリ・ジャンル一覧 ---");
categories.forEach(category => {
// 収入カテゴリなどは除外(income: 0 が支出)
if (category.mode === 'payment') {
console.log(`[カテゴリ] ${category.name} (ID: ${category.id})`);
// このカテゴリに属するジャンル(子要素)を探して出力
const subGenres = genres.filter(g => g.category_id === category.id);
subGenres.forEach(genre => {
console.log(` ┗ [ジャンル] ${genre.name} (ID: ${genre.id})`);
});
}
});
console.log("---------------------------------");
console.log("使いたいIDをコピーしてスクリプトプロパティに設定してください。");
}
5. 認証と自動化
- GASの
runAuth関数を実行し、ログに出たURLをブラウザにコピーして開いて連携を許可します。 - GAS側のログ画面に表示されたアクセストークンとシークレットキーをGASのスクリプトプロパティに追加します。
- 最後に、GASの「トリガー(時計アイコン)」から、
syncYodobashiToZaimを1時間おきに実行するよう設定すれば完了です!
まとめ
一度設定してしまえば、ヨドバシでポチるたびに家計簿が自動で更新されて、それはそれで気持ちいいですw

このようにメールが届くと自動で記録されていきます!
ZaimのAPI仕様変更などでインターネット上にある過去のノウハウや記事が役に立たなかったりと少しハードルは高かったのですが、今回の2026年現在の最新手順で行えば必ず成功しますよ!
おまけ)生成AIって・・・
このコード自体はGeminiに作らせたので、私は動作をデバッグしただけです。
AIは指示していないことは何もやってくれいないのでデバッグが一番大変でしたが・・・例えば、ラベルでの管理を支持していなかったので何年も前からのメールを取り込んで記録してしまって消すのがめちゃ大変だったりとか。
私はエンジニアではないのでこのコードが正しいかなんてまったく分かりません!ただ出てきたコードをコピペしただけですw でも、そんな人間が公開した内容がさらに生成AIの学習データとして勝手に吸い上げていって次の出力になるのだけど、それでいいのかねぇ。
おまけ2)プロンプトの紹介
Geminiにコピペするだけで出来上がるプロンプトも置いておきますね。
以下の指示に従って、ヨドバシカメラの注文メールをZaimに自動登録するGoogle Apps Script(GAS)を作成してください。
1. 処理フローと仕様
トリガー: Gmailのラベル Zaim/待機中 が付いているスレッドを対象とする。
フィルタ: 2026年以降のメールのみを対象とするため、GmailApp.search('label:"Zaim/待機中" after:2026/01/01') を使用すること。
データ抽出: メール本文から「合計金額」「注文日(yyyy年mm月dd日形式をyyyy-mm-ddへ変換)」「商品名」を正規表現で抽出する。
Zaim連携: Zaim API(OAuth 1.0a)を使用して支出データをポストする。その際、店名(place)に「ヨドバシカメラ」を設定すること。
ステータス管理: 完了したスレッドからは Zaim/待機中 ラベルを削除し、Zaim/完了 ラベルを付与する。
セキュリティ: 認証情報(Consumer Key/Secret, Access Token/Secret)およびカテゴリID、ジャンルIDは PropertiesService から取得する。
2. 技術的要件(2026年最新仕様)
Zaim APIのエンドポイントは最新のものを利用すること。
Request Token: https://api.zaim.net/v2/auth/request
Access Token: https://api.zaim.net/v2/auth/access
ヨドバシの最新メール形式(thanks_gochuumon@yodobashi.com から届く、「今回のお買い物合計金額」や「【ご注文商品】」という項目がある形式)に対応したパース処理を書くこと。
OAuth1ライブラリを使用する前提のコードにすること。
3. アウトプット
そのまま貼り付けて動く完結したコード。
必要なスクリプトプロパティの一覧。
Zaimのカテゴリ・ジャンルIDを確認するための補助関数。


ひとことコメント コメント欄以外は任意入力です