@adkit/cli 1.13.1 → 1.13.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.
- package/dist/cli.js +51 -18
- 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
|
|
2488
|
-
const
|
|
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.
|
|
2786
|
-
|
|
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
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
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");
|
|
@@ -3504,6 +3513,7 @@ function isStatusResponse(value) {
|
|
|
3504
3513
|
if (!value || typeof value !== "object") return false;
|
|
3505
3514
|
if (!("connected" in value) || typeof value.connected !== "boolean") return false;
|
|
3506
3515
|
if (!("project" in value) || !value.project || typeof value.project !== "object") return false;
|
|
3516
|
+
if (!("instructions" in value) || typeof value.instructions !== "string") return false;
|
|
3507
3517
|
if (!("platforms" in value) || !value.platforms || typeof value.platforms !== "object") return false;
|
|
3508
3518
|
return true;
|
|
3509
3519
|
}
|
|
@@ -3531,6 +3541,8 @@ async function status(client, json) {
|
|
|
3531
3541
|
lines.push("Google: connected");
|
|
3532
3542
|
for (const a of platforms.google.accounts) lines.push(` ${a.id} \u2014 ${a.name} (${a.currency})`);
|
|
3533
3543
|
} else lines.push("Google: not connected");
|
|
3544
|
+
lines.push("");
|
|
3545
|
+
lines.push(data.instructions);
|
|
3534
3546
|
console.log(lines.join("\n"));
|
|
3535
3547
|
}
|
|
3536
3548
|
|
|
@@ -4150,7 +4162,10 @@ function wrapToLines(value, max) {
|
|
|
4150
4162
|
if (word.length > max) {
|
|
4151
4163
|
if (current) lines.push(current);
|
|
4152
4164
|
current = "";
|
|
4153
|
-
for (let i = 0; i < word.length; i += max)
|
|
4165
|
+
for (let i = 0; i < word.length; i += max) {
|
|
4166
|
+
const chunk = word.slice(i, i + max);
|
|
4167
|
+
lines.push(chunk);
|
|
4168
|
+
}
|
|
4154
4169
|
continue;
|
|
4155
4170
|
}
|
|
4156
4171
|
const next = current ? current + " " + word : word;
|
|
@@ -4164,14 +4179,19 @@ function wrapToLines(value, max) {
|
|
|
4164
4179
|
if (current) lines.push(current);
|
|
4165
4180
|
return lines.length > 0 ? lines : [""];
|
|
4166
4181
|
}
|
|
4167
|
-
function
|
|
4168
|
-
return `$${
|
|
4182
|
+
function formatSearchTermMoney(value) {
|
|
4183
|
+
return `$${value.toFixed(2)}`;
|
|
4169
4184
|
}
|
|
4170
4185
|
function formatSearchTermConversions(conversions) {
|
|
4171
4186
|
if (conversions === 0) return "0";
|
|
4172
4187
|
const fixed = conversions.toFixed(2);
|
|
4173
4188
|
return fixed.replace(/\.?0+$/, "");
|
|
4174
4189
|
}
|
|
4190
|
+
function formatSearchTermRoas(roas) {
|
|
4191
|
+
if (roas === 0) return "0x";
|
|
4192
|
+
const fixed = roas.toFixed(2);
|
|
4193
|
+
return fixed.replace(/\.?0+$/, "") + "x";
|
|
4194
|
+
}
|
|
4175
4195
|
function hasSearchTermStringFields(value) {
|
|
4176
4196
|
if (value === null || typeof value !== "object") return false;
|
|
4177
4197
|
if (!("searchTerm" in value) || typeof value.searchTerm !== "string") return false;
|
|
@@ -4182,7 +4202,11 @@ function hasSearchTermStringFields(value) {
|
|
|
4182
4202
|
function hasSearchTermNumberFields(value) {
|
|
4183
4203
|
if (value === null || typeof value !== "object") return false;
|
|
4184
4204
|
if (!("impressions" in value) || typeof value.impressions !== "number") return false;
|
|
4205
|
+
if (!("clicks" in value) || typeof value.clicks !== "number") return false;
|
|
4185
4206
|
if (!("cost" in value) || typeof value.cost !== "number") return false;
|
|
4207
|
+
if (!("conversions" in value) || typeof value.conversions !== "number") return false;
|
|
4208
|
+
if (!("conversionsValue" in value) || typeof value.conversionsValue !== "number") return false;
|
|
4209
|
+
if (!("roas" in value) || typeof value.roas !== "number") return false;
|
|
4186
4210
|
return true;
|
|
4187
4211
|
}
|
|
4188
4212
|
function isGoogleSearchTermRecord(value) {
|
|
@@ -4205,8 +4229,10 @@ function toGoogleSearchTermDisplayRows(row) {
|
|
|
4205
4229
|
MATCH: isFirst ? row.matchType : "",
|
|
4206
4230
|
IMPR: isFirst ? row.impressions : "",
|
|
4207
4231
|
CLICKS: isFirst ? row.clicks : "",
|
|
4208
|
-
COST: isFirst ?
|
|
4209
|
-
CONV: isFirst ? formatSearchTermConversions(row.conversions) : ""
|
|
4232
|
+
COST: isFirst ? formatSearchTermMoney(row.cost) : "",
|
|
4233
|
+
CONV: isFirst ? formatSearchTermConversions(row.conversions) : "",
|
|
4234
|
+
VALUE: isFirst ? formatSearchTermMoney(row.conversionsValue) : "",
|
|
4235
|
+
ROAS: isFirst ? formatSearchTermRoas(row.roas) : ""
|
|
4210
4236
|
});
|
|
4211
4237
|
}
|
|
4212
4238
|
return result;
|
|
@@ -5242,7 +5268,7 @@ Notes:
|
|
|
5242
5268
|
Display targeting is passed with --data on create or update:
|
|
5243
5269
|
targeting.audience.interests, targeting.audience.customAudiences, targeting.content.topics, targeting.content.websites.
|
|
5244
5270
|
Topic and interest search return IDs used in targeting: research topics -> targeting.content.topics; research interests -> targeting.audience.interests.
|
|
5245
|
-
Websites use direct URLs in targeting.content.websites.include/exclude.
|
|
5271
|
+
Websites use direct URLs in targeting.content.websites.include/exclude. Bare numeric customAudiences IDs are treated as Google user lists (remarketing/Customer Match); for custom segments, pass a customAudiences/{id} or customers/{accountId}/customAudiences/{id} resource path.
|
|
5246
5272
|
WARNING: On update, targeting replaces the full Display targeting set. If you send only one new website, old websites/topics/audiences can be removed.
|
|
5247
5273
|
list returns ad group configuration only (name, status, bid).
|
|
5248
5274
|
For spend/clicks/conversions: adkit manage google results
|
|
@@ -5274,7 +5300,8 @@ Flags (create/update):
|
|
|
5274
5300
|
--status <s> enabled, paused, removed
|
|
5275
5301
|
|
|
5276
5302
|
Flags (list):
|
|
5277
|
-
--
|
|
5303
|
+
--campaign <ids> Filter by Google campaign IDs (platformId, comma-separated)
|
|
5304
|
+
--ad-group <ids> Filter by Google ad group IDs (platformId, comma-separated)
|
|
5278
5305
|
--status <s> Filter by ad status (default: enabled,paused; use all for every status)
|
|
5279
5306
|
--policy-status <s> Filter by policy status: approved, limited, disapproved, problem, pending_review, under_appeal
|
|
5280
5307
|
--limit <n> Max results
|
|
@@ -5293,6 +5320,7 @@ Notes:
|
|
|
5293
5320
|
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
5321
|
|
|
5295
5322
|
Examples:
|
|
5323
|
+
adkit manage google ads list --account 1234567890 --campaign 987654321,987654322
|
|
5296
5324
|
adkit manage google ads list --account 1234567890 --ad-group 555666777
|
|
5297
5325
|
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
5326
|
adkit manage google ads create --ad-group 555666777 \\
|
|
@@ -5328,7 +5356,8 @@ ${FLAG.publish}
|
|
|
5328
5356
|
${FLAG.data}
|
|
5329
5357
|
|
|
5330
5358
|
Flags (list):
|
|
5331
|
-
--
|
|
5359
|
+
--campaign <ids> Filter by Google campaign IDs (platformId, comma-separated)
|
|
5360
|
+
--ad-group <ids> Filter by Google ad group IDs (platformId, comma-separated)
|
|
5332
5361
|
--status <s> Filter by ad status (default: enabled,paused; use all for every status)
|
|
5333
5362
|
--policy-status <s> Filter by policy status: approved, limited, disapproved, problem, pending_review, under_appeal
|
|
5334
5363
|
--limit <n> Max results
|
|
@@ -5349,6 +5378,7 @@ Notes:
|
|
|
5349
5378
|
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
5379
|
|
|
5351
5380
|
Examples:
|
|
5381
|
+
adkit manage google ads list --account 1234567890 --campaign 987654321,987654322
|
|
5352
5382
|
adkit manage google ads list --account 1234567890 --ad-group 555666777
|
|
5353
5383
|
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
5384
|
adkit manage google ads create --ad-group 555666777 \\
|
|
@@ -5623,6 +5653,8 @@ Flags:
|
|
|
5623
5653
|
--limit <n> Max results
|
|
5624
5654
|
--raw Return raw Google API response
|
|
5625
5655
|
|
|
5656
|
+
Output includes conversion value and ROAS so tROAS accounts can be judged from the same rows.
|
|
5657
|
+
|
|
5626
5658
|
Examples:
|
|
5627
5659
|
adkit manage google results search-terms --account 1234567890
|
|
5628
5660
|
adkit manage google results search-terms --account 1234567890 --campaign 456 --period 30d --sort clicks
|
|
@@ -5665,7 +5697,7 @@ Examples:
|
|
|
5665
5697
|
adkit manage google results keywords --account 1234567890 --period 30d --fields all`;
|
|
5666
5698
|
var GOOGLE_RESEARCH_HELP = `adkit manage google research \u2014 Google Ads research tools
|
|
5667
5699
|
|
|
5668
|
-
keywords <
|
|
5700
|
+
keywords <keyword...> Get keyword ideas from Google Keyword Planner
|
|
5669
5701
|
topics <query> Find Display topic IDs for targeting.content.topics
|
|
5670
5702
|
interests <query> Find Display interest IDs for targeting.audience.interests
|
|
5671
5703
|
|
|
@@ -5687,9 +5719,10 @@ Examples:
|
|
|
5687
5719
|
adkit manage google research interests software --account 1234567890
|
|
5688
5720
|
|
|
5689
5721
|
Notes:
|
|
5722
|
+
Keyword research: pass each seed keyword as a separate argument. Do not comma-separate keywords.
|
|
5690
5723
|
Topic search returns IDs for targeting.content.topics.include/exclude.
|
|
5691
5724
|
Interest search returns IDs for targeting.audience.interests.include/exclude.
|
|
5692
|
-
Websites use direct URLs in targeting.content.websites.include/exclude.
|
|
5725
|
+
Websites use direct URLs in targeting.content.websites.include/exclude. Bare numeric customAudiences IDs are treated as Google user lists (remarketing/Customer Match); for custom segments, pass a customAudiences/{id} or customers/{accountId}/customAudiences/{id} resource path.`;
|
|
5693
5726
|
var GOOGLE_MEDIA_HELP = `adkit manage google media \u2014 Upload creative media to Google Ads
|
|
5694
5727
|
|
|
5695
5728
|
upload Upload an image and return reusable Google asset IDs
|
package/package.json
CHANGED