addashboard-cli 0.7.0 → 0.9.0

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.
Files changed (22) hide show
  1. package/dist/commands/ads.js +97 -7
  2. package/dist/commands/ads.js.map +1 -1
  3. package/dist/commands/submission.js +232 -16
  4. package/dist/commands/submission.js.map +1 -1
  5. package/dist/index.js +8 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/schemas/submit-plan.js +80 -5
  8. package/dist/schemas/submit-plan.js.map +1 -1
  9. package/package.json +1 -1
  10. package/skills/ad-ops/SKILL.md +188 -14
  11. package/skills/ad-ops/ad-planner.html +1665 -304
  12. package/skills/ad-ops/scripts/adops.sh +55 -6
  13. package/skills/ad-ops/scripts/plan_lint.py +164 -24
  14. package/skills/ad-ops/scripts/refs_import.py +1 -1
  15. package/skills/ad-ops//343/202/242/343/202/253/343/202/246/343/203/263/343/203/210/bytedance/index.json +5 -0
  16. package/skills/ad-ops//343/202/242/343/202/253/343/202/246/343/203/263/343/203/210/bytedance/sample_account.json +55 -0
  17. package/skills/ad-ops//343/202/242/343/202/253/343/202/246/343/203/263/343/203/210/google/index.json +5 -0
  18. package/skills/ad-ops//343/202/242/343/202/253/343/202/246/343/203/263/343/203/210/google/sample_account.json +40 -0
  19. package/skills/ad-ops//343/202/242/343/202/253/343/202/246/343/203/263/343/203/210/yda/sample_account.json +2 -2
  20. package/skills/ad-ops//343/202/265/343/203/263/343/203/227/343/203/253/343/203/227/343/203/251/343/203/263.json +1 -1
  21. package/skills/ad-ops//343/202/265/343/203/263/343/203/227/343/203/253/343/203/227/343/203/251/343/203/263_bytedance.json +30 -0
  22. package/skills/ad-ops//343/202/265/343/203/263/343/203/227/343/203/253/343/203/227/343/203/251/343/203/263_google.json +33 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ad-ops
3
- description: ad-dashboard (https://macchiato.site) の webgram CLI 経由で広告を YDA / Meta に半自動入稿する (TikTok は将来対応予定)。発火したら「入稿先アカウント&媒体」→「今回の方式 (HTMLプランナーで手動指定=既定 / 前回の入稿計画を参考にする / チャットで1つずつ聞く)」の順に確定させる。入稿の実体は 2 系統 — 動画・ローカル画像の API 入稿フロー (固定デフォルト + URL 空き番号自動割当 + 一覧 OK 確認、現状 YDA) と、入稿プランナー `ad-planner.html` (YDA / Meta を案件×媒体の統合プルダウンで切替する GUI → 入稿計画JSON → `submit-plan` で dry-run → 本実行)。「広告運用」「広告入稿」「動画入稿」「まとめ入稿」「ASC 入稿」「YDA 入稿」「Meta 入稿」「入稿プランナー」「YDA入稿プランナー」「Meta入稿プランナー」「入稿シート」「TikTok 入稿」「webgram」「ad-dashboard」と言われたら使用。Node.js が入っていれば追加インストール不要 (`npx` 経由)。
3
+ description: ad-dashboard (https://macchiato.site) の webgram CLI 経由で広告を YDA / Meta / Google (Demand Gen) / TikTok (ByteDance) に半自動入稿する。発火したら「入稿先アカウント&媒体」→「今回の方式 (HTMLプランナーで手動指定=既定 / 前回の入稿計画を参考にする / チャットで1つずつ聞く)」の順に確定させる。入稿の実体は 2 系統 — 動画・ローカル画像の API 入稿フロー (固定デフォルト + URL 空き番号自動割当 + 一覧 OK 確認、現状 YDA) と、入稿プランナー `ad-planner.html` (YDA / Meta / Google / TikTok を案件×媒体の統合プルダウンで切替する GUI → 入稿計画JSON → `submit-plan` で dry-run → 本実行)。「広告運用」「広告入稿」「動画入稿」「まとめ入稿」「ASC 入稿」「YDA 入稿」「Meta 入稿」「Google 入稿」「YouTube 入稿」「Demand Gen 入稿」「入稿プランナー」「YDA入稿プランナー」「Meta入稿プランナー」「Google入稿プランナー」「TikTok入稿プランナー」「入稿シート」「TikTok 入稿」「webgram」「ad-dashboard」と言われたら使用。Node.js が入っていれば追加インストール不要 (`npx` 経由)。
4
4
  ---
5
5
 
6
6
  # ad-ops skill (広告運用スキル)
@@ -8,8 +8,9 @@ description: ad-dashboard (https://macchiato.site) の webgram CLI 経由で広
8
8
  Google Drive から手動 DL 済みの素材を各媒体に半自動入稿するためのスキル。
9
9
 
10
10
  - **動画の API 入稿フロー(`submit`)**: 現状 **YDA のみ**。
11
- - **入稿プランナー(`ad-planner.html` → 入稿計画JSON → `submit-plan`)**: **YDA / Meta 対応**(ヘッダーの「案件 × 媒体」統合プルダウンで切替)。
12
- - **TikTok / ByteDance**: プランナー・入稿フローともに未対応(汎用 JSON 入稿 `submit --json-file` のみ)。
11
+ - **入稿プランナー(`ad-planner.html` → 入稿計画JSON → `submit-plan`)**: **YDA / Meta / Google / TikTok 対応**(ヘッダーの「案件 × 媒体」統合プルダウンで切替)。
12
+ - **Google (Demand Gen)**: プランナー・dry-run・本実行に対応。**2026-08-23 に実 API での入稿を確認済み**(PAUSED・1キャンペーン)。ただし配信実績はまだ無いので、初回は PAUSED・最小予算から始めて管理画面で目視確認する。詳細は下の「Google (Demand Gen) の対応範囲」を参照。
13
+ - **TikTok / ByteDance**: プランナー・dry-run・本実行に対応(**単一動画のみ**)。**2026-08-23 に実 API を初めて叩き、キャンペーン作成と自動ロールバックまで確認**。広告グループ以降は地域IDの取得手段が無くて未達だったため `regions` を追加した。**配信オン (ENABLE) は backend が拒否する**。詳細は下の「TikTok (単一動画) の対応範囲」を参照。
13
14
 
14
15
  配置・発火方法・ログイン手順は [cli/README.md](../../README.md) の「初期設定: Skill として配置する」章を参照。
15
16
 
@@ -51,7 +52,7 @@ skills/ad-ops/scripts/adops.sh preflight yda <accountId>
51
52
  * **アカウントJSON(`アカウント/<媒体>/<名前>.json`)が存在することは、入稿できることを意味しない。**
52
53
  参照データは過去に取り込んだものが残るだけで、現在の API 権限とは無関係
53
54
 
54
- > 実例: 2026-08-06 リョウシンJV(`1002811292`)。アカウントJSONは揃っていて dry-run も
55
+ > 実例: 2026-08-06 とある案件のアカウント。アカウントJSONは揃っていて dry-run も
55
56
  > 全件パスしたが、`list accounts` が返す 17 件に含まれておらず本実行で 401。
56
57
  > フェーズ1〜3 の作業がすべて無駄になった。
57
58
 
@@ -221,7 +222,7 @@ skills/ad-ops/scripts/adops.sh open meta <accountId> campaigns
221
222
 
222
223
  * `resource` は `campaigns` / `adgroups` / `ads`。**中間層は媒体で語が違う**(YDA=`adgroups` / Meta=`adsets`)が、`adops.sh open` がどちらの表記でも受けて媒体別の正しいURLに変換する(**URLを手で組み立てるとここを間違える**)。複数入稿した場合も一覧を 1 つ開けば十分
223
224
 
224
- * TikTok は将来対応時に `adops.sh open` へ追加する
225
+ * TikTok は `adops.sh open bytedance <advertiserId>` で広告管理画面を開く。**TikTok はキャンペーン / 広告グループ / 広告を URL で指定できない**ため、resource を渡しても同じ画面が開く(画面上のタブで切り替える)
225
226
 
226
227
  ## 画像入稿フロー(ローカル画像・YDA)
227
228
 
@@ -290,13 +291,173 @@ skills/ad-ops/scripts/adops.sh open yda <accountId> campaigns
290
291
 
291
292
  ## 媒体別の注意
292
293
 
293
- **上記の動画 API 入稿フロー (`submit --video`) の対応は YDA のみ。** Meta は **入稿プランナー経由 (`submit-plan`)** で画像/動画とも入稿できる。TikTok を指定された場合は「未対応」と明示してから相談する。
294
+ **上記の動画 API 入稿フロー (`submit --video`) の対応は YDA のみ。** Meta / Google / TikTok は **入稿プランナー経由 (`submit-plan`)** で入稿する。
294
295
 
295
296
  | 媒体 | 動画 API 入稿フロー | 入稿プランナー GUI | 入稿リンクの粒度 | 備考 |
296
297
  | ---------------------- | ------------ | ------------ | ---------------------- | ---------------------------------------------- |
297
298
  | **YDA** | ✅ 対応済み | ✅ 対応済み | 広告ごと | まず YDA から対応 (社内優先順位、名倉さん依頼) |
298
299
  | **Meta** | ⏳ 未対応 | ✅ 対応済み (画像/動画) | 広告ごと (まとめ入稿でも広告単位で変わる) | ASC でも広告ごとに個別リンクを設定。**実 API への本入稿 PoC は未実施** |
299
- | **TikTok / ByteDance** | ⏳ 将来対応予定 | ⏳ 未対応 | 広告グループ単位で 1 本 | まとめ入稿は 10 本でも 20 本でも入稿リンクは 1 つ (クリエイティブグループ単位) |
300
+ | **Google (Demand Gen)** | ⏳ 未対応 | ✅ 対応済み (画像/動画) | 広告ごと | **実 API での入稿を確認済み**(2026-08-23・PAUSED)。動画は YouTube 動画IDを人が用意する |
301
+ | **TikTok / ByteDance** | ⏳ 未対応 | ✅ 対応済み (単一動画) | 広告ごと | **実 API での入稿検証は未了**。**配信オン (ENABLE) は backend が拒否**。動画とカバー画像はアップロード済みIDを使う |
302
+
303
+ ***
304
+
305
+ ## Google (Demand Gen) の対応範囲
306
+
307
+ **Google 広告の入稿を頼まれたら、まずこの節を読んでから動く。**
308
+
309
+ ### 何ができて、何ができないか
310
+
311
+ | | 状態 |
312
+ |---|---|
313
+ | プランナーで計画を組む | ✅ できる(統合プルダウンで「Google」を選ぶ) |
314
+ | dry-run で不備を潰す | ✅ できる |
315
+ | **本実行(実際の入稿)** | ✅ **できる**(2026-08-23 に実 API で確認済み)。ただし**配信オン (ENABLED) では入稿できない** — backend が 400 で拒否し、lint も ERROR で止める。**PAUSED で入稿し、管理画面で確認してから手で配信をオンにする**運用。広告が1件も作れなかった CP は自動削除される |
316
+ | 既存キャンペーン・広告グループへの広告追加 | ❌ 未対応。毎回あたらしいキャンペーンを作る形になる |
317
+ | 動画ファイルのアップロード | ❌ 未対応。**Google Ads API には窓口があるが(`YouTubeVideoUploadService`)、使っている Node ライブラリ(Opteo `google-ads-api`)が非対応**。運用者が YouTube へ手で上げ、動画IDを渡す |
318
+ | 参照データの自動取込(`refs-import`) | ❌ 未対応(yda のみ)。アカウントJSONを手で用意する |
319
+ | 管理画面を開く | ✅ `adops.sh open google <customerId> [campaigns\|adgroups\|ads]`。アカウントJSONの `consoleMcc` を使う |
320
+ | 入稿後に状態を確認する | ✅ `webgram list --platform google --resource ads --account-id <id> [--campaign-id <cpId>]`。**キャンペーン / 広告グループ / 広告の status を名前で返す**(PAUSED で入ったかを管理画面を開かずに確認できる) |
321
+ | 画像のローカルパス入稿 | ❌ 未対応。**Google Ads に登録済み IMAGE アセットの `resource_name` を事前に用意する**(Demand Gen 画像広告は CLI のアップロード対象外) |
322
+ | 地域の指定漏れ | ✅ 安全弁あり。**未指定なら日本 (2392) を既定で入れる**(未指定は全世界配信になるため。Meta の JP 既定と同じ) |
323
+
324
+ ### キャンペーン型が Demand Gen 固定な理由
325
+
326
+ **Google Ads API では動画(VIDEO)キャンペーンを新規作成できない**(公式明記)。API から YouTube 面へ広告を出す経路は Demand Gen だけ。Demand Gen は YouTube / Discover / Gmail / ディスプレイに配信でき、画像広告と動画広告を同じキャンペーンで扱える。
327
+
328
+ ### 事前に用意してもらうもの
329
+
330
+ 戦略壁打ち(フェーズ1)で必ず確認する:
331
+
332
+ 1. **YouTube 動画ID** — 運用者が事前に YouTube へアップロードしておく(動画広告の場合)
333
+ 2. **ブランド名** — 広告に表示される広告主名(表示幅25まで)。**Demand Gen では必須**
334
+ 3. **ロゴ画像アセット** — Google Ads に登録済み IMAGE アセットの resource_name。**画像広告では必須**(1:1・128x128以上)
335
+ 4. **地域** — **指定しないと全世界配信になる**。通常は「日本」
336
+
337
+ ### YDA / Meta との構造の違い
338
+
339
+ | | Google |
340
+ |---|---|
341
+ | 予算の階層 | **キャンペーン**(YDA と同じ。Meta は広告セット) |
342
+ | 入札 | 目標CPA を入れると tCPA 入札 / 空欄ならコンバージョン数の最大化 |
343
+ | 地域・言語の階層 | **広告グループ**(Demand Gen は広告グループ層に持つ) |
344
+ | 動画広告の必須項目 | 見出し / **長見出し** / 説明文 / ブランド名。**長見出しは動画広告だけが持つ** |
345
+ | 画像広告の必須項目 | 横長 or 正方形画像 / **ロゴ 1-5枚** / 見出し / 説明文 / ブランド名 |
346
+ | accountId | 10桁数値(ハイフン無し)。`act_` は付けない |
347
+
348
+ ### 開発中の CLI で dry-run を試す場合
349
+
350
+ npm 公開版(`@latest`)にはまだ Google 対応が入っていないため、手元のビルドを使う:
351
+
352
+ ```bash
353
+ cd <repo>/cli && npm run build
354
+ WEBGRAM_CLI="node $PWD/dist/index.js" skills/ad-ops/scripts/adops.sh plan <入稿計画.json>
355
+ ```
356
+
357
+ `adops.sh` の各コマンドは `WEBGRAM_CLI` で CLI を差し替えられる(未設定なら `npx -y addashboard-cli@latest`)。
358
+
359
+ ## TikTok (単一動画) の対応範囲
360
+
361
+ **TikTok 広告の入稿を頼まれたら、まずこの節を読んでから動く。**
362
+
363
+ ### 何ができて、何ができないか
364
+
365
+ | | 状態 |
366
+ |---|---|
367
+ | プランナーで計画を組む | ✅ できる(統合プルダウンで「TikTok」を選ぶ) |
368
+ | dry-run で不備を潰す | ✅ できる |
369
+ | **本実行(実際の入稿)** | ⚠️ **できるが実 API で未検証**。**配信オン (ENABLE) は backend が 400 で拒否する**(検証が済むまで)。DISABLE で 1キャンペーン・最小予算から流し、管理画面で目視確認する。広告が1件も作れなかった CP は自動削除される(削除できなければ停止に切り替える) |
370
+ | 単一動画広告 (`SINGLE_VIDEO`) | ✅ 対応 |
371
+ | 画像広告 / カルーセル / Spark Ads | ❌ 未対応 |
372
+ | CV最適化(`WEB_CONVERSIONS` + pixel) | ❌ 未対応。目的は `TRAFFIC`(記事LP誘導)固定 |
373
+ | **動画・カバー画像のローカルアップロード** | ✅ **できる**。広告行の「動画パス」「カバー画像パス」に入れると、本実行の直前に CLI が自動アップロードして ID に解決する(dry-run では上げない)。参照データに登録済みなら番号だけでよい |
374
+ | **入稿後の確認** | ✅ `webgram list --platform bytedance --resource ads --account-id <id> [--campaign-id <id>]`。`operationStatus`(指定したオン/オフ)と `secondaryStatus`(審査・配信の実状態)の**両方**が返る |
375
+ | 既存キャンペーン・広告グループへの広告追加 | ❌ 未対応。毎回あたらしいキャンペーンを作る形になる |
376
+ | 参照データの自動取込(`refs-import`) | ❌ 未対応。アカウントJSONを手で用意する |
377
+ | 管理画面を開く | ✅ `adops.sh open bytedance <advertiserId>`。**キャンペーン / 広告グループ / 広告のURL指定はできない**ので、開いた画面のタブで切り替える |
378
+ | 配信期間 / フリークエンシー | ❌ 未対応(開始時刻は未指定なら 1 時間後になる) |
379
+
380
+ ### 事前に用意してもらうもの
381
+
382
+ 戦略壁打ち(フェーズ1)で必ず確認する:
383
+
384
+ 1. **identity ID と BC ID** — 広告主として表示される TikTok アカウント。**これが無いと広告が作れない**(Meta の FBページID 相当)
385
+ ```bash
386
+ webgram list --platform bytedance --resource identities --account-id <advertiserId>
387
+ ```
388
+ **本番実測では `BC_AUTH_TT`(Business Center 経由で認可された TikTok アカウント)がほぼ全て**(4アカウントで各14件。`CUSTOMIZED_USER` は 0〜2件)。`BC_AUTH_TT` は **`identityAuthorizedBcId` が必須**なので、`identities` が返す `authorizedBcId` もアカウントJSONに入れる。ID は UUID 形式で数値ではない
389
+
390
+ 2. **地域ID(location_id)** — **TikTok 独自の採番で公開一覧が無い**。決め打ちの値は使えない(`1210023` を送ったら `code=40002 At least 1 location ID is invalid` になった)
391
+ ```bash
392
+ webgram list --platform bytedance --resource regions --account-id <advertiserId>
393
+ # 0 件のときは経路を切り替える / 生の応答を見る
394
+ webgram list --platform bytedance --resource regions --account-id <id> --mode search
395
+ webgram list --platform bytedance --resource regions --account-id <id> --raw
396
+ # 既存の配信中広告グループから逆引きする(最も確実)
397
+ webgram list --platform bytedance --resource adgroups --account-id <id>
398
+ ```
399
+ 取れた値をアカウントJSONの `refs.regions`(`{"日本": "<location_id>"}`)に入れる
400
+ 2. **動画とカバー画像** — 2 通りある。**`SINGLE_VIDEO` はカバー画像が必須**で、動画だけでは広告を作れない
401
+ - **登録済みを使う**: アセットライブラリの ID を参照データに入れる
402
+ ```bash
403
+ webgram list --platform bytedance --resource resources --account-id <advertiserId>
404
+ ```
405
+ - **ローカルファイルを上げる**: 広告行の「動画パス」「カバー画像パス」に入れる(本実行時に自動アップロード)
406
+ 3. **動画とカバー画像** — 前述のとおり登録済みIDでもローカルファイルでもよい
407
+ 4. **日予算** — 広告グループ階層。上限 1,000,000 円で backend が弾く(桁ミス防止)。**`BUDGET_MODE_DAY` で拒否されたら `BUDGET_MODE_DYNAMIC_DAILY_BUDGET` を試す**(TRAFFIC では後者を要求されることがある)
408
+
409
+ ### 他媒体との構造の違い
410
+
411
+ | | TikTok |
412
+ |---|---|
413
+ | 予算の階層 | **広告グループ**(Meta と同じ。YDA / Google はキャンペーン) |
414
+ | 配信オンの値 | **`ENABLE`**(YDA / Meta は `ACTIVE`、Google は `ENABLED`)。配信オフは `DISABLE` |
415
+ | 状態のキー名 | **`operationStatus`**(他媒体は `status`) |
416
+ | 広告文 | **1 本だけ**(`ad_text`・100字まで)。見出し / 説明文の 2 段構えを持たない |
417
+ | 素材モード | `creative_material_mode` は**広告グループ**のフィールド(既定 `CUSTOM`)。広告側に置いても無視される |
418
+ | accountId | `advertiser_id`(数値)。`act_` は付けない |
419
+ | **配信スケジュールの時刻** | **UTC+0**(YDA / Meta は JST)。`schedule_start_time` は `"YYYY-MM-DD HH:mm:ss"` で **UTC** で書く。JST で書くと 9 時間ずれる |
420
+ | identity | **`BC_AUTH_TT` が主流**。`identityAuthorizedBcId` が必須。ID は UUID 形式 |
421
+ | 地域 | **参照データ(`refs.regions`)から引く**。固定の enum を持たない(公開一覧が無いため) |
422
+ | 命名規則 | `{番号}v-{広告文番号}-{paramCode}`(説明文が無いので L 区間が無い) |
423
+ | 最終リンク先URL | `{記事URL}?ad={paramCode}`(Meta / Google と同じ形) |
424
+
425
+ ### 失敗したときに何が残るか
426
+
427
+ TikTok の削除は `/campaign/status/update/` の `operation_status=DELETE`。**拒否されると停止(DISABLE)にフォールバックする**ので、3 状態を区別する。
428
+
429
+ | 状態 | 意味 | 運用者がすること |
430
+ |---|---|---|
431
+ | `deleted` | CP は消えた | なし(Slack に「自動削除済み」と出る) |
432
+ | `disabled` | **CP は停止して残っている** | **手動で削除する**(Slack の warning とCLIのログに campaignId が出る) |
433
+ | `failed` | 削除も停止もできなかった | **至急確認**。配信可能な状態で残っている可能性がある |
434
+
435
+ 広告が 1 件でも作れていれば削除しない。**広告グループの作成で失敗した場合も削除対象**(広告に到達していないので結果の広告は 0 件になるが、「広告なし計画」ではない)。
436
+
437
+ ### 実 API で確認できたこと / まだ届いていないこと(2026-08-23)
438
+
439
+ 本番アカウントで初めて叩いた結果。
440
+
441
+ | 項目 | 結果 |
442
+ |---|---|
443
+ | 認証・書き込み権限 | ✅ **キャンペーンの作成に成功** |
444
+ | **自動ロールバック** | ✅ **実地で動作**。広告グループ作成が失敗 → CP を自動削除。孤児ゼロ |
445
+ | エラーの可視化 | ✅ `code=40002` と `request_id` が CLI まで届いた |
446
+ | identity 取得 | ✅ 動作。**`BC_AUTH_TT` が主流**と判明 |
447
+ | 入稿後の読み返し(`list --resource ads`) | ✅ 動作。ただし `fields` 未指定で `landing_page_url` / `ad_text` / `identity_id` が空だったので明示するよう直した |
448
+ | lint | ✅ ERROR 2件を事前に検出(`urlParamsEnabled: false` の宣言で解消) |
449
+ | 地域ID | ❌ **決め打ちの `1210023` は無効**。`regions` / `adgroups` で引く形に直した |
450
+ | 広告グループ以降の作成 | ⏳ **未達**(地域IDで落ちたため)。地域を取り直して再テストする |
451
+
452
+ ### 実 API 検証で確かめること
453
+
454
+ 初回入稿の前に、この節を読んで手順を確認する。
455
+
456
+ - identity が広告アカウント配下で取れるか(Business Center 配下にしか出ないアカウントがあるかもしれない)
457
+ - 動画アップロード直後に広告へ使えるか(処理待ちが必要か)
458
+ - `/campaign/status/update/` の `operation_status=DELETE` でロールバックが通るか
459
+ - 地域の `location_id` の実値(日本のIDが `1210023` で正しいか)
460
+ - 最低予算(通貨ごとに違う。20 以上という記述があるが JPY での実値は未確認)
300
461
 
301
462
  ***
302
463
 
@@ -312,7 +473,9 @@ skills/ad-ops/scripts/adops.sh open yda <accountId> campaigns
312
473
  | アカウント一覧 | `npx -y addashboard-cli@latest list --platform <yda\|meta\|google\|smartnews\|bytedance> --resource accounts` |
313
474
  | キャンペーン一覧 | `npx -y addashboard-cli@latest list --platform <媒体> --resource campaigns --account-id <id>` |
314
475
  | **広告一覧 (YDA)** | `npx -y addashboard-cli@latest list --platform yda --resource ads --account-id <id> --campaign-id <cpId>`(広告グループで絞るなら `--ad-group-ids <id1,id2>`。どちらか必須) |
315
- | 登録画像一覧 (YDA) | `npx -y addashboard-cli@latest list --platform yda --resource media --account-id <id>` |
476
+ | 登録画像一覧 (YDA) | `npx -y addashboard-cli@latest list --platform yda --resource media --account-id <id>`(審査状況 `approvalStatus` と否認理由コード `disapprovalReasonCodes` 付き) |
477
+ | **掲載不可の画像だけ抽出 (YDA)** | `npx -y addashboard-cli@latest list --platform yda --resource media --account-id <id> --approval-status PRE_DISAPPROVED,DISAPPROVED` |
478
+ | **入稿後の状態確認 (Google)** | `npx -y addashboard-cli@latest list --platform google --resource ads --account-id <id> [--campaign-id <cpId>]`(CP/広告グループ/広告の status を名前で返す) |
316
479
  | 登録画像一覧 (Meta) | `npx -y addashboard-cli@latest list --platform meta --resource image-library --account-id act_<id>`(imageHash) |
317
480
  | 登録動画一覧 (Meta) | `npx -y addashboard-cli@latest list --platform meta --resource video-library --account-id act_<id>`(videoId) |
318
481
  | 汎用入稿 (JSON) dry-run | `npx -y addashboard-cli@latest submit --platform <媒体> --json-file <path>` |
@@ -320,6 +483,12 @@ skills/ad-ops/scripts/adops.sh open yda <accountId> campaigns
320
483
  | 入稿計画 順次入稿 dry-run | `npx -y addashboard-cli@latest submit-plan --plan-file <入稿計画.json>`(yda / meta。`plan.platform` 未記載は yda 扱い) |
321
484
  | 入稿計画 順次入稿 実入稿 | `npx -y addashboard-cli@latest submit-plan --plan-file <入稿計画.json> --no-dry-run --yes`(1CPずつ・再開可能) |
322
485
 
486
+ **【重要】画像が「掲載不可」でも広告は「承認済み」のままになる。** 広告単位の審査状況(`--resource ads` の `approvalStatus`)が全件 APPROVED でも、画像単位で掲載不可になっていることがある。**画像の掲載可否は `--resource media` でしか分からない**ので、入稿後の確認は両方を見る。掲載不可があったら「別名で再アップロード → 差し替え広告を追加」する(同名で上げ直しても否認判定が引き継がれる)。
487
+
488
+ - `approvalStatus` の実測値は `APPROVED` と `PRE_DISAPPROVED`(= 管理画面の「掲載不可」)
489
+ - `disapprovalReasonCodes` は理由コードの配列。**空配列なら否認なし**。コードの意味は Yahoo の公式リファレンスを引く(CLI は説明文を持たない)
490
+ - 差し替え画像のサイズ合わせ用に `width` / `height` / `fileSize` / `aspectRatio` / `mediaAdFormat` も返る
491
+
323
492
  **【重要】本実行がタイムアウトしたら「失敗」と決めつけない。** CLI の進捗は `unknown`(成否不明)になる。backend は入稿を続けており、**キャンペーンと広告が作成済みのことがある**(実測あり)。この状態で再実行すると二重入稿になるため `unknown` は自動でスキップされる。媒体の管理画面を確認し、作成済みなら計画ファイルの `status` を `"submitted"`、未作成なら `"pending"` に直してから再実行する(exit code は 3)。
324
493
  | 「予実」「予実管理」「今月の予実」「着地予測」「予実サマリ」 | `npx -y addashboard-cli@latest pl summary`(月指定は `pl summary --month YYYY-MM`) |
325
494
  | 「案件別の予実」「案件ごとの損益」 | `npx -y addashboard-cli@latest pl projects`(`--month` / `--status` / `--platform` で絞り込み可) |
@@ -330,7 +499,7 @@ skills/ad-ops/scripts/adops.sh open yda <accountId> campaigns
330
499
 
331
500
  ***
332
501
 
333
- ## 入稿プランナー(YDA / Meta 媒体切替・JSON入稿)
502
+ ## 入稿プランナー(YDA / Meta / Google / TikTok 媒体切替・JSON入稿)
334
503
 
335
504
  動画の API 入稿とは別に、**一括入稿を計画・確認する**ためのシングルHTMLツール。2026-07-16 / 07-21 定例フィードバックを反映。**2026-07-23 に CSV 書き出しを廃止し、保存・入稿受け渡しを JSON に統一**。**2026-07-30 に媒体スキーマ駆動化(`PLATFORMS` レジストリ)して Meta に対応**。
336
505
 
@@ -355,7 +524,8 @@ skills/ad-ops/scripts/adops.sh open yda <accountId> campaigns
355
524
  | 入札 | 最大配信 / tCPA(`MAXIMIZE_CONVERSIONS`+targetCpa) | `LOWEST_COST_WITHOUT_CAP` / `LOWEST_COST_WITH_BID_CAP` / `COST_CAP` / `LOWEST_COST_WITH_MIN_ROAS`(後2者は `bidAmount` 必須) |
356
525
  | ターゲティング列 | 年齢 / 性別 / デバイス / 曜日時間帯 / **オーディエンス(含む・除外)** / **配置(含む・除外)** / 地域・サーチKW。**オーディエンス・配置は参照表の実IDで入稿JSONに載り、本番の配信ターゲティングに反映される**(数値IDでない値は落として警告)。**入稿JSONに載らないのは 地域 と サーチKW だけ** | 年齢(ageMin/ageMax) / 性別 / デバイス / 配置(Facebook / Instagram / Audience Network / Messenger、既定は自動配置) |
357
526
  | 命名規則 | `{番号}{c\|s}-{見出し}L{本文}-{paramCode}` / `?ad=&creative=` | **同形式を踏襲**(形式記号は `i`(画像) / `v`(動画))。**最終URLは `{記事URL}?ad={paramCode}` のみ**(`creative=` もパス連結もしない)。paramCode は**広告行 > 広告セット**の実効値 |
358
- | 手入稿の除外 | バナー(固定サイズ)は API 未対応 → `手入稿` フラグで入稿JSONから除外 | 手入稿フラグの区分は無し(未解決の広告のみ除外) |
527
+ | 広告タイプ | 広告行の**「広告タイプ」列**で レスポンシブ(`RESPONSIVE_AD`) / バナー(`BANNER_AD`) を選ぶ。**同一キャンペーンで混在可**。バナーはタイトル/説明文/主体者/CTA が API に存在しないのでセルが「—」で無効化される | 区分なし(レスポンシブ相当のみ) |
528
+ | 書き出しの除外 | **未解決の広告のみ**除外(バナーは除外しない=API入稿対象) | 同じ(未解決の広告のみ除外) |
359
529
  | 管理画面 | `https://ads.yahoo.co.jp/manager/#/{mccId}/{accountId}/list/campaigns`(**CP詳細への直リンクは不可**) | `adsmanager.facebook.com/adsmanager/manage/campaigns?act=<数値>` |
360
530
 
361
531
  **Meta で未対応(今回スコープ外)**: カルーセル/コレクション等の複数素材フォーマット、カスタムオーディエンス/類似オーディエンスの ID 解決、地域ターゲティングの細分化(国単位のみ)、既存キャンペーンの複製テンプレート運用の GUI 化。**本番 Meta API への本入稿 PoC も未実施**。
@@ -413,6 +583,7 @@ skills/ad-ops/scripts/adops.sh open yda <accountId> campaigns
413
583
  | `status: ACTIVE` | 確認前に配信・課金が始まる |
414
584
  | 日予算の桁間違い | 想定外の課金 |
415
585
  | CP名に「テスト」等が残存 | 本番アカウントに検証用の名前が残る |
586
+ | **CP名がアカウントの既存CPと同名 (Google)** | **Google は同名CPを拒否する**。dry-run は通り、本実行の作成で落ちる。lint が ERROR で拾う |
416
587
  | `imagePaths` のファイルが存在しない | 本実行のアップロードで初めて落ちる。lint は ERROR で拾う(`~` 展開・相対の基準は計画JSONのディレクトリ) |
417
588
  | `paramCode` が特定できない | 計測パラメータ無しの広告が入稿される。パラメータ無し運用なら `urlParamsEnabled: false` を入れる(WARN 止まりになる) |
418
589
  | `smartTargeting: false` | 配信が伸びない。方針は常時 ON なので lint が WARN で拾う |
@@ -481,7 +652,7 @@ npx -y addashboard-cli@latest list --platform yda --resource ads \
481
652
  ```
482
653
  * **`campaigns --campaign-id`(campaign-import)はキャンペーン + 広告グループ設定までしか返さない**。広告の文言が要るときはこちらを使う
483
654
 
484
- **【必須】アカウントJSONには `baseArticleUrl` を必ず入れる(YDA / Meta 共通)。** 記事ベースURL(例: `https://iiiyah.com/ab/`)。
655
+ **【必須】アカウントJSONには `baseArticleUrl` を必ず入れる(YDA / Meta 共通)。** 記事ベースURL(例: `https://example.com/lp/`)。
485
656
 
486
657
  * 未設定だと `finalUrl` が `jv_C_1?ad=...` のような**相対パス**になり、**遷移先の壊れた広告が入稿される**
487
658
  * **`submit-plan` の dry-run はこれを検出しない**(形式チェックのみ)。`adops.sh plan` の lint が ERROR で拾う
@@ -582,7 +753,7 @@ npx -y addashboard-cli@latest list --platform yda --resource ads \
582
753
  - **履歴ビュー**: バージョン・日時・媒体・名称・メモ・作成者の一覧。`読込`(過去バージョン復元)/ `編集`(名称・メモ)/ `削除`。
583
754
  - **入稿JSON書き出し**: 設定ダイアログなしの**ワンクリック**。参照未解決の広告は自動除外、accountId 未入力・0件なら書き出し中止(空入稿防止)。媒体別の中身:
584
755
  - **YDA(見出し・本文の空欄許容)**: **タイトル番号 / 説明文番号は空欄でよい**(見出し・本文を使わない広告のケース)。空欄の広告はエラーにならず、`headlines` / `descriptions` は**空配列**で書き出され、backend も空を受理する。**空を許容するのはこの2フィールドのみ**(画像番号 `imageNo`・`paramCode`・principal・finalUrl は従来どおり必須)。**番号を入れたのに参照表(refs.titles / refs.descriptions)に無い場合は従来どおり「未解決」エラー**で、その広告は書き出しから除外される(別の障害なので緩めない)。Meta は従来どおり見出し・本文とも必須。
585
- - **YDA**: アカウントID・目的(goal)・配信開始日は案件設定チップ、入札はキャンペーン行(tCPA→`MAXIMIZE_CONVERSIONS`+targetCpa)、ターゲティングは広告グループ行の列(日本語ラベル→API enum 自動変換)から `*_入稿計画_*.json`(planVersion:1、広告は IMAGE 形式: mediaIds/headlines/descriptions/principal)を生成。手入稿バナーも自動除外。
756
+ - **YDA**: アカウントID・目的(goal)・配信開始日は案件設定チップ、入札はキャンペーン行(tCPA→`MAXIMIZE_CONVERSIONS`+targetCpa)、ターゲティングは広告グループ行の列(日本語ラベル→API enum 自動変換)から `*_入稿計画_*.json`(planVersion:1、広告は IMAGE 形式: mediaIds/headlines/descriptions/principal)を生成。広告タイプ=バナーの行は `adType:"BANNER_AD"` + `mediaIds` のみ(テキスト系は出さない)。除外されるのは参照未解決の広告だけ。
586
757
  - **Meta**: 予算は広告セット行(CBO は使わない)、目的は `objective`、最適化/課金/入札戦略/pixel/CVイベント/FBページID は案件設定チップ、ターゲティング(年齢・性別・デバイス・配置)は広告セット行の列から `*_Meta入稿計画_*.json`(planVersion:1、`platform:"meta"`、`campaigns[].adSets[]`、広告は IMAGE / VIDEO)を生成。`act_` 形式違反・FBページID 未入力・pixelId 必須ケースの未入力でブロック。 **配信日時(`startTime` / `endTime`)は広告セットごとに解決される(広告セット行 > 案件設定チップ > 既定=翌日05:00)。入力は `YYYY-MM-DD [HH:mm[:ss]]`・JST 前提で、書き出し時に `+0900` 付き ISO8601 に正規化される(時刻を明示した場合は 23:59:59 に丸めずその時刻を尊重)。`startTime` は常に送り、配信終了日が空欄なら `endTime` キー自体を送らない(無期限配信)。`lifetimeBudget` 指定時に限り backend が配信開始日+30日を補完する。**
587
758
 
588
759
  ### 量産構造(媒体要件の核)
@@ -595,7 +766,10 @@ npx -y addashboard-cli@latest list --platform yda --resource ads \
595
766
  ### 入稿モードと手入稿
596
767
 
597
768
  - モード: **新規**(12,000円/日・1CP=1AG=1広告を量産)/ **既存ASC**(5万〜10万円/日・まとめ入稿)/ 既存-広告グループ追加 / 既存-広告追加。
598
- - **YDA のバナー(固定サイズ画像)は API 未対応 → 手入稿**。プランナーでは `手入稿` フラグで区別し、入稿JSONから自動除外。Meta には手入稿フラグの区分は無い。
769
+ - **YDA のバナー(静止画・固定サイズ)は API 入稿に対応済**(2026-08-19 本番実機で `AdGroupAdService/add` 成功)。プランナーの広告行「広告タイプ」列で **レスポンシブ / バナー** を選ぶだけで、レスポンシブと同じ入稿計画JSON → `submit-plan` に乗る(**手入稿フラグという仕組みは存在しない**。過去のドキュメント記述だけが残っていた)。
770
+ - **画像プールは共用**: YDA のメディアはアカウントに1ライブラリだけで「バナー用/レスポンシブ用」の区分は無い。バナー行も参照表 `refs.media[画像番号].card` / `.sq` をそのまま引く(形式列 = 画像サイズ Card/SQ)。**広告タイプ(レスポンシブ/バナー)と 形式(Card/SQ)は独立した2軸**。
771
+ - **命名**: バナーはタイトル/説明文が存在しないので L 区間を出さない → `{画像番号}{c|s}-{paramCode}`(例 `957c-jv_Cac_148`)。レスポンシブは従来どおり `957c-45L60-jv_Cac_148`。
772
+ - 入稿計画JSON では `adType:"BANNER_AD"` が載り、`headlines` / `descriptions` / `principal` / `buttonText` は出さない(`adType` 省略時は `RESPONSIVE_AD` 扱い=旧プラン後方互換)。
599
773
 
600
774
  ### 発火時の案内
601
775
 
@@ -644,5 +818,5 @@ npx -y addashboard-cli@latest list --platform yda --resource ads \
644
818
  - **命名規則の統一**: `【】内の数字`のみ共通で、キャンペーン名/広告名は担当者差がある → システム命名に寄せられるようにする。
645
819
  - ~~**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` を追加。
646
820
  - **Meta の残タスク(未対応)**: 本番アカウントへの入稿 PoC(未実施)、カルーセル/コレクション等の複数素材フォーマット、カスタムオーディエンス/類似オーディエンスの ID 解決、地域ターゲティング細分化(現状は国単位)、既存キャンペーンの複製テンプレート運用の GUI 化。
647
- - **TikTok / ByteDance のプランナー対応**: 未着手(`PLATFORMS` に媒体定義を追加すれば載る設計)。
821
+ - **TikTok / ByteDance の拡張**: CV最適化(`WEB_CONVERSIONS` + pixel)/ 画像広告(`SINGLE_IMAGE`)/ カルーセル / Spark Ads / プランナーからのローカル動画アップロード / 配信期間 / `refs-import` は未対応。
648
822
  - **未確定(要実機確認)**: CTA既定(画像=もっとみる / 動画=詳細を見る)と `buttonText` enum、画像レスポンシブAPI入稿(PR #82)の実疎通、新規時に CP/AG ID 未払出でどう入稿するか、画像サムネURLの入手経路。