3つに分けて配布した経緯

元は3モールで使っていたフル版

このツールは、商品名・説明文の改善提案を作り、検索順位を毎朝計測するスプレッドシートです。元は自社の運用で3モール(Amazonを含む)に対して使っていたフル版でした。

配布にあたり、まずAmazon関連を物理的に取り除いた、楽天とYahoo!の2モールのセット版を作りました。その後、セット版からさらに楽天単体版とYahoo!単体版を切り出しています。

単体版で取り除いたもの

単体版では、もう一方のモールに関する関数、定数、メニュー項目、スプレッドシートのタブ、診断項目を取り除きました。たとえば楽天単体版では、Yahoo!の競合取得、カタログ取り込み、検索順位・カテゴリ順位のバッチをそれぞれ除去しています。

版の経過は、v1.0、v1.1(2026-07-03に改良差分を3-wayマージで適用)、v1.1 patch(2026-07-04)です。今回の3件は、v1.1 patch(2026-07-04)で直したものです。

3件に共通する原因

3件とも、「片方のモールだけで使う」状態を実際に動かして試していなかったことが共通の原因でした。除去したことはgrepで確認していましたが、除去したあとに片方だけで動かす確認が足りていませんでした。

不具合1: セット版で楽天だけ使うと、毎朝の計測が止まる

症状

セット版で、Yahoo!のID(YAHOO_APPID)を設定せず楽天だけで使うと、毎朝の自動計測が全滅する状態でした。具体的には、Yahoo!競合取得のバッチ(fetchCompetitorsBatch)とYahoo!カテゴリ順位のバッチ(measureYahooCategoryBatch)が、未設定を理由に例外を投げていました。

楽天側のバッチは、未設定ならスキップする作りでした。つまり、同じ「未設定」に対する扱いが、2つのモールで食い違っていました。

同梱の説明との不一致

同梱の説明には「片方だけでもOK」と書いてありました。実装は、その説明と一致していませんでした。

直し方

Yahoo!側のバッチを、楽天側と同じ形に揃えました。未設定のときは、okのログを残し、skipped:true を返して処理を抜けます。

  • 未設定は異常ではなく、正常系として扱う
  • スキップした事実は実行ログに残す
  • 2モールで同じ振る舞いにする

あわせて、診断関数 summarizeSetup も、どちらか一方のモールが設定されていれば ok とする判定(at-least-one-mall)に変えました。これで、説明の「片方だけでもOK」と実装が一致します。上流のリポジトリにも同じ修正を反映しています。

不具合2: 楽天単体版の診断が、正しく設定しても「必須の設定が必要」になる

症状

楽天単体版の設定診断(summarizeSetup)が、フル版由来のYahoo!必須の判定のまま残っていました。修正前の判定は、次のとおりです。

  • 必須タブが「競合解析(Yahoo!)」「勝ちパターン(Yahoo!)」になっている
  • YAHOO_APPIDとYahoo!のストアIDが、未設定なら ng(必須エラー)になる
  • 反映方法の文言が、ストアクリエイターProの手順になっている

楽天単体版には、そもそもYahoo!のタブを作る処理がありません。そのため、楽天の設定を正しく済ませても、診断は常に「❌必須の設定が必要」を出し続けます。

なぜ見落としやすいか

診断は、ツール本体の動作とは別の部品です。バッチや順位計測が動いていても、診断だけが前提のずれたまま残ります。しかも症状が「設定が足りない」という表示なので、使う人は自分の設定のほうを疑いやすくなります。

直し方

診断の前提を、楽天のものに置き換えました。

  • 必須タブを、楽天のタブにする
  • 楽天のApp IDとショップコードが未設定なら ng にする
  • 狙いキーワードが0件なら ng にする
  • 商品が0件なら warn(警告)にする
  • 反映方法の文言を、RMSの手順にする

不具合3: Yahoo!単体版に、存在しない楽天の診断項目が12個出ていた

症状

Yahoo!単体版の診断に、楽天グループの項目が12個表示されていました。この版には楽天の機能が存在しないため、表示されても対応のしようがない項目です。

直し方

summarizeSetup から楽天グループを取り除き、Yahoo!専用の診断にしました。関数の説明コメント(JSDoc)も、実態に合わせて更新しています。

不具合2と3は、同じ関数の同じ種類の問題で、向きが逆なだけです。片方は「持っていない前提を必須にした」、もう片方は「持っていない機能の項目を表示した」というものでした。

ついでに見つかった別件

楽天単体版のv1.1では、もう1件見つかっています。メニューが、存在しない関数名(cleanRankLogByDate と cleanObsoleteKeywordLogs)を呼んでいました。

v1.0ではクリックすると「関数が見つかりません」のエラーになります。正しい関数名(pruneRankLog と cleanupOldKeywords)に直しました。

出荷前の検証と、直したあとの確認方法

v1.1の配布前検証項目

v1.1の配布前には、次の項目を確認しています。

  • すべての .gs と .js に対する node --check の構文チェック
  • pure-logic.js が require で読み込めること
  • メニューの .addItem、newTrigger、HTMLの google.script.run が呼ぶ関数が、すべて実在すること
  • 他モールの function 定義が0件であること、実店舗の識別子、実IDのサンプル、実APIキーが0件であること

単体版では、逆のモールの function 定義が0件であることを、grepでも確認しています。

不具合2・3の確認

診断の修正では、文字列の検索だけで済ませず、関数を実際に実行して確かめました。

  • 設定済みの状態を渡すと ok:true になる
  • IDが無い状態を渡すと ok:false になる
  • 関数の中に、逆のモールの語(Yahoo・ストアクリエイター、または楽天・rakuten)が0件であることを、独立したgrepで二重に確認する

セット版と上流リポジトリにも同じ修正を反映しました。上流のリポジトリでは、修正後に315件のテストが通った記録があります。

この件から整理した3つの点

以下は、今回の経験からの整理です。他のツールにそのまま当てはまると断定するものではありません。

  • 除去は、grepで「消えたか」を数えれば確かめられます。一方で「残った側が片方だけで正しく動くか」は別の検査で、実際にその状態で動かさないと分かりません。
  • 未設定を異常(例外)にするか、正常(スキップ)にするかは、モール間で揃えます。今回は、揃っていなかったことが不具合1の原因でした。
  • 設定の診断は、フル版の前提を最も引きずりやすい部品でした。単体版を作るときは、診断を最初に見直す対象にするのがよさそうです。

メニューのように名前で関数を呼ぶ参照は、実在を確認する作業を機械化できます。v1.1 の配布前検証には、この実在確認を項目として入れています。

この記事の範囲と、参照した資料

この記事に書いたこと

書いたのは、配布の準備中に見つかった不具合3件と、v1.1で見つかったメニューの別件、その直し方と確認方法です。

この記事に書いていないこと

  • 不具合による実害の有無は、記録が無いため書いていません。「出荷前に見つけた」範囲に限っています。
  • v1.0の時点で、これらの不具合が配布物に入っていたかどうかも、断定していません。
  • 販売数、売上、購入者からの報告については、記録が無いため触れていません。

参照した資料

  • セット版 v1.1 の MANIFEST(v1.1 更新と v1.1 patch の記録)
  • 楽天単体版 v1.1 の MANIFEST(除去した項目の一覧、v1.1 patch の記録)
  • Yahoo!単体版 v1.1 の MANIFEST(v1.1 patch の記録)
  • 楽天単体版 v1.0 の summarizeSetup(修正前のコード)