@koda-sl/baker-cli 0.290.3 → 0.291.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.
- package/README.md +3 -1
- package/dist/cli.js +4 -6
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -669,7 +669,7 @@ Command groups: `budgets`, `campaigns`, `ad-groups`, `keywords` (add/update/remo
|
|
|
669
669
|
|
|
670
670
|
**A device criterion can be added, but never removed** — `campaign-criteria add` with a device criterion works, but Google then rejects `campaign-criteria remove` on it forever, including on a criterion you added yourself (and Baker refuses the removal before publish). Adjust it instead with `campaign-criteria update customers/<cid>/campaignCriteria/<campaignId>~<criterionId> --bid-modifier <n>`: `1` for no adjustment, `1.25` to bid 25% more, `0.9` to bid 10% less, `0` to stop serving on that device. Locations, languages and ad schedules remove normally.
|
|
671
671
|
|
|
672
|
-
**Images on a Search campaign** — `assets create` with an image publishes it into the advertiser's Google Ads asset library, but Google refuses the asset link that puts an image extension on a Search campaign (`AD_IMAGE` and every marketing-image field type, at campaign, ad group and customer level alike), so `assets attach`
|
|
672
|
+
**Images on a Search campaign** — `assets create` with an image publishes it into the advertiser's Google Ads asset library, but Google refuses the asset link that puts an image extension on a Search campaign (`AD_IMAGE` and every marketing-image field type, at campaign, ad group and customer level alike), so `assets attach` **skips** it at stage time and names what to do instead — the op is never stored, the rest of a batch stages normally, and the skipped link is what records which images belong on which campaign. Staging an image, or asking to link one the account already holds, therefore also stages a **Task** — "Add N images to <campaign> in Google Ads" — which applies with the rest of the chat, so the one step Google keeps inside its own interface is tracked rather than mentioned. Attach the image to a Performance Max asset group (`asset-groups attach`) and the Task withdraws itself. The one image a Search campaign does take through a link is the advertiser's logo: `BUSINESS_LOGO`, at campaign or customer level, on a verified account.
|
|
673
673
|
|
|
674
674
|
**Primary vs secondary conversion actions** — `conversions update <id> --primary` makes an action a primary action (automated bidding optimizes toward it); `--no-primary` (or `--primary=false`) demotes it to secondary (reported only) — the spaced form `--primary false` is rejected, since a boolean flag written with a space is set to true and the word dropped. `conversions create` stages a new action as **secondary** unless its `--file` payload sets `"primaryForGoal": true`, so a new action never silently joins the bidding target of a Maximize Conversions or Target CPA campaign. The staged card shows an "Action optimization" row with the before/after role.
|
|
675
675
|
|
|
@@ -6017,6 +6017,8 @@ Pushing to `main` with changes in `packages/cli/` triggers the GitHub Actions wo
|
|
|
6017
6017
|
|
|
6018
6018
|
- **0.271.0**: **`--format demandGenVideo` — the Demand Gen ad most Demand Gen spend actually runs through can be edited.** A `DEMAND_GEN_VIDEO_RESPONSIVE_AD` keeps its copy in `demandGenVideoResponsiveAd`, which has a `longHeadlines` list no other ad format has and takes its business name as a text asset rather than a string. Baker modelled only the multi-asset Demand Gen ad and labelled all four Demand Gen types as one format, so every served video ad was uneditable: the strict content schema refused `longHeadlines` and named a field instead of a missing format, and the only route left was the Google Ads interface. On the account that surfaced it, Demand Gen was 76% of the spend. New flags on `ads create|update`: `--long-headlines` (up to 5 × 90 chars, this format only), `--video-assets`, `--logo-image-assets`, `--call-to-action-assets`; a create with no video is refused with the `assets create` call to make first, and an omitted media list on an update leaves that media on the ad. Two more gates ship with it. **A content flag a format does not read is now refused instead of dropped** — `--long-headlines` on `--format demandGen` staged the copy without them and reported success, the same silent-drop the backend's strict schemas exist to stop. And **the format is checked against the live `ad_group_ad.ad.type` when it stages**: a mismatch is refused with the right format named, and the two Demand Gen types Baker writes no format for (`DEMAND_GEN_CAROUSEL_AD`, `DEMAND_GEN_PRODUCT_AD`) are refused by name, so "Baker cannot edit this ad" arrives at stage time rather than as a publish failure a Session too late.
|
|
6019
6019
|
|
|
6020
|
+
- **0.291.0**: **the image handover Task no longer depends on having uploaded the images.** It was built only from staged `asset.create` image ops, so a Session that audited a live account — found the brand campaign carrying 22 image extensions and the generic one carrying none, and reached for `assets attach` on assets that were *already in the library* — got Google's refusal and nothing else: no upload to hang a Task on, and a CLI hint telling the agent not to raise one by hand because "Baker stages it itself". The one step only the user can take reached them as a sentence in a chat that scrolls away. An image `assets attach` is now **skipped rather than refused**: it still never reaches Google (re-verified live with `validate_only` on v23 *and* v25 against 3865083115, against a control op that validates clean in the same request — `AD_IMAGE` → `UNSUPPORTED_FIELD_TYPE` at customer and campaign level, `MARKETING_IMAGE` → `FIELD_TYPE_INCOMPATIBLE_WITH_CAMPAIGN_TYPE`, `BUSINESS_LOGO` → `CUSTOMER_NOT_VERIFIED`, which is what proves the field type is the objection; **we are not on Google's allowlist for it**), but the skip carries the image and campaign names, recorded on the draft so the next staged op cannot recompute the Task away, and a batch that also carries sitelinks keeps them instead of failing whole. The schema stopped refusing the field type for the same reason: a boundary refusal has no chat to record a handover against.
|
|
6021
|
+
|
|
6020
6022
|
### Testing a pre-release in sandboxes
|
|
6021
6023
|
|
|
6022
6024
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -2373,7 +2373,6 @@ var IMAGE_ASSET_LINK_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
|
2373
2373
|
"PORTRAIT_MARKETING_IMAGE",
|
|
2374
2374
|
"AD_IMAGE"
|
|
2375
2375
|
]);
|
|
2376
|
-
var IMAGE_ASSET_LINK_MESSAGE = "Google refuses the LINK, not the upload \u2014 so do not stop at this refusal, finish the handover. `assets create` with an image DOES publish: the image lands in the advertiser's Google Ads asset library and is theirs to use. Only this link is refused (MARKETING_IMAGE is a Performance Max asset-group slot \u2014 use `asset-groups attach`; AD_IMAGE comes back UNSUPPORTED_FIELD_TYPE at every level, on every API version). So: stage the image assets anyway, drop this link, and tell the user the images are already in their Google Ads account and only need adding to the campaign under Assets \u2014 name them. Baker stages the Task for that step itself, alongside the image, so it is already in this Session's changes \u2014 do not stage a second one with `baker actions`. Never tell them to upload the images; they are uploaded. The one image a Search campaign does take through a link is the advertiser's logo \u2014 BUSINESS_LOGO at campaign or customer level, on a verified account.";
|
|
2377
2376
|
function isImageAssetLinkFieldType(fieldType) {
|
|
2378
2377
|
return IMAGE_ASSET_LINK_FIELD_TYPES.has(fieldType);
|
|
2379
2378
|
}
|
|
@@ -3377,7 +3376,6 @@ var assetLinkAttachSchema = z5.object({
|
|
|
3377
3376
|
if (value.fieldType === "BUSINESS_LOGO" && value.level === "adGroup") {
|
|
3378
3377
|
ctx.addIssue({ code: z5.ZodIssueCode.custom, path: ["fieldType"], message: BUSINESS_LOGO_LEVEL_MESSAGE });
|
|
3379
3378
|
} else if (isImageAssetLinkFieldType(value.fieldType)) {
|
|
3380
|
-
ctx.addIssue({ code: z5.ZodIssueCode.custom, path: ["fieldType"], message: IMAGE_ASSET_LINK_MESSAGE });
|
|
3381
3379
|
} else if (!ASSET_FIELD_TYPES.includes(value.fieldType)) {
|
|
3382
3380
|
ctx.addIssue({
|
|
3383
3381
|
code: z5.ZodIssueCode.custom,
|
|
@@ -16575,8 +16573,8 @@ function imageAssetHints(payload) {
|
|
|
16575
16573
|
return [];
|
|
16576
16574
|
}
|
|
16577
16575
|
return [
|
|
16578
|
-
"This image publishes into the advertiser's Google Ads asset library \u2014 that half works. What Google refuses is the link that puts it on a Search campaign, so
|
|
16579
|
-
"Finish the handover rather than reporting a limitation: tell the user the images are already in their Google Ads account and only need adding to the campaign under Assets, and name the ones you staged. Baker stages the Task for that step itself the moment you stage the image, so it is already in this chat's changes \u2014 do not stage a second one with `baker actions`. Never tell them to upload images they already have. (A Performance Max asset group is different \u2014 images do link there, with `asset-groups attach`.)"
|
|
16576
|
+
"This image publishes into the advertiser's Google Ads asset library \u2014 that half works. What Google refuses is the link that puts it on a Search campaign, so the `assets attach` for it never stores: it is skipped with the reason, and staging it anyway is what tells Baker which campaign these images belong on.",
|
|
16577
|
+
"Finish the handover rather than reporting a limitation: tell the user the images are already in their Google Ads account and only need adding to the campaign under Assets, and name the ones you staged. Baker stages the Task for that step itself the moment you stage the image, so it is already in this chat's changes \u2014 do not stage a second one with `baker actions`. Stage the `assets attach` too if you know which campaign they belong on: it is skipped rather than stored, and it is what puts the campaign's name in that Task. Never tell them to upload images they already have. (A Performance Max asset group is different \u2014 images do link there, with `asset-groups attach`.)"
|
|
16580
16578
|
];
|
|
16581
16579
|
}
|
|
16582
16580
|
var assetsUpdateCommand = defineCommand31({
|
|
@@ -16619,7 +16617,7 @@ var assetsUpdateCommand = defineCommand31({
|
|
|
16619
16617
|
var assetsCommand = defineCommand31({
|
|
16620
16618
|
meta: {
|
|
16621
16619
|
name: "assets",
|
|
16622
|
-
description: "Stage asset create/update + asset-link attach/detach (via --file). For a high-performance Search campaign add \u22654 sitelinks, \u22653 callouts and \u22651 structured snippet per campaign. Image extensions are the one thing you cannot finish here \u2014 `create` uploads the image into the advertiser's account, but Google refuses the link that puts it on a Search campaign, so hand that one step over rather than telling them to upload anything. The image a Search campaign does take through a link is the advertiser's logo \u2014 BUSINESS_LOGO, at campaign or customer level, on a verified account."
|
|
16620
|
+
description: "Stage asset create/update + asset-link attach/detach (via --file). For a high-performance Search campaign add \u22654 sitelinks, \u22653 callouts and \u22651 structured snippet per campaign. Image extensions are the one thing you cannot finish here \u2014 `create` uploads the image into the advertiser's account, but Google refuses the link that puts it on a Search campaign, so hand that one step over rather than telling them to upload anything (stage the `attach` regardless: it is skipped, and it is what records the handover Task). The image a Search campaign does take through a link is the advertiser's logo \u2014 BUSINESS_LOGO, at campaign or customer level, on a verified account."
|
|
16623
16621
|
},
|
|
16624
16622
|
subCommands: {
|
|
16625
16623
|
create: fileCreateCommand(
|
|
@@ -16630,7 +16628,7 @@ var assetsCommand = defineCommand31({
|
|
|
16630
16628
|
),
|
|
16631
16629
|
update: assetsUpdateCommand,
|
|
16632
16630
|
attach: fileCreateCommand("attach", "google.assetLink.attach", "Attach an asset to a campaign/adGroup/customer", [
|
|
16633
|
-
"Image extensions
|
|
16631
|
+
"Image extensions cannot be linked \u2014 Google refuses AD_IMAGE and every marketing-image field type at every level, on every API version \u2014 but stage the link anyway: it is skipped rather than stored, the rest of a batch is unaffected, and it is what records the handover Task naming those images and that campaign. That is the ONLY record when the images are already in the account and you are uploading nothing. Then tell the user they are already in their Google Ads account and only need adding to the campaign under Assets; do not stage a second Task with `baker actions`. Two images that DO link: the advertiser's logo through this command (`BUSINESS_LOGO`, campaign or customer level, on a verified account), and Performance Max asset-group images, which are a different mechanism (`asset-groups attach`)."
|
|
16634
16632
|
]),
|
|
16635
16633
|
detach: statusCommand2("google.assetLink.detach", "asset link")
|
|
16636
16634
|
}
|