@adkit/cli 1.12.11 → 1.12.13

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 +77 -53
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1380,28 +1380,30 @@ function readMediaFormatFlag(value) {
1380
1380
  throw new CliError("INVALID_VALUE", `Invalid --media-format: ${value}`, "Use one of: default, square, vertical, horizontal.");
1381
1381
  }
1382
1382
  async function listResults(client, args, flags) {
1383
- validateFlags(flags, ["campaign", "adset", "ad", "status", "period", "from", "to", "metrics", "actions", "attribution-window", "breakdown", "sort", "limit", "confirm", "raw"], "manage meta results");
1383
+ validateFlags(flags, ["account", "campaign-ids", "adset-ids", "ad-ids", "statuses", "period", "from", "to", "fields", "conversion-event-keys", "attribution-window", "breakdowns", "sort", "sort-direction", "limit", "offset", "confirm", "raw"], "manage meta results");
1384
1384
  const accountId = typeof flags.account === "string" ? flags.account : void 0;
1385
1385
  const level = parseResultsLevel(args);
1386
1386
  warnIgnoredResultsArgs(args);
1387
- const campaign = typeof flags.campaign === "string" ? flags.campaign : void 0;
1388
- const adset = typeof flags.adset === "string" ? flags.adset : void 0;
1389
- const ad = typeof flags.ad === "string" ? flags.ad : void 0;
1390
- const status2 = typeof flags.status === "string" ? flags.status : void 0;
1387
+ const campaignIds = typeof flags["campaign-ids"] === "string" ? flags["campaign-ids"] : void 0;
1388
+ const adsetIds = typeof flags["adset-ids"] === "string" ? flags["adset-ids"] : void 0;
1389
+ const adIds = typeof flags["ad-ids"] === "string" ? flags["ad-ids"] : void 0;
1390
+ const statuses = typeof flags.statuses === "string" ? flags.statuses : void 0;
1391
1391
  const period = typeof flags.period === "string" ? flags.period : void 0;
1392
1392
  const from = typeof flags.from === "string" ? flags.from : void 0;
1393
1393
  const to = typeof flags.to === "string" ? flags.to : void 0;
1394
- const metrics = typeof flags.metrics === "string" ? flags.metrics : void 0;
1395
- const actions = typeof flags.actions === "string" ? flags.actions : void 0;
1394
+ const fields = typeof flags.fields === "string" ? flags.fields : void 0;
1395
+ const conversionEventKeys = typeof flags["conversion-event-keys"] === "string" ? flags["conversion-event-keys"] : void 0;
1396
1396
  const attributionWindow = typeof flags["attribution-window"] === "string" ? flags["attribution-window"] : void 0;
1397
- const breakdown = typeof flags.breakdown === "string" ? flags.breakdown : void 0;
1397
+ const breakdowns = typeof flags.breakdowns === "string" ? flags.breakdowns : void 0;
1398
1398
  const sort = typeof flags.sort === "string" ? flags.sort : void 0;
1399
+ const sortDirection = typeof flags["sort-direction"] === "string" ? flags["sort-direction"] : void 0;
1399
1400
  const limit = typeof flags.limit === "string" ? flags.limit : void 0;
1401
+ const offset = typeof flags.offset === "string" ? flags.offset : void 0;
1400
1402
  const confirm = flags.confirm === true ? "true" : void 0;
1401
1403
  const raw = flags.raw === true ? "true" : void 0;
1402
- const hasTimeBreakdown = breakdown?.split(",").some((b) => b === "day" || b === "week" || b === "month");
1404
+ const hasTimeBreakdown = breakdowns?.split(",").some((b) => b === "day" || b === "week" || b === "month");
1403
1405
  if (period === "maximum" && hasTimeBreakdown && !confirm) throw new CliError("INVALID_VALUE", "maximum date range with time breakdowns (day/week/month) can produce very large result sets. Add --confirm to proceed.");
1404
- const qs = queryString({ accountId, level, campaign, adset, ad, status: status2, period, from, to, metrics, actions, "attribution-window": attributionWindow, breakdown, sort, limit, confirm, raw });
1406
+ const qs = queryString({ accountId, level, campaignIds, adsetIds, adIds, statuses, period, from, to, fields, conversionEventKeys, attributionWindow, breakdowns, sort, sortDirection, limit, offset, confirm, raw });
1405
1407
  return client.get(`/manage/meta/results${qs}`);
1406
1408
  }
1407
1409
  async function createAd(client, _args, flags) {
@@ -4388,20 +4390,22 @@ var RESULTS_HELP = `adkit manage meta results \u2014 Meta performance insights
4388
4390
  [campaigns|adsets|ads] Optional level positional arg (default: campaigns)
4389
4391
 
4390
4392
  Flags:
4391
- --campaign <ids> Comma-separated campaign IDs
4392
- --adset <ids> Comma-separated ad set IDs
4393
- --ad <ids> Comma-separated ad IDs
4394
- --status <s> active, paused (filter by entity status)
4393
+ --campaign-ids <ids> Comma-separated campaign IDs
4394
+ --adset-ids <ids> Comma-separated ad set IDs
4395
+ --ad-ids <ids> Comma-separated ad IDs
4396
+ --statuses <s> active, paused (filter by entity status)
4395
4397
  --period <range> Relative range like 7d or preset: today, yesterday, this_month, last_month, this_quarter, last_quarter, this_year, last_year, maximum (default: 30d)
4396
4398
  --from <date> Start date, YYYY-MM-DD
4397
4399
  --to <date> End date, YYYY-MM-DD
4398
- --metrics <list> Override the default insights field preset
4399
- --actions <list> purchase,lead or all
4400
+ --fields <list> Normalized fields, e.g. spend, impressions, clicks, conversionEvents, etc
4401
+ --conversion-event-keys <list> purchase,lead or all
4400
4402
  --attribution-window <w> 1d_click, 7d_click, 1d_view, 7d_click_1d_view, 28d_click_1d_view
4401
- --breakdown <list> day,week,month,age,gender,country,region,device_platform,publisher_platform,platform_position,impression_device
4403
+ --breakdowns <list> day, week, month, age, gender, country, region, device_platform, publisher_platform, platform_position, impression_device
4402
4404
  --confirm Required with --period maximum plus any breakdown
4403
4405
  --sort <field> spend = descending, +spend = ascending
4406
+ --sort-direction <d> asc or desc
4404
4407
  --limit <n> Limit rows after sorting
4408
+ --offset <n> Skip rows after sorting
4405
4409
  --raw Return Meta's paginated response without conversion
4406
4410
 
4407
4411
  Output: always JSON, even in TTY mode.
@@ -4410,15 +4414,15 @@ Examples:
4410
4414
  # Campaign overview (default: last 30 days)
4411
4415
  adkit manage meta results
4412
4416
  # Top-spending ads for a campaign
4413
- adkit manage meta results ads --campaign 123 --sort spend --limit 10
4417
+ adkit manage meta results ads --campaign-ids 123 --sort spend --limit 10
4414
4418
  # Daily performance by age group
4415
- adkit manage meta results adsets --period 7d --breakdown day,age
4419
+ adkit manage meta results adsets --period 7d --breakdowns day,age
4416
4420
  # Country breakdown for all time
4417
- adkit manage meta results ads --period maximum --breakdown country --confirm
4421
+ adkit manage meta results ads --period maximum --breakdowns country --confirm
4418
4422
  # Conversion data for a campaign
4419
- adkit manage meta results --campaign 123 --actions purchase,lead
4423
+ adkit manage meta results --campaign-ids 123 --conversion-event-keys purchase,lead
4420
4424
  # Raw API response with custom metrics
4421
- adkit manage meta results --campaign 123 --raw --metrics spend,impressions,actions`.trim();
4425
+ adkit manage meta results --campaign-ids 123 --raw --fields spend,impressions,conversionEvents`.trim();
4422
4426
  var CREATIVE_HELP = `adkit manage meta creatives \u2014 Meta ad creatives
4423
4427
 
4424
4428
  Prefer using "ads create --media" which handles creative creation automatically.
@@ -5026,14 +5030,18 @@ Flags:
5026
5030
  --limit <n> Max results
5027
5031
  --status <s> Filter: enabled, paused, all
5028
5032
  --breakdown <b> Split rows by: day, device, network (For placements, use "results placements")
5029
- --fields <list> Response fields, e.g. cost,clicks,searchImpressionShare. Competitive metrics are opt-in.
5033
+ --fields <list> Response fields, e.g. cost,clicks,searchImpressionShare. Omit for default advertiser metrics; use all for every supported field.
5030
5034
  --raw Return raw Google API response
5031
5035
  --account <id> Optional if one Google Ads account is connected
5032
5036
 
5033
- Competitive metrics (opt-in via --fields):
5037
+ Default metrics include:
5038
+ Cost/clicks/conversions, CPA, CVR, ROAS, all conversions, view-through conversions,
5039
+ top-position rates, search impression share where Google supports it, and serving/learning status.
5040
+
5041
+ Visibility fields:
5034
5042
  Search: searchImpressionShare, searchRankLostImpressionShare, searchBudgetLostImpressionShare,
5035
- searchTopImpressionShare, searchAbsoluteTopImpressionShare, searchClickShare
5036
- Content: contentImpressionShare, contentRankLostImpressionShare, contentBudgetLostImpressionShare
5043
+ searchTopImpressionShare, searchAbsoluteTopImpressionShare, searchClickShare (default where supported)
5044
+ Content: contentImpressionShare, contentRankLostImpressionShare, contentBudgetLostImpressionShare (use --fields all)
5037
5045
  Note: search fields available at all levels except ads. Content fields not available at keywords or ads.
5038
5046
 
5039
5047
  Examples:
@@ -5045,7 +5053,7 @@ Examples:
5045
5053
  adkit manage google results placements --campaign 123 --period 30d
5046
5054
  adkit manage google results --period this_month --sort clicks --limit 20
5047
5055
  adkit manage google results search-terms --campaign 123 --period 30d
5048
- adkit manage google results --campaign 123 --fields default,searchImpressionShare,searchBudgetLostImpressionShare`;
5056
+ adkit manage google results --campaign 123 --fields all`;
5049
5057
  var GOOGLE_RESULTS_PLACEMENTS_HELP = `adkit manage google results placements \u2014 Google placement report
5050
5058
 
5051
5059
  Shows each website, app, or YouTube placement where ads appeared.
@@ -5108,12 +5116,13 @@ Flags:
5108
5116
  --sort <field> Sort by: cost (default), clicks, impressions, conversions, ctr, cpc
5109
5117
  --status <s> Filter: enabled, paused, all (default: all)
5110
5118
  --limit <n> Max results
5111
- --fields <list> Response fields, e.g. cost,clicks,qualityScore,searchImpressionShare
5119
+ --fields <list> Response fields, e.g. cost,clicks,qualityScore,searchImpressionShare. Omit for default advertiser metrics.
5112
5120
  --raw Return raw Google API response
5113
5121
 
5114
- Search competitive fields also available at keyword level:
5115
- searchImpressionShare, searchRankLostImpressionShare, searchBudgetLostImpressionShare,
5116
- searchTopImpressionShare, searchAbsoluteTopImpressionShare, searchClickShare
5122
+ Default keyword metrics include CPA, CVR, ROAS, search impression share, search lost impression share,
5123
+ search click share, primary serving/learning status, and Quality Score diagnostics.
5124
+ Extra keyword diagnostics are available with --fields all, including:
5125
+ systemServingStatus, approvalStatus, firstPageCpc, topOfPageCpc, firstPositionCpc
5117
5126
 
5118
5127
  Examples:
5119
5128
  adkit manage google results keywords --account 1234567890 --period 7d
@@ -5121,7 +5130,7 @@ Examples:
5121
5130
  adkit manage google results keywords --account 1234567890 --campaign 987654321 --period this_month
5122
5131
  adkit manage google results keywords --account 1234567890 --period last_month --fields cost,clicks,qualityScore
5123
5132
  adkit manage google results keywords --account 1234567890 --period 7d --fields default,primaryStatus
5124
- adkit manage google results keywords --account 1234567890 --period 30d --fields default,searchImpressionShare`;
5133
+ adkit manage google results keywords --account 1234567890 --period 30d --fields all`;
5125
5134
  var GOOGLE_RESEARCH_HELP = `adkit manage google research \u2014 Google Ads research tools
5126
5135
 
5127
5136
  keywords <query> Get keyword ideas from Google Keyword Planner
@@ -5913,11 +5922,11 @@ function printResultsCard(data) {
5913
5922
  const parts = [];
5914
5923
  const reportCurrency = str(report, "currency");
5915
5924
  const timezone = str(report, "timezone");
5916
- const attrWindow = str(report, "attribution_window");
5925
+ const attrWindow = str(report, "attributionWindow") ?? str(report, "attribution_window");
5917
5926
  if (reportCurrency) parts.push(reportCurrency);
5918
5927
  if (timezone) parts.push(timezone);
5919
5928
  if (attrWindow) parts.push(attrWindow);
5920
- const dr = nested(report, "date_range");
5929
+ const dr = nested(report, "dateRange") ?? nested(report, "date_range");
5921
5930
  if (dr) {
5922
5931
  const from = str(dr, "from");
5923
5932
  const to = str(dr, "to");
@@ -5925,7 +5934,7 @@ function printResultsCard(data) {
5925
5934
  }
5926
5935
  if (parts.length > 0) console.log(parts.join(" \xB7 "));
5927
5936
  }
5928
- const results = data.results;
5937
+ const results = Array.isArray(data.rows) ? data.rows : data.results;
5929
5938
  if (!Array.isArray(results) || results.length === 0) {
5930
5939
  console.log("\nNo results for this period.");
5931
5940
  printWarnings(data.warnings);
@@ -5933,40 +5942,43 @@ function printResultsCard(data) {
5933
5942
  }
5934
5943
  for (const row of results) {
5935
5944
  if (!isObject(row)) continue;
5936
- const name = str(row, "campaign_name") || str(row, "adset_name") || str(row, "ad_name") || "Unknown";
5945
+ const entity = nested(row, "entity");
5946
+ const metrics = nested(row, "metrics");
5947
+ const breakdown = nested(row, "breakdown");
5948
+ const name = (entity ? str(entity, "name") : void 0) || str(row, "campaign_name") || str(row, "adset_name") || str(row, "ad_name") || "Unknown";
5937
5949
  const titleParts = [name];
5938
- const status2 = str(row, "status");
5939
- const spend = num(row, "spend");
5950
+ const status2 = (entity ? str(entity, "status") : void 0) || str(row, "status");
5951
+ const spend = (metrics ? num(metrics, "spend") : void 0) ?? num(row, "spend");
5940
5952
  if (status2) titleParts.push(status2);
5941
5953
  if (spend !== void 0) titleParts.push(`${fmtCurrency(spend, currency)} spent`);
5942
- const dateStart = str(row, "date_start");
5943
- const dateStop = str(row, "date_stop");
5954
+ const dateStart = (breakdown ? str(breakdown, "day") ?? str(breakdown, "week") ?? str(breakdown, "month") ?? str(breakdown, "dateStart") : void 0) ?? str(row, "date_start");
5955
+ const dateStop = (breakdown ? str(breakdown, "dateStop") : void 0) ?? str(row, "date_stop");
5944
5956
  if (dateStart && dateStop) titleParts.push(`${fmtShortDate(dateStart)} \u2013 ${fmtShortDate(dateStop)}`);
5945
5957
  else if (dateStart) titleParts.push(fmtShortDate(dateStart));
5946
5958
  else if (dateStop) titleParts.push(fmtShortDate(dateStop));
5947
- const age = str(row, "age");
5959
+ const age = (breakdown ? str(breakdown, "age") : void 0) ?? str(row, "age");
5948
5960
  if (age) titleParts.push(age);
5949
- const gender = str(row, "gender");
5961
+ const gender = (breakdown ? str(breakdown, "gender") : void 0) ?? str(row, "gender");
5950
5962
  if (gender) titleParts.push(gender);
5951
- const country = str(row, "country");
5963
+ const country = (breakdown ? str(breakdown, "country") : void 0) ?? str(row, "country");
5952
5964
  if (country) titleParts.push(country);
5953
- const region = str(row, "region");
5965
+ const region = (breakdown ? str(breakdown, "region") : void 0) ?? str(row, "region");
5954
5966
  if (region) titleParts.push(region);
5955
- const devicePlatform = str(row, "device_platform");
5967
+ const devicePlatform = (breakdown ? str(breakdown, "devicePlatform") : void 0) ?? str(row, "device_platform");
5956
5968
  if (devicePlatform) titleParts.push(devicePlatform);
5957
- const publisherPlatform = str(row, "publisher_platform");
5969
+ const publisherPlatform = (breakdown ? str(breakdown, "publisherPlatform") : void 0) ?? str(row, "publisher_platform");
5958
5970
  if (publisherPlatform) titleParts.push(publisherPlatform);
5959
- const platformPosition = str(row, "platform_position");
5971
+ const platformPosition = (breakdown ? str(breakdown, "platformPosition") : void 0) ?? str(row, "platform_position");
5960
5972
  if (platformPosition) titleParts.push(platformPosition);
5961
- const impressionDevice = str(row, "impression_device");
5973
+ const impressionDevice = (breakdown ? str(breakdown, "impressionDevice") : void 0) ?? str(row, "impression_device");
5962
5974
  if (impressionDevice) titleParts.push(impressionDevice);
5963
5975
  console.log(`
5964
5976
  ${titleParts.join(" \xB7 ")}`);
5965
- const impressions = num(row, "impressions");
5977
+ const impressions = (metrics ? num(metrics, "impressions") : void 0) ?? num(row, "impressions");
5966
5978
  if (impressions !== void 0) console.log(` Impressions ${fmtNum(impressions)}`);
5967
- const reach = num(row, "reach");
5979
+ const reach = (metrics ? num(metrics, "reach") : void 0) ?? num(row, "reach");
5968
5980
  if (reach !== void 0) {
5969
- const freq = num(row, "frequency");
5981
+ const freq = (metrics ? num(metrics, "frequency") : void 0) ?? num(row, "frequency");
5970
5982
  const freqStr = freq !== void 0 ? ` (${fmtPct(freq)} freq)` : "";
5971
5983
  console.log(` Reach ${fmtNum(reach)}${freqStr}`);
5972
5984
  }
@@ -5976,14 +5988,17 @@ ${titleParts.join(" \xB7 ")}`);
5976
5988
  if (all) printClickLine("Clicks", all, currency);
5977
5989
  const outbound = nested(clicks, "outbound");
5978
5990
  if (outbound) printClickLine("Outbound", outbound, currency);
5991
+ } else if (metrics) {
5992
+ printClickLine("Clicks", { count: metrics.clicks, ctr: metrics.ctr, cpc: metrics.cpc }, currency);
5993
+ printClickLine("Outbound", { count: metrics.outboundClicks, ctr: metrics.outboundCtr, cpc: metrics.costPerOutboundClick }, currency);
5979
5994
  }
5980
- const actions = nested(row, "actions");
5995
+ const actions = nested(row, "conversionEvents") ?? nested(row, "actions");
5981
5996
  if (actions) {
5982
5997
  for (const [key, val] of Object.entries(actions)) {
5983
5998
  if (!isObject(val)) continue;
5984
5999
  const parts = [];
5985
6000
  const count = num(val, "count");
5986
- const cost = num(val, "cost");
6001
+ const cost = num(val, "costPerResult") ?? num(val, "cost");
5987
6002
  if (count !== void 0) parts.push(fmtNum(count));
5988
6003
  if (cost !== void 0) parts.push(`${fmtCurrency(cost, currency)} each`);
5989
6004
  if (parts.length > 0) console.log(` ${humanizeAction(key).padEnd(14)}${parts.join(" \xB7 ")}`);
@@ -5997,6 +6012,15 @@ ${titleParts.join(" \xB7 ")}`);
5997
6012
  for (const [key, val] of Object.entries(aq)) if (typeof val === "string" && val !== "UNKNOWN") parts.push(`${humanizeAction(key)}: ${val}`);
5998
6013
  if (parts.length > 0) console.log(` Ad Quality ${parts.join(" \xB7 ")}`);
5999
6014
  }
6015
+ } else if (metrics) {
6016
+ const parts = [];
6017
+ const qualityRanking = str(metrics, "qualityRanking");
6018
+ const engagementRateRanking = str(metrics, "engagementRateRanking");
6019
+ const conversionRateRanking = str(metrics, "conversionRateRanking");
6020
+ if (qualityRanking && qualityRanking !== "UNKNOWN") parts.push(`quality: ${qualityRanking}`);
6021
+ if (engagementRateRanking && engagementRateRanking !== "UNKNOWN") parts.push(`engagement rate: ${engagementRateRanking}`);
6022
+ if (conversionRateRanking && conversionRateRanking !== "UNKNOWN") parts.push(`conversion rate: ${conversionRateRanking}`);
6023
+ if (parts.length > 0) console.log(` Ad Quality ${parts.join(" \xB7 ")}`);
6000
6024
  }
6001
6025
  }
6002
6026
  printWarnings(data.warnings);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adkit/cli",
3
- "version": "1.12.11",
3
+ "version": "1.12.13",
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",