@koda-sl/baker-cli 0.353.0-dev.f5f2d3146 → 0.354.0-dev.7687bbeae
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/README.md +1 -5
- package/dist/cli.js +41 -27
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -238,10 +238,6 @@ baker ads google query --preset campaign-performance --customer-id 1234567890
|
|
|
238
238
|
# its target instead of holding its recent actual cost, so a target above actual raises cost.
|
|
239
239
|
baker ads google query --preset budget-limited --customer-id 1234567890
|
|
240
240
|
|
|
241
|
-
# Which target each ad group actually bids to: its own, or its campaign's / portfolio's.
|
|
242
|
-
# A campaign or portfolio target change does not reach an ad group whose source is AD_GROUP.
|
|
243
|
-
baker ads google query --preset bid-targets --customer-id 1234567890
|
|
244
|
-
|
|
245
241
|
# Include paused entities too (default is serving-only)
|
|
246
242
|
baker ads google query --preset ad-copy-performance --customer-id 1234567890 --include-paused
|
|
247
243
|
|
|
@@ -700,7 +696,7 @@ Command groups: `budgets`, `campaigns`, `ad-groups`, `keywords` (add/update/remo
|
|
|
700
696
|
|
|
701
697
|
**Retiring a conversion action** — `status` accepts `ENABLED` and `REMOVED` only. Google denies `HIDDEN` on every conversion-action write, so to stop bidding toward an action while it keeps measuring use `--no-primary`, and to stop it counting at all use `"status": "REMOVED"`. Conversion actions **Google owns** cannot be changed at all — Smart campaign call/directions actions, the in-ad lead form's submit, YouTube subscriptions and follow-on views, Floodlight and Search Ads 360 imports, store visits, codeless webpage actions. Staging any edit to one, a rename included, is refused up front; there is no manual route either, since the Google Ads interface will not change them.
|
|
702
698
|
|
|
703
|
-
**Reviewing the draft** — `baker ads google draft list` renders everything you've staged as a grouped campaign ▸ ad group ▸ ad tree (with non-blocking completeness advisories), the CLI counterpart to the dashboard's Google Ads tab. Pass `--json` for the raw envelope. Once the chat has published it reports the outcome instead — `published · N applied, M failed`, with a `✗` line naming each op that did not land and why
|
|
699
|
+
**Reviewing the draft** — `baker ads google draft list` renders everything you've staged as a grouped campaign ▸ ad group ▸ ad tree (with non-blocking completeness advisories), the CLI counterpart to the dashboard's Google Ads tab. Pass `--json` for the raw envelope. Once the chat has published it reports the outcome instead — `published · N applied, M failed`, with a `✗` line naming each op that did not land and why — and every row reads what Google did and the status it left, `Created · Paused`, `Failed to create` or `Created · Enabled · 1 change failed` when a keyword under it did not land, where before publish it reads `Creating · Paused`. Aim for a fully built campaign — 2–4 ad groups, ≥5 keywords each, 2–4 RSAs with 8–12 headlines, ≥4 sitelinks / ≥3 callouts / ≥1 structured snippet, and ≥1 shared negative list; the advisories flag what's still thin.
|
|
704
700
|
|
|
705
701
|
**Amending a staged op** — `draft amend <ref> (--file patch.json | --patch '<json>')` merges a JSON patch into an already-staged op's payload (objects deep-merge, `null` deletes a key, arrays/scalars replace) and re-validates it in full. Always prefer this over removing and re-staging — it preserves the op's ref (so dependents don't break) and its position in the draft. `draft show <ref>` prints the full staged payload (including warnings/annotations) so you can verify a change looks right before publish.
|
|
706
702
|
|
package/dist/cli.js
CHANGED
|
@@ -3569,7 +3569,10 @@ var googleDraftStatusNodeSchema = z6.lazy(
|
|
|
3569
3569
|
existing: z6.boolean(),
|
|
3570
3570
|
collections: z6.array(googleDraftStatusCollectionSchema),
|
|
3571
3571
|
children: z6.array(googleDraftStatusNodeSchema),
|
|
3572
|
-
warnings: z6.array(z6.string()).optional()
|
|
3572
|
+
warnings: z6.array(z6.string()).optional(),
|
|
3573
|
+
result: googleDraftOpResultSchema.shape.status.optional(),
|
|
3574
|
+
foldedNotApplied: z6.object({ failed: z6.number(), skipped: z6.number() }).optional(),
|
|
3575
|
+
status: z6.string().optional()
|
|
3573
3576
|
})
|
|
3574
3577
|
);
|
|
3575
3578
|
var googleDraftListResponseSchema = z6.object({
|
|
@@ -9184,13 +9187,6 @@ var FIELD_DESCRIPTIONS = {
|
|
|
9184
9187
|
"ad_group.name": "Ad group display name",
|
|
9185
9188
|
"ad_group.status": "ENABLED, PAUSED, or REMOVED",
|
|
9186
9189
|
"ad_group.type": "Ad group type (SEARCH_STANDARD, DISPLAY_STANDARD, etc.)",
|
|
9187
|
-
"ad_group.target_roas": "This ad group's own target ROAS (ratio), overriding its campaign's and portfolio's; 0 or omitted = none",
|
|
9188
|
-
"ad_group.effective_target_roas": "The target ROAS this ad group actually bids to, from whichever level sets it",
|
|
9189
|
-
"ad_group.effective_target_roas_source": "Which level the effective target ROAS comes from: AD_GROUP (its own \u2014 a campaign or portfolio change does not reach it) or CAMPAIGN_BIDDING_STRATEGY (the campaign's strategy, its own or a portfolio)",
|
|
9190
|
-
"ad_group.target_cpa_micros": "This ad group's own target CPA in micros, overriding its campaign's and portfolio's; 0 or omitted = none",
|
|
9191
|
-
"ad_group.effective_target_cpa_micros": "The target CPA (micros) this ad group actually bids to",
|
|
9192
|
-
"ad_group.effective_target_cpa_source": "Which level the effective target CPA comes from: AD_GROUP (its own \u2014 a campaign or portfolio change does not reach it) or CAMPAIGN_BIDDING_STRATEGY (the campaign's strategy, its own or a portfolio)",
|
|
9193
|
-
"campaign.bidding_strategy": "Resource name of the portfolio bidding strategy the campaign uses; blank = its own strategy",
|
|
9194
9190
|
// Ad group ad
|
|
9195
9191
|
"ad_group_ad.ad.id": "Unique ad identifier",
|
|
9196
9192
|
"ad_group_ad.ad.final_urls": "Landing page URLs (array)",
|
|
@@ -11048,14 +11044,44 @@ var OPERATION_LABELS = {
|
|
|
11048
11044
|
update: "Updating",
|
|
11049
11045
|
pause: "Pausing",
|
|
11050
11046
|
resume: "Resuming",
|
|
11051
|
-
remove: "Removing"
|
|
11047
|
+
remove: "Removing",
|
|
11048
|
+
upload: "Uploading"
|
|
11052
11049
|
};
|
|
11053
|
-
|
|
11054
|
-
|
|
11055
|
-
|
|
11056
|
-
|
|
11050
|
+
var APPLIED_LABELS = {
|
|
11051
|
+
create: "Created",
|
|
11052
|
+
update: "Updated",
|
|
11053
|
+
pause: "Paused",
|
|
11054
|
+
resume: "Resumed",
|
|
11055
|
+
remove: "Removed",
|
|
11056
|
+
upload: "Uploaded"
|
|
11057
|
+
};
|
|
11058
|
+
function notAppliedText(node) {
|
|
11059
|
+
const { failed = 0, skipped = 0 } = node.foldedNotApplied ?? {};
|
|
11060
|
+
const changes = (n) => `${n} change${n === 1 ? "" : "s"}`;
|
|
11061
|
+
const parts = [
|
|
11062
|
+
...failed > 0 ? [`${changes(failed)} failed`] : [],
|
|
11063
|
+
...skipped > 0 ? [`${changes(skipped)} skipped`] : []
|
|
11064
|
+
];
|
|
11065
|
+
return parts.length > 0 ? parts.join(", ") : void 0;
|
|
11066
|
+
}
|
|
11067
|
+
function outcomeBadge(node, result) {
|
|
11068
|
+
const verb = node.operation ?? "update";
|
|
11069
|
+
if (result === "applied") {
|
|
11070
|
+
return node.operation ? APPLIED_LABELS[verb] ?? "Applied" : "Changes applied";
|
|
11057
11071
|
}
|
|
11058
|
-
|
|
11072
|
+
if (result === "simulated") {
|
|
11073
|
+
return `Simulated (${verb})`;
|
|
11074
|
+
}
|
|
11075
|
+
if (result === "failed") {
|
|
11076
|
+
return node.operation ? `Failed to ${verb}` : "Failed";
|
|
11077
|
+
}
|
|
11078
|
+
return "Skipped";
|
|
11079
|
+
}
|
|
11080
|
+
function badge(node) {
|
|
11081
|
+
const label = node.result ? outcomeBadge(node, node.result) : (node.operation ? OPERATION_LABELS[node.operation] : void 0) ?? (node.existing ? "on Google Ads" : "staged");
|
|
11082
|
+
const parts = [label, ...node.status && node.status !== label ? [node.status] : []];
|
|
11083
|
+
const notApplied = notAppliedText(node);
|
|
11084
|
+
return [...parts, ...notApplied ? [notApplied] : []].join(" \xB7 ");
|
|
11059
11085
|
}
|
|
11060
11086
|
function collectionLine(collection) {
|
|
11061
11087
|
const parts = [];
|
|
@@ -11454,7 +11480,7 @@ var draftCommand2 = defineCommand22({
|
|
|
11454
11480
|
list: defineCommand22({
|
|
11455
11481
|
meta: {
|
|
11456
11482
|
name: "list",
|
|
11457
|
-
description: "Review everything staged as a campaign \u25B8 ad group \u25B8 ad tree (--json for the raw envelope)"
|
|
11483
|
+
description: "Review everything staged as a campaign \u25B8 ad group \u25B8 ad tree, each row with its status; after publish each row says what Google did (Created / Failed to create) (--json for the raw envelope)"
|
|
11458
11484
|
},
|
|
11459
11485
|
args: {
|
|
11460
11486
|
json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable tree" },
|
|
@@ -12044,18 +12070,6 @@ var PRESETS = [
|
|
|
12044
12070
|
defaultLimit: 200,
|
|
12045
12071
|
statusFields: ["campaign.status"]
|
|
12046
12072
|
},
|
|
12047
|
-
{
|
|
12048
|
-
// A target resolves ad group > campaign > portfolio strategy, so the campaign's or the portfolio's
|
|
12049
|
-
// number is not necessarily the one bidding. `effective_target_*_source` names the level that is;
|
|
12050
|
-
// a change staged anywhere else is inert for that ad group. Undated on purpose: an ad group that
|
|
12051
|
-
// spent nothing in the window still carries its own target, and a dated read would drop its row.
|
|
12052
|
-
name: "bid-targets",
|
|
12053
|
-
description: "Which target each ad group actually bids to \u2014 its own target ROAS / CPA, the effective one and the level it comes from. Read it before changing any target: a campaign or portfolio change does not reach an ad group whose source is AD_GROUP",
|
|
12054
|
-
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, campaign.bidding_strategy_type, campaign.bidding_strategy, ad_group.id, ad_group.name, ad_group.status, ad_group.target_roas, ad_group.effective_target_roas, ad_group.effective_target_roas_source, ad_group.target_cpa_micros, ad_group.effective_target_cpa_micros, ad_group.effective_target_cpa_source FROM ad_group WHERE campaign.bidding_strategy_type IN ('TARGET_ROAS', 'TARGET_CPA', 'MAXIMIZE_CONVERSION_VALUE', 'MAXIMIZE_CONVERSIONS'){statusScope} ORDER BY campaign.name LIMIT {limit}`,
|
|
12055
|
-
defaultDateRange: "ALL_TIME",
|
|
12056
|
-
defaultLimit: 200,
|
|
12057
|
-
statusFields: ["campaign.status", "ad_group.status"]
|
|
12058
|
-
},
|
|
12059
12073
|
{
|
|
12060
12074
|
name: "conversions-by-action",
|
|
12061
12075
|
description: "Which conversion action each campaign's conversions actually are \u2014 the read that says whether two campaigns' conversion rates are measuring the same event",
|