addashboard-cli 0.6.0 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,6 +21,8 @@ ad-hoc に `python3 -c` / `curl` / `ls -t` を書かない。**定型作業は
21
21
  skills/ad-ops/scripts/adops.sh preflight <platform> <accountId> # フェーズ0: ログイン + アカウント疎通確認
22
22
  skills/ad-ops/scripts/adops.sh planner [--stop] # フェーズ2: プランナーをHTTPで開く
23
23
  skills/ad-ops/scripts/adops.sh plan [<入稿計画.json>] # フェーズ3: DL回収 + 要約 + lint + 合意との差分
24
+ skills/ad-ops/scripts/adops.sh open <platform> <accountId> [campaigns|adgroups|ads] # 管理画面を開く(中間層は YDA=adgroups / Meta=adsets に自動変換)
25
+ skills/ad-ops/scripts/adops.sh refs-import <platform> <accountId> [--write] # 実アカウントから参照表を取り込む
24
26
  ```
25
27
 
26
28
  | サブコマンド | やること |
@@ -28,6 +30,12 @@ skills/ad-ops/scripts/adops.sh plan [<入稿計画.json>] # フェ
28
30
  | `preflight` | `auth whoami` → `list --resource accounts` を1回だけ叩き、**その accountId が接続中の認証情報で入稿可能か**を判定。不可なら exit 1 でアクセス可能なアカウント一覧を出す |
29
31
  | `planner` | ポート 8799 で `http.server` を起動(起動済みなら再利用)してブラウザで開く。`--stop` で停止 |
30
32
  | `plan` | `~/Downloads` に落ちた入稿計画を `入稿計画/` へリネーム移動し、構成を表で要約し、**dry-run が検出しない不備**を lint し、`サンプルプラン.json`(=合意内容)との**差分だけ**を出す |
33
+ | `open` | アカウントJSONの `mccId` を読んで管理画面URLを組み立てて開く。`--dry` でURLを出すだけ。**中間層の語は媒体で違う**(YDA=`adgroups` / Meta=`adsets`)が、どちらの表記で渡しても媒体別の正しい語へ変換される |
34
+ | `refs-import` | `webgram list` の `campaigns` / `ads` / `resources` を叩き、見出し・説明文・CP名・広告グループの `campaignId`/`paramCode`/`finalUrlSample`・オーディエンス・配置面をアカウントJSONの `refs` にマージ。既定は差分表示のみ、`--write` で書き込み |
35
+
36
+ **【必須】管理画面URLを手で組み立てない。** 媒体ごとのURL形式(YDA の `mccId` 等)は `adops.sh open` に集約してある。SKILL.md や応答にURLをベタ書きすると、今回のように形式が変わったとき全箇所が腐る。
37
+
38
+ > **YDA はキャンペーン詳細への直リンクを表現できない**(管理画面は `#/{mccId}/{accountId}/list/{resource}` = 一覧ルートしか持たない)。**一覧を開いて CP 名で探す**方針で妥協する。
31
39
 
32
40
  ## 【最重要】フェーズ0: 疎通確認(戦略壁打ちより前)
33
41
 
@@ -47,6 +55,20 @@ skills/ad-ops/scripts/adops.sh preflight yda <accountId>
47
55
  > 全件パスしたが、`list accounts` が返す 17 件に含まれておらず本実行で 401。
48
56
  > フェーズ1〜3 の作業がすべて無駄になった。
49
57
 
58
+ ## 【必須】入口メニュー: 用途の分岐
59
+
60
+ **本スキルが発火したら、フェーズ0 の `preflight` を通したうえで、最初に `AskUserQuestion` で用途を確認する。**(文脈から暗黙に判断しない。特に「ローカル画像で入稿」は暗黙判断では絶対に選ばれない)
61
+
62
+ | 選択肢 | 遷移先 |
63
+ |---|---|
64
+ | 動画を API 入稿する | 下の「動画入稿フロー」Step 0〜6 |
65
+ | **ローカル画像で入稿する** | 下の「画像入稿フロー(ローカル画像・YDA)」Step 0〜6 |
66
+ | 入稿プランナーで量産する | 「起点フロー(4フェーズ)」 |
67
+ | チーム週次レビューを見る | 「チーム週次レビュー取得(review コマンド)」 |
68
+
69
+ * **`preflight` は分岐前の共通の前提**。落ちたら分岐せずその場で止めて報告する
70
+ * ユーザーの依頼に媒体・素材が明示されていれば選択肢の既定として提示してよいが、**確認そのものは省略しない**
71
+
50
72
  ## 動画入稿フロー (メイン用途)
51
73
 
52
74
  macOS Finder で「option キー長押し → パス名をコピー」した動画パスを、ユーザーがドラッグ&ドロップで提示するところから始まる半自動ワークフロー。
@@ -90,6 +112,8 @@ npx -y addashboard-cli@latest auth whoami
90
112
 
91
113
  * 予算: 新規 = 12,000 円、ASC = 50,000〜100,000 円
92
114
 
115
+ * **スマートターゲティング: 常時 ON** (backend 側の既定も `true`。明示的に OFF にしたい場合だけユーザーに確認する)
116
+
93
117
  **必ずユーザー確認 or 自動生成が必要な項目**:
94
118
 
95
119
  * **入稿先アカウント名**: アカウント名で指定可 (アカウント ID は不要、CLI 側で名前 → ID 解決)。指定なければ AskUserQuestion で聞く
@@ -143,20 +167,86 @@ npx -y addashboard-cli@latest submit \
143
167
 
144
168
  ### Step 6: 管理画面 URL を開く
145
169
 
146
- 入稿完了後、対象媒体の管理画面 (該当キャンペーンの詳細ページ) を **`open <URL>`** **で開く**。ユーザーが目視で入稿結果を確認できるようにする。
170
+ 入稿完了後、対象媒体の管理画面を **`adops.sh open`** で開く。ユーザーが目視で入稿結果を確認できるようにする。
171
+
172
+ ```bash
173
+ skills/ad-ops/scripts/adops.sh open yda <accountId> campaigns
174
+ skills/ad-ops/scripts/adops.sh open meta <accountId> campaigns
175
+ ```
176
+
177
+ * **URL を手で組み立てない。** YDA は `mccId` がアカウントJSON(v2)由来で、手書きすると 404 / 白画面になる
178
+
179
+ * **YDA はキャンペーン詳細への直リンクを表現できない**(`list/` 配下しかルートが無い)。**キャンペーン一覧を開き、Step 5 で入稿した CP 名で探してもらう**
180
+
181
+ * `resource` は `campaigns` / `adgroups` / `ads`。**中間層は媒体で語が違う**(YDA=`adgroups` / Meta=`adsets`)が、`adops.sh open` がどちらの表記でも受けて媒体別の正しいURLに変換する(**URLを手で組み立てるとここを間違える**)。複数入稿した場合も一覧を 1 つ開けば十分
182
+
183
+ * TikTok は将来対応時に `adops.sh open` へ追加する
184
+
185
+ ## 画像入稿フロー(ローカル画像・YDA)
186
+
187
+ **手元のローカル画像ファイルを、プランナーを開かずに少数だけ入稿する**ときのフロー。動画入稿フローと同じ Step 構成で、差分だけを以下に書く(共通部分は動画側を参照)。
147
188
 
148
- * YDA: `https://ads-display.yahoo.co.jp/campaign/detail?accountId=<accountId>&campaignId=<campaignId>` (キャンペーン ID は Step 5 の応答から取得)
189
+ **新しい CLI コマンドは無い。** Skill が Step 3-4 の合意内容から**最小の入稿計画JSON**(`planVersion:1` / `ads[].imagePaths[]`)を組み立て、`adops.sh plan` の lint → `submit-plan` の dry-run → 本実行に流す。量産する場合はプランナーの `画像パス` 列(同じ `imagePaths` 契約)を使う。
190
+
191
+ ### Step 0: ログイン状態確認
192
+
193
+ 動画入稿フロー Step 0 と共通(`auth whoami`)。
194
+
195
+ ### Step 1: ローカル画像ファイルパスの受け取り
196
+
197
+ * 受け付ける形式は 3 つ: **絶対パス** / **`~/…`** / **カレント基準の相対パス**(入稿計画JSONに書いたあとの相対の基準は**計画JSONのディレクトリ**になる点に注意)
198
+
199
+ * パスが未指定なら AskUserQuestion で提示を促す
200
+
201
+ * **ディレクトリを渡された場合**は allowlist 拡張子(`.jpg` `.jpeg` `.png` `.gif`)で列挙し、対象ファイルをユーザーに確認する
202
+
203
+ ### Step 2: 入稿モードの判定
204
+
205
+ `新規` / `既存-広告追加` のどちらか。動画入稿フロー Step 2 と共通。
206
+
207
+ ### Step 3: パラメータ収集
208
+
209
+ 固定デフォルト(アトリビューション 1 日 / CTA / 入札 / 予算 / **スマートターゲティング常時 ON**)は動画入稿フロー Step 3 の表を共有する。**画像固有で必ず確認する項目**:
210
+
211
+ | 項目 | 内容 |
212
+ |---|---|
213
+ | 入稿先アカウント名 | 名前で指定可(CLI が ID 解決)。`preflight` 済みであること |
214
+ | キャンペーン / 広告グループ | 新規作成か、既存の CP/AG へ広告追加か |
215
+ | 見出し・説明文 | 本文そのもの。既存アカウントの文言を使うなら `adops.sh refs-import yda <accountId>` で吸い出す |
216
+ | 最終リンク先URL | 記事の完全URL |
217
+ | **URLパラメータ ON/OFF** | アカウントJSONの `urlParamsEnabled`。OFF なら `?ad=` / `&creative=` を付けない |
218
+ | **広告名の命名方針** | アカウントJSONの `adNamePolicy`。`imageNo`(既定 = 画像番号ベースの自動生成)/ `free`(自由入力) |
219
+
220
+ ### Step 4: 一覧提示 → OK 確認 (必須)
149
221
 
150
- * Meta: `https://adsmanager.facebook.com/adsmanager/manage/campaigns?act=<accountId の数値部分>`(`act_` は除いた数値を渡す)
222
+ 画像枚数ぶんの入稿リストを **表形式で提示** し、必ず AskUserQuestion で OK 確認を取る。**OK が取れるまで Step 5 に進まない。**
151
223
 
152
- * TikTok は将来対応時に URL 形式を追記
224
+ | # | 画像ファイル | **解決後の絶対パス** | **実在** | 見出し | 説明文 | 広告名 | 最終リンク先URL |
225
+ | - | ------- | ------------ | ---- | --- | --- | --- | --------- |
226
+ | 1 | a.jpg | /Users/…/a.jpg | ✅ | … | … | 01c-… | https://… |
227
+ | 2 | b.png | /Users/…/b.png | ❌ | … | … | 02c-… | https://… |
153
228
 
154
- * 複数入稿した場合は、キャンペーン一覧ページ (`https://ads-display.yahoo.co.jp/campaign/list?accountId=<accountId>`) を 1 つ開けば十分
229
+ **解決後の絶対パスと実在チェックを必ず表に入れる**(誤パスはここで殺す。`~` の展開結果もここで見える)。
230
+
231
+ ### Step 5: 順次実行
232
+
233
+ 1. 合意内容から最小の入稿計画JSONを `入稿計画/` に書き出す(`ads[].imagePaths[]` にローカルパス)
234
+ 2. `adops.sh plan <入稿計画.json>` — lint で **`imagePaths` の不存在は ERROR**。ERROR が残るうちは進まない
235
+ 3. dry-run: `npx -y addashboard-cli@latest submit-plan --plan-file <入稿計画.json>`
236
+ 4. 本実行: `--no-dry-run --yes`。`POST /api/submission/yda/upload-image` で**アップロード → mediaId 解決 → 広告作成**の順で走る
237
+
238
+ * 解決した mediaId は計画ファイルに書き戻され、再開時に再アップロードしない
239
+ * **重複画像は D0001 で既存 mediaId が再利用される**ので二重登録の心配は無い
240
+ * 途中失敗は握りつぶさず、残りを続けるか `AskUserQuestion` で確認
241
+
242
+ ### Step 6: 管理画面 URL を開く
155
243
 
156
244
  ```bash
157
- open "https://ads-display.yahoo.co.jp/campaign/detail?accountId=<accountId>&campaignId=<campaignId>"
245
+ skills/ad-ops/scripts/adops.sh open yda <accountId> campaigns
158
246
  ```
159
247
 
248
+ 動画入稿フロー Step 6 と共通(CP詳細への直リンクは不可。一覧で CP 名を探す)。
249
+
160
250
  ## 媒体別の注意
161
251
 
162
252
  **上記の動画 API 入稿フロー (`submit --video`) の対応は YDA のみ。** Meta は **入稿プランナー経由 (`submit-plan`)** で画像/動画とも入稿できる。TikTok を指定された場合は「未対応」と明示してから相談する。
@@ -180,6 +270,7 @@ open "https://ads-display.yahoo.co.jp/campaign/detail?accountId=<accountId>&camp
180
270
  | ヘルプ | `npx -y addashboard-cli@latest --help` |
181
271
  | アカウント一覧 | `npx -y addashboard-cli@latest list --platform <yda\|meta\|google\|smartnews\|bytedance> --resource accounts` |
182
272
  | キャンペーン一覧 | `npx -y addashboard-cli@latest list --platform <媒体> --resource campaigns --account-id <id>` |
273
+ | **広告一覧 (YDA)** | `npx -y addashboard-cli@latest list --platform yda --resource ads --account-id <id> --campaign-id <cpId>`(広告グループで絞るなら `--ad-group-ids <id1,id2>`。どちらか必須) |
183
274
  | 登録画像一覧 (YDA) | `npx -y addashboard-cli@latest list --platform yda --resource media --account-id <id>` |
184
275
  | 登録画像一覧 (Meta) | `npx -y addashboard-cli@latest list --platform meta --resource image-library --account-id act_<id>`(imageHash) |
185
276
  | 登録動画一覧 (Meta) | `npx -y addashboard-cli@latest list --platform meta --resource video-library --account-id act_<id>`(videoId) |
@@ -187,6 +278,8 @@ open "https://ads-display.yahoo.co.jp/campaign/detail?accountId=<accountId>&camp
187
278
  | 汎用入稿 (JSON) 実入稿 | `npx -y addashboard-cli@latest submit --platform <媒体> --json-file <path> --no-dry-run --yes` |
188
279
  | 入稿計画 順次入稿 dry-run | `npx -y addashboard-cli@latest submit-plan --plan-file <入稿計画.json>`(yda / meta。`plan.platform` 未記載は yda 扱い) |
189
280
  | 入稿計画 順次入稿 実入稿 | `npx -y addashboard-cli@latest submit-plan --plan-file <入稿計画.json> --no-dry-run --yes`(1CPずつ・再開可能) |
281
+
282
+ **【重要】本実行がタイムアウトしたら「失敗」と決めつけない。** CLI の進捗は `unknown`(成否不明)になる。backend は入稿を続けており、**キャンペーンと広告が作成済みのことがある**(実測あり)。この状態で再実行すると二重入稿になるため `unknown` は自動でスキップされる。媒体の管理画面を確認し、作成済みなら計画ファイルの `status` を `"submitted"`、未作成なら `"pending"` に直してから再実行する(exit code は 3)。
190
283
  | チーム週次レビュー取得 | `npx -y addashboard-cli@latest review --team <伊藤T\|松井T> [--week <YYYY-MM-DD>]` |
191
284
  | 「予実」「予実管理」「今月の予実」「着地予測」「予実サマリ」 | `npx -y addashboard-cli@latest pl summary`(月指定は `pl summary --month YYYY-MM`) |
192
285
  | 「案件別の予実」「案件ごとの損益」 | `npx -y addashboard-cli@latest pl projects`(`--month` / `--status` / `--platform` で絞り込み可) |
@@ -243,6 +336,7 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
243
336
  動画の API 入稿とは別に、**一括入稿を計画・確認する**ためのシングルHTMLツール。2026-07-16 / 07-21 定例フィードバックを反映。**2026-07-23 に CSV 書き出しを廃止し、保存・入稿受け渡しを JSON に統一**。**2026-07-30 に媒体スキーマ駆動化(`PLATFORMS` レジストリ)して Meta に対応**。
244
337
 
245
338
  - **ファイル**: 本スキル同梱の [`ad-planner.html`](./ad-planner.html)(旧 `yda-planner.html` からリネーム。ローカルで開くだけ・依存なし)
339
+ - **作業中プランの指定**: `アクティブプラン.json`(媒体 / 案件名 / サンプルプランファイル)。プランナーは起動時にこれを読んで案件×媒体を自動選択する。**書き出し口は `adops.sh planner --platform <媒体> --account "<案件名>"` の1つだけ**。各自のローカル作業状態なので git では追跡しない(追跡すると他メンバーの作業対象が既定として配られる)
246
340
  - **媒体切替**: ヘッダーの **統合プルダウン(`<案件名> YDA` / `<案件名> Meta`)** で切替。案件(アカウント)と媒体を1つの選択で同時に切り替える。列定義・enum変換・命名規則・検証・入稿ボディ変換・プロンプト文言はすべて媒体定義側にあり、コアは「3階層 × 表 × 参照解決 × 除外集計」だけを持つ。プラン・履歴・参照データは **媒体別に保存**される(localStorage キー `ad_planner_*`。旧 `yda_planner_*` からは初回に1回だけ自動マイグレーション)
247
341
  - **役割**: 動画の API 入稿=`addashboard-cli submit`(YDA のみ)、**まとめ入稿=このプランナーで計画 → 「入稿JSON書き出し」(入稿計画JSON planVersion:1)→ `submit-plan` に流す**(Yahoo管理画面CSVインポートは廃止)。
248
342
  - **基本思想(定例)**: AIで生成できる部分は **AIに生成させ(JSON読込)**、絶対に人が確定する部分(クリエイティブ選定・確認)を **スプシ的コピペ・一括入力・複製** で楽にする。プランナーで確認・修正して **OK なら 入稿JSON書き出し(=GO)→ `submit-plan` dry-run一括検証 → 本実行**(1キャンペーンずつ入稿・進捗書き戻しで再開可能)。
@@ -258,11 +352,12 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
258
352
  | クリエイティブ形式 | 画像のみ(Card 1200 / SQ 1080 の mediaID) | **画像(imageHash)/動画(videoId + サムネ imageHash)両対応**(広告行の形式列 IMAGE / VIDEO) |
259
353
  | 参照データ (`refs.media`) | `{card, sq}` | `{image, video, thumb}` |
260
354
  | プロジェクト必須項目 | accountId / 目的(goal) / 配信開始日 / 入札 | accountId(`act_`) / **FBページID** / **pixelId**(`OFFSITE_CONVERSIONS`/`VALUE` 時) / CVイベント / 最適化 / 課金 / 入札戦略 / 配信開始日(配信終了日は任意) |
355
+ | 配信期間の指定階層 | 案件設定チップのみ(配信開始日) | **広告セット行の列 → 案件設定チップ → 既定(当日)** の順で解決。**時刻も指定可**(`YYYY-MM-DD [HH:mm[:ss]]`・JST) |
261
356
  | 入札 | 最大配信 / tCPA(`MAXIMIZE_CONVERSIONS`+targetCpa) | `LOWEST_COST_WITHOUT_CAP` / `LOWEST_COST_WITH_BID_CAP` / `COST_CAP` / `LOWEST_COST_WITH_MIN_ROAS`(後2者は `bidAmount` 必須) |
262
- | ターゲティング列 | 年齢 / 性別 / デバイス / 地域・オーディエンス・サーチKW(後3者は入稿JSONに載らない警告付き) | 年齢(ageMin/ageMax) / 性別 / デバイス / 配置(Facebook / Instagram / Audience Network / Messenger、既定は自動配置) |
357
+ | ターゲティング列 | 年齢 / 性別 / デバイス / 曜日時間帯 / **オーディエンス(含む・除外)** / **配置(含む・除外)** / 地域・サーチKW。**オーディエンス・配置は参照表の実IDで入稿JSONに載り、本番の配信ターゲティングに反映される**(数値IDでない値は落として警告)。**入稿JSONに載らないのは 地域 と サーチKW だけ** | 年齢(ageMin/ageMax) / 性別 / デバイス / 配置(Facebook / Instagram / Audience Network / Messenger、既定は自動配置) |
263
358
  | 命名規則 | `{番号}{c\|s}-{見出し}L{本文}-{paramCode}` / `?ad=&creative=` | **同形式を踏襲**(形式記号は `i`(画像) / `v`(動画)) |
264
359
  | 手入稿の除外 | バナー(固定サイズ)は API 未対応 → `手入稿` フラグで入稿JSONから除外 | 手入稿フラグの区分は無し(未解決の広告のみ除外) |
265
- | 管理画面 | `ads.yahoo.co.jp/manager/#/...` | `adsmanager.facebook.com/adsmanager/manage/campaigns?act=<数値>` |
360
+ | 管理画面 | `https://ads.yahoo.co.jp/manager/#/{mccId}/{accountId}/list/campaigns`(**CP詳細への直リンクは不可**) | `adsmanager.facebook.com/adsmanager/manage/campaigns?act=<数値>` |
266
361
 
267
362
  **Meta で未対応(今回スコープ外)**: カルーセル/コレクション等の複数素材フォーマット、カスタムオーディエンス/類似オーディエンスの ID 解決、地域ターゲティングの細分化(国単位のみ)、既存キャンペーンの複製テンプレート運用の GUI 化。**本番 Meta API への本入稿 PoC も未実施**。
268
363
 
@@ -275,7 +370,7 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
275
370
  | # | フェーズ | 完了条件(次へ進める条件) |
276
371
  | - | ---- | ------------- |
277
372
  | 0 | **疎通確認** | `adops.sh preflight <媒体> <accountId>` が通った(ログイン済み かつ そのアカウントに入稿できる) |
278
- | 1 | **戦略壁打ち** | 商材・目的・予算・訴求点をもとに、ターゲティング方針 / キャンペーン>広告グループ(広告セット)構成 / 訴求軸をユーザーと合意した |
373
+ | 1 | **戦略壁打ち** | 商材・目的・予算・訴求点をもとに、ターゲティング方針 / キャンペーン>広告グループ(広告セット)構成 / 訴求軸をユーザーと合意した。**下記3点の確認も完了している** |
279
374
  | 2 | **プランナー確認** | サンプルプラン JSON を書き出し、**ユーザーがプランナーを開いて内容を目視確認した** |
280
375
  | 3 | **入稿計画** | プランナーから入稿計画JSON(`planVersion:1`)を書き出し、`submit-plan` の **dry-run が全件パス**した |
281
376
  | 4 | **実行** | `--no-dry-run --yes` で本実行し、結果を報告した |
@@ -291,9 +386,13 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
291
386
 
292
387
  0. **疎通確認**: `adops.sh preflight <媒体> <accountId>` を通す。落ちたら戦略を練らずに止めてユーザーに報告する(上の「フェーズ0」章を参照)。
293
388
  1. **戦略壁打ち**: AI(Claude Code)に商材・目的・予算・訴求点を伝え、ターゲティング方針・キャンペーン/広告グループ構成・訴求軸を提案させる。合意できたら `AskUserQuestion` で承認を取る。
389
+ **【必須】このフェーズで `AskUserQuestion` により次の3点を確認する**(後から変えると finalUrl・広告名・計測が全部ズレるため):
390
+ 1. **URLパラメータ ON/OFF** — `?ad=` / `&creative=` を付けるか。結果はアカウントJSONの `urlParamsEnabled` に固定する(キー無し = ON)
391
+ 2. **広告名の命名方針** — 既定 = 画像番号ベースの自動生成(`imageNo`)/ 自由入力(`free`)。結果は `adNamePolicy` に固定する。**自由入力にすると `finalUrl` の `creative=` も広告名に追従して変わる**ことを併せて伝える
392
+ 3. **スマートターゲティングは常時 ON** であることを通知する(明示 OFF は lint が WARN で拾う)
294
393
  2. **プランナー確認**:
295
394
  1. 合意した戦略を本スキル同梱のサンプルプラン(**YDA=`サンプルプラン.json` / Meta=`サンプルプラン_meta.json`**、保存先はいずれも `.claude/skills/ad-ops/` 直下、フォーマット: `{"schemaVersion":3, "platform":"yda|meta", "accountId":"<ID>", "campaigns":[ キャンペーン>広告グループ(=Metaは広告セット, paramCode)>広告 ]}`)に **上書き**する。このファイルは以降 **「合意内容の正」** として `adops.sh plan` の差分比較に使われるので、合意した構成をそのまま反映すること。
296
- 2. **`adops.sh planner` で開く(`open <path>` で開かない)。** すでに開いているならリロードする(Meta なら統合プルダウンで Meta の案件に切替)。起動時に当該媒体のサンプルプランが読み込まれ、キャンペーン > 広告グループ/広告セット > 広告として表示される(accountId が現アカウントと不一致なら読み込まない安全弁あり)。
395
+ 2. **`adops.sh planner --platform <媒体> --account "<案件名>"` で開く(`open <path>` で開かない)。** `--platform` / `--account` は「いま作業中のプラン」(`アクティブプラン.json`)を書き換えてから開くための指定で、**今回の案件×媒体を必ず渡す**。渡さないと前回の作業対象のまま開き、別案件のアカウントを既定にしたまま作業を始めることになる。すでに開いているならリロードする(Meta なら統合プルダウンで Meta の案件に切替)。起動時に当該媒体のサンプルプランが読み込まれ、キャンペーン > 広告グループ/広告セット > 広告として表示される(accountId が現アカウントと不一致なら読み込まない安全弁あり)。
297
396
  > **`file://` で開いてはならない。** `fetch('サンプルプラン.json')` がブラウザにブロックされ、**エラーも出ないまま空のプランナーが表示される**。「プランが出てこない」と言われたら真っ先にこれを疑う。
298
397
  3. **ユーザーが画面で内容を確認する。** 修正は次のいずれかで行う: 構成・文言の作り直しは **AI に再指示**(サンプルプラン JSON を上書きして再読込)、個別の追加・複製・文言/画像/パラメータの微修正は **プランナー内で直接編集**(セル選択コピペ可)。
299
398
  4. 確認完了を `AskUserQuestion` で承認してもらう。**この承認がフェーズ3へのゲートである。**
@@ -315,9 +414,74 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
315
414
  | `status: ACTIVE` | 確認前に配信・課金が始まる |
316
415
  | 日予算の桁間違い | 想定外の課金 |
317
416
  | CP名に「テスト」等が残存 | 本番アカウントに検証用の名前が残る |
417
+ | `imagePaths` のファイルが存在しない | 本実行のアップロードで初めて落ちる。lint は ERROR で拾う(`~` 展開・相対の基準は計画JSONのディレクトリ) |
418
+ | `paramCode` が特定できない | 計測パラメータ無しの広告が入稿される。パラメータ無し運用なら `urlParamsEnabled: false` を入れる(WARN 止まりになる) |
419
+ | `smartTargeting: false` | 配信が伸びない。方針は常時 ON なので lint が WARN で拾う |
420
+ | **`mediaIds` と `imagePaths` の同時指定** | 画像はアップロードされるのに広告には**旧 mediaId**が使われる(backend は `mediaIds[0]` のみ)。dry-run も成功する。lint が ERROR で拾う |
421
+
422
+ ### YDA の初回セットアップ(`アカウント/yda/<名前>.json`)
423
+
424
+ 1. アカウントを特定し、**`mccId` を控える**: 管理画面を開いてURLの `#/{ここ}/{accountId}/list/...` の第1セグメントが `mccId`(= loginAccountId)。多くの場合 `accountId` と同値だが、MCC 配下だと別値になる。**`mccId` は `adops.sh open` の唯一の供給元**(未設定だと 404 / 白画面)
425
+ 2. 参照データを取り込む:
426
+ ```bash
427
+ npx -y addashboard-cli@latest list --platform yda --resource accounts
428
+ npx -y addashboard-cli@latest list --platform yda --resource campaigns --account-id <ID>
429
+ npx -y addashboard-cli@latest list --platform yda --resource media --account-id <ID>
430
+ npx -y addashboard-cli@latest list --platform yda --resource ads --account-id <ID> --campaign-id <cpId>
431
+ npx -y addashboard-cli@latest list --platform yda --resource ads --account-id <ID> --ad-group-ids <agId1,agId2> # 広告グループで絞る
432
+ npx -y addashboard-cli@latest list --platform yda --resource resources --account-id <ID> # オーディエンス / 配置面
433
+ ```
434
+ 3. **既存広告からの取り込みは手作業でやらない**:
435
+ ```bash
436
+ skills/ad-ops/scripts/adops.sh refs-import yda <accountId> # 差分表示のみ(既定)
437
+ skills/ad-ops/scripts/adops.sh refs-import yda <accountId> --write # アカウントJSONへ書き込み
438
+ ```
439
+ 見出し・説明文を**既存の番号を再利用したまま**採番(過去の入稿計画・広告名・`creative=` に焼き込まれているため振り直さない)、CP名・広告グループの `campaignId` / `finalUrlSample` / `paramCode` の補完、`audiences` / `placements` の取り込みまで行う。
440
+ **`/yda/ads` は広告グループ名を返さない**ので、新規に足された広告グループ行は `name` が空(プランナーの「既存広告グループを呼び出し」では `AG <ID>` 表示になる)。件数はレポート行に出るので、名前が要るならアカウントJSONへ手で足す。
441
+ 4. スキーマ(v2):
442
+ ```json
443
+ {
444
+ "accountJsonVersion": 2,
445
+ "accountId": "<数値ID>",
446
+ "mccId": "<管理画面URLの #/{ここ}/>",
447
+ "name": "<アカウント名>",
448
+ "principal": "<広告主体者>",
449
+ "projectName": "<案件名>",
450
+ "baseArticleUrl": "<記事ベースURL>",
451
+ "urlParamsEnabled": true,
452
+ "adNamePolicy": "imageNo",
453
+ "refs": {
454
+ "titles": {"1": "見出し"},
455
+ "descriptions": {"1": "本文"},
456
+ "media": {"1": {"card": "<mediaId>", "sq": "<mediaId>"}},
457
+ "campaigns": {"<campaignId>": {"name": "CP名"}},
458
+ "adGroups": {"<adGroupId>": {"name": "【code】AG名", "campaignId": "<campaignId>", "paramCode": "<code>", "finalUrlSample": "https://…"}},
459
+ "groups": {"<code>": {"campaignId": "…", "adGroupId": "…", "groupName": "…"}},
460
+ "audiences": {"<実ID>": {"name": "…", "kind": "audienceList"}},
461
+ "placements": {"<実ID>": {"name": "…", "kind": "standard"}}
462
+ }
463
+ }
464
+ ```
465
+
466
+ **`accountJsonVersion` の扱い**: **v2 は追加キーのみ**(`mccId` / `urlParamsEnabled` / `adNamePolicy` / `refs.audiences` / `refs.placements` / `finalUrlSample`)。**読み手はバージョンで分岐せず `.get()` で読む**ので、**v1 のまま置かれたファイルもそのまま動く**(欠落 = 従来挙動)。
318
467
 
319
468
  **初回セットアップ**: 初めて使うアカウントは、先に「アカウント取込プロンプト」で登録画像・見出し・既存キャンペーン/広告グループを取り込み、**`アカウント/<platform>/<名前>.json`**(refs。YDA なら `アカウント/yda/<名前>.json`、Meta なら `アカウント/meta/<名前>.json`)を用意する(アカウント名は日本語で可)。**旧配置(`アカウント/` 直下)も fetch フォールバックで読める**(`platform` 未記載=yda 扱いの後方互換)。
320
469
 
470
+ **YDA は既存の勝ちクリエイティブを CLI で吸い出せる**(管理画面のコピペ / CSV エクスポートは不要):
471
+
472
+ ```bash
473
+ npx -y addashboard-cli@latest list --platform yda --resource ads \
474
+ --account-id <accountId> --campaign-id <campaignId>
475
+ ```
476
+
477
+ * 見出し・説明文・最終URL・使用メディア(mediaId)・広告主体者・CTA が広告単位で返る
478
+ * **`--ad-group-ids` か `--campaign-id` の**どちらか**が必須**。広告グループを絞るときは `--ad-group-ids 20000001,20000002`(カンマ区切り)を使う。**backend を curl で直叩きしない**(認証ヘッダを自前で組むことになる)
479
+ ```bash
480
+ npx -y addashboard-cli@latest list --platform yda --resource ads \
481
+ --account-id <accountId> --ad-group-ids 20000001,20000002
482
+ ```
483
+ * **`campaigns --campaign-id`(campaign-import)はキャンペーン + 広告グループ設定までしか返さない**。広告の文言が要るときはこちらを使う
484
+
321
485
  **【必須】アカウントJSONには `baseArticleUrl` を必ず入れる(YDA / Meta 共通)。** 記事ベースURL(例: `https://iiiyah.com/ab/`)。
322
486
 
323
487
  * 未設定だと `finalUrl` が `jv_C_1?ad=...` のような**相対パス**になり、**遷移先の壊れた広告が入稿される**
@@ -326,14 +490,27 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
326
490
 
327
491
  #### Meta の初回セットアップ(`アカウント/meta/<名前>.json`)
328
492
 
329
- 1. アカウントを特定: `webgram list --platform meta --resource accounts` → 対象の **accountId(`act_` 付き)** を確定。あわせて **FBページID / IGユーザーID(任意)/ pixelId** を確認する(この3つは CLI では取れないので Meta Business 管理画面から拾う)。
330
- 2. クリエイティブ参照を取り込む:
493
+ 1. アカウントを特定: `webgram list --platform meta --resource accounts` → 対象の **accountId(`act_` 付き)** を確定。
494
+ 2. **入稿アセットID(FBページID / pixelId / IGユーザーID)を取得する**:
495
+ ```bash
496
+ npx -y addashboard-cli@latest list --platform meta --resource pixels --account-id act_<ID> # pixelId(アカウント配下)
497
+ npx -y addashboard-cli@latest list --platform meta --resource pages # FBページID
498
+ npx -y addashboard-cli@latest list --platform meta --resource instagram-accounts --account-id act_<ID> # IGユーザーID
499
+ ```
500
+ * **`pages` は `--account-id` を取らない**。`act_<ID>/promote_pages` は 200 を返すが常に 0 件で、ページはビジネスマネージャ配下でしか引けないため、トークンから見える全ページを返す。
501
+ * **【最重要】一覧に出る ≠ そのページで入稿できる。** 各行の **`canAdvertise`**(`tasks` に `ADVERTISE` を含むか)を見て、**`true` のページだけを使う**。`false` のページを指定すると入稿の広告作成で `code 10 / subcode 3858749`「ページに投稿するには広告主の役割以上のアクセス許可が必要」で落ちる(キャンペーンと広告セットだけ作られて残る)。
502
+ 実測(2026-08-16)では 62 件中 `canAdvertise: true` は **`source` に `me` を含む 9 件だけ**で、`owned` / `client` 由来の 53 件はすべて false だった。使いたいページが false のときは、Meta Business でそのページへ広告主以上の役割を付与してもらう必要がある。
503
+ * **`instagram-accounts` の `--account-id` は任意**。指定すると広告アカウント配下(`act_<ID>/instagram_accounts`)も併せて引く。**アカウントによって「act_ 配下にだけ出る / business 配下にだけ出る」が分かれる**ので、原則は指定する。
504
+ * **ページ紐付け型の IG は現状どの経路でも引けない**(トークンに `pages_read_engagement` が無いため)。既存広告が使っている IG が一覧に出ない場合はこれ。既存キャンペーンを `campaign-import` して実際の `instagramUserId` を写すか、管理画面から拾う。
505
+ * `pages` の各行の `source` は取得経路(`me` = トークン所有ユーザーが管理 / `owned` = BM所有 / `client` = BMのクライアント)。どれを使うかは案件で決める。
506
+ * 一覧が多い場合は名前で絞り込んで対象を特定する。判断がつかない場合のみ Meta Business 管理画面で照合する。
507
+ 3. クリエイティブ参照を取り込む:
331
508
  ```bash
332
509
  npx -y addashboard-cli@latest list --platform meta --resource image-library --account-id act_<ID> # imageHash
333
510
  npx -y addashboard-cli@latest list --platform meta --resource video-library --account-id act_<ID> # videoId
334
511
  npx -y addashboard-cli@latest list --platform meta --resource campaigns --account-id act_<ID> # 既存CP/広告セット
335
512
  ```
336
- 3. 取得結果を下記スキーマに整形して `アカウント/meta/<アカウント名>.json` へ保存する(雛形は同梱の `アカウント/meta/sample_account.json`):
513
+ 4. 取得結果を下記スキーマに整形して `アカウント/meta/<アカウント名>.json` へ保存する(雛形は同梱の `アカウント/meta/sample_account.json`):
337
514
  ```json
338
515
  {
339
516
  "accountJsonVersion": 1,
@@ -353,7 +530,7 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
353
530
  }
354
531
  }
355
532
  ```
356
- 4. プランナーの「+新規追加 → 📄 ファイルから追加」または「📁 フォルダ」再接続で一覧に出る。
533
+ 5. プランナーの「+新規追加 → 📄 ファイルから追加」または「📁 フォルダ」再接続で一覧に出る。
357
534
 
358
535
  **プランナー内の「❓使い方」ボタンから、この取込プロンプト(媒体別の文言)をコピーできる**ので、AI に貼るだけでも進められる。
359
536
 
@@ -366,12 +543,15 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
366
543
  | **pixelId** | `optimizationGoal` が **`OFFSITE_CONVERSIONS` / `VALUE`** の場合は公式必須(`promoted_object`)。未入力は書き出しブロック(backend 側も 400 を返す) |
367
544
  | **customEventType(CVイベント)** | `promoted_object` の CV イベント(既定 `PURCHASE`) |
368
545
  | `bidAmount` | 入札戦略が `COST_CAP` / `LOWEST_COST_WITH_BID_CAP` のときのみ必須 |
369
- | `instagramUserId` | 任意(Instagram 配置を使う場合に指定) |
546
+ | `instagramUserId` | 任意(Instagram 配置を使う場合に指定)。`list --resource instagram-accounts --account-id act_<ID>` で取得できる(ページ紐付け型は引けないので既存CPのインポート値を使う) |
370
547
 
371
548
  ### 入稿手順(YDA):未知の画像・キャンペーン/広告グループは先に登録
372
549
 
373
550
  入稿は「**未知のアセットを先に登録 → アカウントJSONに反映 → 広告を入稿**」の順で行う。`submit-plan` 本実行がこれを自動化する:
374
551
 
552
+ 0. **ローカル画像で新規入稿する**: 広告の `ads[].imagePaths[]` に**絶対 / `~/…` / 計画JSON基準の相対**の3形式が使える。**dry-run でも存在検証される**(アップロードはしない)。重複画像は D0001 で既存 mediaId が再利用されるので二重登録にならない。解決結果は計画ファイルに書き戻され、再開時に再アップロードしない。
553
+ **プランナーを使わず少数を入稿する場合は上の「画像入稿フロー(ローカル画像・YDA)」へ。**
554
+ **【必須】同じ広告に `mediaIds`(解決済み)と `imagePaths` を同時に書かない。** CLI はアップロードした mediaId を `mediaIds` の**末尾に追記**するだけで、backend は **`mediaIds[0]` しか使わない**。両方あると「新しい画像はメディアライブラリに登録されるのに、広告は古い画像のまま」という**サイレントな取り違え**になる。既存クリエイティブを差し替えたいときは `mediaIds` を空にして `imagePaths` だけを書く(プランナーでは広告行の**画像番号を空にする**。画像番号が解決済みの行の `画像パス` は書き出し時に落とし、`画像パス無視(画像番号が解決済み)` の警告を出す)。
375
555
  1. **未知の画像を登録**: 広告の `imagePaths[]`(ローカル画像)を `/yda/upload-image` で自動アップロードして mediaId を解決。解決結果は計画ファイルに書き戻され、再開時の再アップロードを防ぐ。
376
556
  2. **未知のキャンペーン/広告グループを作成**: 計画に既存IDが無い CP/AG は backend が新規作成し、応答から campaignId を回収(進捗に書き戻し)。
377
557
  3. **アカウントJSONへ反映**: 解決した mediaId・新規作成した CP/AG のID(`【paramCode】↔ID`)を `アカウント/<媒体>/<名前>.json` の `refs`(media / campaigns / adGroups / groups)へ反映し、次回以降は再利用する(未解決を避ける)。
@@ -379,7 +559,8 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
379
559
 
380
560
  ### 入稿手順(Meta)
381
561
 
382
- 1. **プランナーで計画**: ヘッダーの統合プルダウンで **`<案件名> Meta`** を選ぶ(`アカウント/meta/<名前>.json` 未整備なら先に上記セットアップ)。キャンペーン > 広告セット > 広告を作り、共通設定チップで FBページID / pixelId / CVイベント / 最適化 / 課金 / 入札戦略 / 配信開始日 / 配信終了日(任意・空欄なら無期限)を確定する。
562
+ 1. **プランナーで計画**: ヘッダーの統合プルダウンで **`<案件名> Meta`** を選ぶ(`アカウント/meta/<名前>.json` 未整備なら先に上記セットアップ)。キャンペーン > 広告セット > 広告を作り、共通設定チップで FBページID / pixelId / CVイベント / 最適化 / 課金 / 入札戦略 / 配信開始日 / 配信終了日(任意・空欄なら無期限)を確定する。**配信日時は広告セット行の列でも個別に上書きできる**(優先順位: 広告セット行 > 案件設定チップ > 既定=当日)。書式は `YYYY-MM-DD` または `YYYY-MM-DD HH:mm[:ss]`(**JST**)で、時刻を省くと開始は `00:00:00` / 終了は `23:59:59` になる。
563
+ - **既知の制約**: 解決は「行が空ならチップを継承」なので、**チップに終了日が入っているとき、特定の広告セットだけを無期限にすることはできない**。混在させたい場合はチップの終了日を空にし、期限を付けたい広告セット行だけに終了日時を入れる。
383
564
  2. **入稿JSON書き出し**: ワンクリックで `<案件名>_Meta入稿計画_<日時>.json`(`planVersion:1`、`platform:"meta"`)を出力。`act_` 形式違反・FBページID 未入力・(`OFFSITE_CONVERSIONS`/`VALUE` 時の)pixelId 未入力・0件 は**書き出しをブロック**する。
384
565
  3. **dry-run で一括検証**:
385
566
  ```bash
@@ -403,7 +584,7 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
403
584
  - **入稿JSON書き出し**: 設定ダイアログなしの**ワンクリック**。参照未解決の広告は自動除外、accountId 未入力・0件なら書き出し中止(空入稿防止)。媒体別の中身:
404
585
  - **YDA(見出し・本文の空欄許容)**: **タイトル番号 / 説明文番号は空欄でよい**(見出し・本文を使わない広告のケース)。空欄の広告はエラーにならず、`headlines` / `descriptions` は**空配列**で書き出され、backend も空を受理する。**空を許容するのはこの2フィールドのみ**(画像番号 `imageNo`・`paramCode`・principal・finalUrl は従来どおり必須)。**番号を入れたのに参照表(refs.titles / refs.descriptions)に無い場合は従来どおり「未解決」エラー**で、その広告は書き出しから除外される(別の障害なので緩めない)。Meta は従来どおり見出し・本文とも必須。
405
586
  - **YDA**: アカウントID・目的(goal)・配信開始日は案件設定チップ、入札はキャンペーン行(tCPA→`MAXIMIZE_CONVERSIONS`+targetCpa)、ターゲティングは広告グループ行の列(日本語ラベル→API enum 自動変換)から `*_入稿計画_*.json`(planVersion:1、広告は IMAGE 形式: mediaIds/headlines/descriptions/principal)を生成。手入稿バナーも自動除外。
406
- - **Meta**: 予算は広告セット行(CBO は使わない)、目的は `objective`、最適化/課金/入札戦略/pixel/CVイベント/FBページID は案件設定チップ、ターゲティング(年齢・性別・デバイス・配置)は広告セット行の列から `*_Meta入稿計画_*.json`(planVersion:1、`platform:"meta"`、`campaigns[].adSets[]`、広告は IMAGE / VIDEO)を生成。`act_` 形式違反・FBページID 未入力・pixelId 必須ケースの未入力でブロック。 **配信終了日は空欄なら `endTime` キー自体を送らない(無期限配信)。`lifetimeBudget` 指定時に限り backend が配信開始日+30日を補完する。**
587
+ - **Meta**: 予算は広告セット行(CBO は使わない)、目的は `objective`、最適化/課金/入札戦略/pixel/CVイベント/FBページID は案件設定チップ、ターゲティング(年齢・性別・デバイス・配置)は広告セット行の列から `*_Meta入稿計画_*.json`(planVersion:1、`platform:"meta"`、`campaigns[].adSets[]`、広告は IMAGE / VIDEO)を生成。`act_` 形式違反・FBページID 未入力・pixelId 必須ケースの未入力でブロック。 **配信日時(`startTime` / `endTime`)は広告セットごとに解決される(広告セット行 > 案件設定チップ > 既定=当日)。入力は `YYYY-MM-DD [HH:mm[:ss]]`・JST 前提で、書き出し時に `+0900` 付き ISO8601 に正規化される(時刻を明示した場合は 23:59:59 に丸めずその時刻を尊重)。`startTime` は常に送り、配信終了日が空欄なら `endTime` キー自体を送らない(無期限配信)。`lifetimeBudget` 指定時に限り backend が配信開始日+30日を補完する。**
407
588
 
408
589
  ### 量産構造(媒体要件の核)
409
590
 
@@ -419,8 +600,9 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
419
600
 
420
601
  ### 発火時の案内
421
602
 
603
+ - 「**ローカル画像で入稿**」「**この画像で入稿して**」「画像パスを渡された(ドラッグ&ドロップされた)」ときは、**入口メニューの『ローカル画像で入稿する』へ分岐**し、「画像入稿フロー(ローカル画像・YDA)」を Step 0 から進める。プランナーは開かない。
422
604
  - 「入稿プランナー」「YDA入稿プランナー」「入稿シート」「タイトル/画像一覧」「まとめ入稿の確認用シート」等を求められたら、**`adops.sh planner` で開く**(`open <path>` は使わない。`file://` だとプランが読み込まれず空の画面になる)。**媒体が明示されていなければどちらの媒体か確認**し、開いたあとヘッダーの統合プルダウン(案件 × 媒体)で切替えるよう伝える。
423
- - 「**Meta入稿プランナー**」「Meta のまとめ入稿」等と言われたら、同じ `ad-planner.html` を `adops.sh planner` で開いて **統合プルダウンで `<案件名> Meta` に切替**するよう案内する。アカウント参照データ(`アカウント/meta/<名前>.json`)が無ければ**先に初回セットアップ**(`list --platform meta --resource image-library|video-library|campaigns` で取り込み)へ誘導する。**FBページID / pixelId / CVイベント**が未確定なら、書き出しがブロックされる旨を先に伝えて確認する。
605
+ - 「**Meta入稿プランナー**」「Meta のまとめ入稿」等と言われたら、同じ `ad-planner.html` を `adops.sh planner` で開いて **統合プルダウンで `<案件名> Meta` に切替**するよう案内する。アカウント参照データ(`アカウント/meta/<名前>.json`)が無ければ**先に初回セットアップ**(`list --platform meta --resource pixels|pages|instagram-accounts|image-library|video-library|campaigns` で取り込み)へ誘導する。**FBページID / pixelId / CVイベント**が未確定なら、`list --resource pages|pixels` で候補を出して確定させる(IG は `--resource instagram-accounts --account-id act_<ID>`)(書き出しがブロックされる旨も先に伝える)。
424
606
  - 入稿計画JSONは書き出し後 `webgram submit-plan --plan-file <入稿計画.json>` で **dry-run一括検証 → `--no-dry-run --yes` 本実行** にかける(1CPずつ・進捗書き戻しで途中失敗後も再開可、`submitted` 済みはスキップ)。`plan.platform` で YDA / Meta が自動判別される(未記載は yda 扱い)。
425
607
  - **Meta は本番PoC 未実施**なので、実入稿を頼まれたら「配信オフ(PAUSED)・1キャンペーン・最小予算から」を必ず提案してから進める。
426
608
 
@@ -438,6 +620,11 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
438
620
  | **プランナーを開いてもプランが空** | `file://` で開いている。`fetch('サンプルプラン.json')` がブロックされエラーも出ない。**`adops.sh planner` で開き直す** |
439
621
  | **本実行で `401 Account not found` (code 0112)** | その accountId が接続中の認証情報のスコープ外。アカウントJSONの有無は無関係。**`adops.sh preflight <媒体> <accountId>` で事前に確認する** |
440
622
  | **広告のリンクが相対パスになる** | アカウントJSONの `baseArticleUrl` 未設定。**dry-run は通ってしまう**ので `adops.sh plan` の lint で見る |
623
+ | **管理画面が 404 / 白画面** | アカウントJSONに `mccId` が無く `accountId` で代替されている。管理画面URLの `#/{ここ}/` の値を `アカウント/yda/<名前>.json` の `"mccId"` に追記する |
624
+ | **`imagePaths` で ENOENT** | 相対パスの基準は**計画JSONのあるディレクトリ**(カレントではない)。`~/…` は展開される。絶対パスで書くのが確実 |
625
+ | **画像を差し替えたのに古い画像のまま入稿された** | `mediaIds`(画像番号)と `imagePaths` を両方書いている。**画像番号を空にして `imagePaths` だけにする**(プランナーは書き出し時に落として `画像パス無視(画像番号が解決済み)` を警告する) |
626
+ | **管理画面で広告セット一覧が開かない (Meta)** | `adops.sh open meta <act_id> adsets`。中間層の語は媒体で違う(YDA=`adgroups`)。**URLを手で組み立てない**(`adops.sh open` が変換する) |
627
+ | **lint で「paramCode が特定できません」** | パラメータ無し運用ならアカウントJSONに `"urlParamsEnabled": false` を入れる(ERROR → WARN になる)。使う運用なら広告グループ名に `【コード】` を入れる |
441
628
  | `command not found: npx` | Node.js が入っていない。`https://nodejs.org` から LTS 版インストールを案内 |
442
629
  | `Login failed: invalid_grant` | Web UI (`https://macchiato.site`) でログインできるか確認を案内 |
443
630
  | `Login failed: network_error` | `curl -v https://macchiato.site/api/health` で疎通確認 |
@@ -453,8 +640,8 @@ npx -y addashboard-cli@latest review --team 松井T --week 2026-07-13
453
640
  ### 入稿プランナー関連ロードマップ(2026-07-16 定例 / 2026-07-23・2026-07-30 更新)
454
641
 
455
642
  - ~~CSVを介さない直接入稿~~ → **完了(2026-07-23)**: プランナーの「入稿JSON書き出し」が入稿計画JSON(planVersion:1)を生成し、`submit-plan` が dry-run一括検証→1CPずつ入稿(`/yda/upload-image` で新規画像の mediaId 解決・進捗書き戻し・再開可)。backend は `createImageAd`(RESPONSIVE_AD+IMAGE)対応。CSV書き出しは廃止。
456
- - **キャンペーン/広告グループID の自動取得**: 管理画面からの手コピペ(`【paramCode】`↔ID の突合)を、API/MCP で自動取得して置き換える。新規CPは払出し後にID解決。
457
- - **新規画像のメディア登録自動化**: ドライブ格納画像を YDA メディアに登録し、プランナーの参照データ(画像番号→mediaID)へ反映。
643
+ - ~~キャンペーン/広告グループID の自動取得~~ → **完了**: `list --resource campaigns|ads|resources` と `adops.sh refs-import yda <accountId> --write` で、CP ID/名前・AG ID・`campaignId`・`paramCode`・`finalUrlSample`・見出し・説明文・オーディエンス・配置面をアカウントJSONへ自動マージ(既存番号は再利用し振り直さない)。**広告グループ名だけは `/yda/ads` が返さないため未取得**(新規行は `AG <ID>` 表示)。新規CPは `submit-plan` 本実行の払出し後にID解決。
644
+ - ~~新規画像のメディア登録自動化~~ → **完了**: 広告の `imagePaths[]`(絶対 / `~/…` / 計画JSON基準の相対)を `submit-plan` 本実行が `/yda/upload-image` へ自動アップロードして mediaId を解決し、計画ファイルへ書き戻す。プランナー側は広告行の `画像パス` 列が担体。
458
645
  - **命名規則の統一**: `【】内の数字`のみ共通で、キャンペーン名/広告名は担当者差がある → システム命名に寄せられるようにする。
459
646
  - ~~**Meta広告対応**(GUI未対応)~~ → **プランナーGUI 対応完了(2026-07-30)**: `PLATFORMS` 媒体スキーマ駆動化により、統合プルダウンで Meta の案件を選ぶと専用の列・enum・命名規則・検証・入稿ボディ変換に切り替わる。backend は Meta Marketing API 公式Docs 照合で 12 ギャップを修正(APIバージョン集約 / zodスキーマ一本化と 400 応答 / `instagram_user_id` / `promoted_object` / JPY の currency offset / `bid_amount` 必須条件 / 動画サムネ hash / 特別広告カテゴリ / JST ISO8601 / `success` 判定 など)。CLI は `submit-plan` の meta 対応と `list --resource image-library|video-library` を追加。
460
647
  - **Meta の残タスク(未対応)**: 本番アカウントへの入稿 PoC(未実施)、カルーセル/コレクション等の複数素材フォーマット、カスタムオーディエンス/類似オーディエンスの ID 解決、地域ターゲティング細分化(現状は国単位)、既存キャンペーンの複製テンプレート運用の GUI 化。