@adkit/cli 1.13.1 → 1.13.2

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 (2) hide show
  1. package/dist/cli.js +46 -16
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1834,7 +1834,7 @@ var CAMPAIGN_CREATE_FLAGS = ["name", "status", "budget-daily", "campaign-type",
1834
1834
  var CAMPAIGN_UPDATE_FLAGS = ["name", "status", "budget-daily", "bid-strategy", "target-cpa", "target-roas", "search-partners", "display-network", "tracking-url-suffix", "countries"];
1835
1835
  var AD_GROUP_LIST_FLAGS = ["campaign", "status", "limit", "offset"];
1836
1836
  var AD_GROUP_FLAGS = ["campaign", "name", "status", "cpc-bid"];
1837
- var AD_LIST_FLAGS = ["ad-group", "status", "policy-status", "limit", "offset"];
1837
+ var AD_LIST_FLAGS = ["ad-group", "campaign", "status", "policy-status", "limit", "offset"];
1838
1838
  var AD_FLAGS2 = ["headline", "headline-1", "headline-2", "headline-3", "description", "description-1", "description-2", "callout", "sitelink", "final-url", "path", "ad-group", "status"];
1839
1839
  var KEYWORD_LIST_FLAGS = ["ad-group", "campaign", "status", "limit", "offset"];
1840
1840
  var KEYWORD_FLAGS = ["ad-group", "text", "match-type", "cpc-bid", "status"];
@@ -2484,8 +2484,9 @@ async function deleteAdGroup(client, args, flags) {
2484
2484
  }
2485
2485
  async function listGoogleAds(client, _args, flags) {
2486
2486
  validateFlags(flags, AD_LIST_FLAGS, "manage google ads list");
2487
- const adGroupId = typeof flags["ad-group"] === "string" ? flags["ad-group"] : void 0;
2488
- const qs = buildGoogleListQuery(flags, { adGroupId });
2487
+ const adGroupIds = typeof flags["ad-group"] === "string" ? flags["ad-group"] : void 0;
2488
+ const campaignIds = typeof flags.campaign === "string" ? flags.campaign : void 0;
2489
+ const qs = buildGoogleListQuery(flags, { adGroupIds, campaignIds });
2489
2490
  const path3 = `/manage/google/ads${qs}`;
2490
2491
  return client.get(path3);
2491
2492
  }
@@ -2782,17 +2783,25 @@ async function listGoogleKeywordResults(client, _args, flags) {
2782
2783
  }
2783
2784
  async function researchKeywords(client, _args, flags) {
2784
2785
  validateFlags(flags, KEYWORD_RESEARCH_FLAGS, "manage google research keywords");
2785
- const keywords = _args.join(",");
2786
- if (!keywords) throw new CliError("MISSING_ARGUMENT", "At least one seed keyword is required", 'Run: adkit manage google research keywords "saas ads" --account 1234567890');
2786
+ const keywords = _args.map((keyword) => keyword.trim());
2787
+ const hasBlankKeyword = keywords.some((keyword) => keyword.length === 0);
2788
+ if (keywords.length === 0) throw new CliError("MISSING_ARGUMENT", "At least one seed keyword is required", 'Run: adkit manage google research keywords "saas ads" --account 1234567890');
2789
+ if (hasBlankKeyword) throw new CliError("INVALID_VALUE", "Seed keywords must be non-empty", 'Run: adkit manage google research keywords "saas ads" --account 1234567890');
2787
2790
  const url = typeof flags.url === "string" ? flags.url : void 0;
2788
2791
  const location = typeof flags.location === "string" ? flags.location : void 0;
2789
2792
  const language = typeof flags.language === "string" ? flags.language : void 0;
2790
2793
  const limit = typeof flags.limit === "string" ? flags.limit : void 0;
2791
2794
  const minVolume = typeof flags["min-volume"] === "string" ? flags["min-volume"] : void 0;
2792
2795
  const accountId = typeof flags.account === "string" ? flags.account : void 0;
2793
- const qs = queryString({ accountId, keywords, url, location, language, limit, minVolume });
2794
- const path3 = `/manage/google/research/keywords${qs}`;
2795
- return client.get(path3);
2796
+ return client.post("/manage/google/research/keywords", {
2797
+ accountId,
2798
+ keywords,
2799
+ url,
2800
+ location,
2801
+ language,
2802
+ limit,
2803
+ minVolume
2804
+ });
2796
2805
  }
2797
2806
  async function researchTopics(client, args, flags) {
2798
2807
  validateFlags(flags, TARGETING_RESEARCH_FLAGS, "manage google research topics");
@@ -4150,7 +4159,10 @@ function wrapToLines(value, max) {
4150
4159
  if (word.length > max) {
4151
4160
  if (current) lines.push(current);
4152
4161
  current = "";
4153
- for (let i = 0; i < word.length; i += max) lines.push(word.slice(i, i + max));
4162
+ for (let i = 0; i < word.length; i += max) {
4163
+ const chunk = word.slice(i, i + max);
4164
+ lines.push(chunk);
4165
+ }
4154
4166
  continue;
4155
4167
  }
4156
4168
  const next = current ? current + " " + word : word;
@@ -4164,14 +4176,19 @@ function wrapToLines(value, max) {
4164
4176
  if (current) lines.push(current);
4165
4177
  return lines.length > 0 ? lines : [""];
4166
4178
  }
4167
- function formatSearchTermCost(cost) {
4168
- return `$${cost.toFixed(2)}`;
4179
+ function formatSearchTermMoney(value) {
4180
+ return `$${value.toFixed(2)}`;
4169
4181
  }
4170
4182
  function formatSearchTermConversions(conversions) {
4171
4183
  if (conversions === 0) return "0";
4172
4184
  const fixed = conversions.toFixed(2);
4173
4185
  return fixed.replace(/\.?0+$/, "");
4174
4186
  }
4187
+ function formatSearchTermRoas(roas) {
4188
+ if (roas === 0) return "0x";
4189
+ const fixed = roas.toFixed(2);
4190
+ return fixed.replace(/\.?0+$/, "") + "x";
4191
+ }
4175
4192
  function hasSearchTermStringFields(value) {
4176
4193
  if (value === null || typeof value !== "object") return false;
4177
4194
  if (!("searchTerm" in value) || typeof value.searchTerm !== "string") return false;
@@ -4182,7 +4199,11 @@ function hasSearchTermStringFields(value) {
4182
4199
  function hasSearchTermNumberFields(value) {
4183
4200
  if (value === null || typeof value !== "object") return false;
4184
4201
  if (!("impressions" in value) || typeof value.impressions !== "number") return false;
4202
+ if (!("clicks" in value) || typeof value.clicks !== "number") return false;
4185
4203
  if (!("cost" in value) || typeof value.cost !== "number") return false;
4204
+ if (!("conversions" in value) || typeof value.conversions !== "number") return false;
4205
+ if (!("conversionsValue" in value) || typeof value.conversionsValue !== "number") return false;
4206
+ if (!("roas" in value) || typeof value.roas !== "number") return false;
4186
4207
  return true;
4187
4208
  }
4188
4209
  function isGoogleSearchTermRecord(value) {
@@ -4205,8 +4226,10 @@ function toGoogleSearchTermDisplayRows(row) {
4205
4226
  MATCH: isFirst ? row.matchType : "",
4206
4227
  IMPR: isFirst ? row.impressions : "",
4207
4228
  CLICKS: isFirst ? row.clicks : "",
4208
- COST: isFirst ? formatSearchTermCost(row.cost) : "",
4209
- CONV: isFirst ? formatSearchTermConversions(row.conversions) : ""
4229
+ COST: isFirst ? formatSearchTermMoney(row.cost) : "",
4230
+ CONV: isFirst ? formatSearchTermConversions(row.conversions) : "",
4231
+ VALUE: isFirst ? formatSearchTermMoney(row.conversionsValue) : "",
4232
+ ROAS: isFirst ? formatSearchTermRoas(row.roas) : ""
4210
4233
  });
4211
4234
  }
4212
4235
  return result;
@@ -5274,7 +5297,8 @@ Flags (create/update):
5274
5297
  --status <s> enabled, paused, removed
5275
5298
 
5276
5299
  Flags (list):
5277
- --ad-group <id> Filter by Google ad group ID (platformId)
5300
+ --campaign <ids> Filter by Google campaign IDs (platformId, comma-separated)
5301
+ --ad-group <ids> Filter by Google ad group IDs (platformId, comma-separated)
5278
5302
  --status <s> Filter by ad status (default: enabled,paused; use all for every status)
5279
5303
  --policy-status <s> Filter by policy status: approved, limited, disapproved, problem, pending_review, under_appeal
5280
5304
  --limit <n> Max results
@@ -5293,6 +5317,7 @@ Notes:
5293
5317
  That means sibling ads in the same ad group may also use those assets. Use google assets if you need explicit scope control or richer sitelink payloads.
5294
5318
 
5295
5319
  Examples:
5320
+ adkit manage google ads list --account 1234567890 --campaign 987654321,987654322
5296
5321
  adkit manage google ads list --account 1234567890 --ad-group 555666777
5297
5322
  adkit manage google ads create --data '{"ads":[{"type":"responsive_display","adGroupId":"555666777","headlines":[{"text":"Display headline"}],"longHeadline":{"text":"A longer Display headline"},"descriptions":[{"text":"Display description"}],"businessName":"AdKit","finalUrls":["https://example.com"],"media":[{"role":"marketing_image","id":"customers/123/assets/111"},{"role":"square_marketing_image","id":"customers/123/assets/222"},{"role":"logo","id":"customers/123/assets/333"},{"role":"square_logo","id":"customers/123/assets/444"}]}]}' --account 1234567890
5298
5323
  adkit manage google ads create --ad-group 555666777 \\
@@ -5328,7 +5353,8 @@ ${FLAG.publish}
5328
5353
  ${FLAG.data}
5329
5354
 
5330
5355
  Flags (list):
5331
- --ad-group <id> Filter by Google ad group ID (platformId)
5356
+ --campaign <ids> Filter by Google campaign IDs (platformId, comma-separated)
5357
+ --ad-group <ids> Filter by Google ad group IDs (platformId, comma-separated)
5332
5358
  --status <s> Filter by ad status (default: enabled,paused; use all for every status)
5333
5359
  --policy-status <s> Filter by policy status: approved, limited, disapproved, problem, pending_review, under_appeal
5334
5360
  --limit <n> Max results
@@ -5349,6 +5375,7 @@ Notes:
5349
5375
  Path format: pass one string like "crm" or "crm/demo". AdKit normalizes extra slashes, and each segment must stay within Google's 15-character limit.
5350
5376
 
5351
5377
  Examples:
5378
+ adkit manage google ads list --account 1234567890 --campaign 987654321,987654322
5352
5379
  adkit manage google ads list --account 1234567890 --ad-group 555666777
5353
5380
  adkit manage google ads create --data '{"ads":[{"type":"responsive_display","adGroupId":"555666777","headlines":[{"text":"Display headline"}],"longHeadline":{"text":"A longer Display headline"},"descriptions":[{"text":"Display description"}],"businessName":"AdKit","finalUrls":["https://example.com"],"media":[{"role":"marketing_image","id":"customers/123/assets/111"},{"role":"square_marketing_image","id":"customers/123/assets/222"},{"role":"logo","id":"customers/123/assets/333"},{"role":"square_logo","id":"customers/123/assets/444"}]}]}' --account 1234567890
5354
5381
  adkit manage google ads create --ad-group 555666777 \\
@@ -5623,6 +5650,8 @@ Flags:
5623
5650
  --limit <n> Max results
5624
5651
  --raw Return raw Google API response
5625
5652
 
5653
+ Output includes conversion value and ROAS so tROAS accounts can be judged from the same rows.
5654
+
5626
5655
  Examples:
5627
5656
  adkit manage google results search-terms --account 1234567890
5628
5657
  adkit manage google results search-terms --account 1234567890 --campaign 456 --period 30d --sort clicks
@@ -5665,7 +5694,7 @@ Examples:
5665
5694
  adkit manage google results keywords --account 1234567890 --period 30d --fields all`;
5666
5695
  var GOOGLE_RESEARCH_HELP = `adkit manage google research \u2014 Google Ads research tools
5667
5696
 
5668
- keywords <query> Get keyword ideas from Google Keyword Planner
5697
+ keywords <keyword...> Get keyword ideas from Google Keyword Planner
5669
5698
  topics <query> Find Display topic IDs for targeting.content.topics
5670
5699
  interests <query> Find Display interest IDs for targeting.audience.interests
5671
5700
 
@@ -5687,6 +5716,7 @@ Examples:
5687
5716
  adkit manage google research interests software --account 1234567890
5688
5717
 
5689
5718
  Notes:
5719
+ Keyword research: pass each seed keyword as a separate argument. Do not comma-separate keywords.
5690
5720
  Topic search returns IDs for targeting.content.topics.include/exclude.
5691
5721
  Interest search returns IDs for targeting.audience.interests.include/exclude.
5692
5722
  Websites use direct URLs in targeting.content.websites.include/exclude. Custom audiences are Google user list IDs.`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adkit/cli",
3
- "version": "1.13.1",
3
+ "version": "1.13.2",
4
4
  "description": "The Ads CLI for AI agents — manage Meta & Google ad campaigns, browse the ad library, and generate creatives from your terminal.",
5
5
  "keywords": [
6
6
  "ads cli",