@koda-sl/baker-cli 0.255.0 → 0.256.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 +4 -0
- package/dist/cli.js +44 -7
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5843,6 +5843,10 @@ Pushing to `main` with changes in `packages/cli/` triggers the GitHub Actions wo
|
|
|
5843
5843
|
|
|
5844
5844
|
Three more things the 202608 pin brought with it. **The conversion-type enum went from 8 values to all 34 LinkedIn accepts** — `QUALIFIED_LEAD`, `BOOK_APPOINTMENT`, `SUBMIT_APPLICATION` and 23 others were rejected by our own schema before the request ever left, and 202608 adds `MARKETING_QUALIFIED_LEAD` / `SALES_QUALIFIED_LEAD` on top. **Attribution windows gained 365** (and view-through gained 90), with the type-conditional rule enforced on `conversions create`: 365 is only legal for `SUBMIT_APPLICATION`, `PURCHASE`, `ADD_TO_CART`, `QUALIFIED_LEAD`, `LEAD`. And **a 429 carrying `SEGMENT_LIMIT_EXCEEDED` is no longer reported as a throttle** — 202608 caps an ad account at 1,000 DMP segments and reuses the rate-limit status for it, so an agent that read it as "retry in a second" would have retried forever against a cap only a human can clear in Campaign Manager.
|
|
5845
5845
|
|
|
5846
|
+
- **0.256.0**: **`assets attach` no longer offers an image link, because Google accepts none.** A production publish came back with six `AssetLinkError.FIELD_TYPE_INCOMPATIBLE_WITH_CAMPAIGN_TYPE` rows (trigger `MARKETING_IMAGE,SEARCH`) on an otherwise built and live Search campaign — staged exactly as this CLI's own advisory and the scaffold's ads-google doc instructed, at `"fieldType": "MARKETING_IMAGE"`. The obvious fix was `AD_IMAGE`, which is what Google's documentation and its own forum answers name for a Search image extension. **It does not work either.** Sent to a real account on v23, all four combinations are refused: `MARKETING_IMAGE` on a Search `CampaignAsset` → `FIELD_TYPE_INCOMPATIBLE_WITH_CAMPAIGN_TYPE`; `MARKETING_IMAGE` on a Search `AdGroupAsset` → `UNSUPPORTED_FIELD_TYPE`; `AD_IMAGE` on a `CampaignAsset` → `UNSUPPORTED_FIELD_TYPE`; `AD_IMAGE` on an `AdGroupAsset` → `UNSUPPORTED_FIELD_TYPE`. Image extensions never moved to asset-based extensions, so there is no request the API takes. Every image field type is now refused at the CLI boundary with the interface named instead of another field type to try, and the **"recommend at least 3 image assets" advisory is removed** — it had been firing on every Search campaign since 0.191.0 and could not be satisfied by any draft, because the write it named has never once succeeded. Performance Max asset-group images are a different mechanism and are untouched (`asset-groups attach`). Four force-synced scaffold surfaces were saying the same wrong thing and now agree with the API: the `ads-google.md` tool doc, the `assets` command group description, the account-audit playbook's Dynamic Images row, and `staged-writes.md`. An audit should still raise a missing-images gap — it is a real SERP disadvantage — it just has to name the Google Ads interface as the fix rather than a command.
|
|
5847
|
+
|
|
5848
|
+
- **0.256.0**: a structured snippet value over 25 characters is refused before it is staged. Google caps each VALUE at 25 and answers a longer one with a bare `Too long.` at `structured_snippet_asset.values[i]` — no header, no value, nothing to act on — and it takes the asset's campaign link down with it as `RESOURCE_NOT_FOUND`. `assets create --values` and `assets update --values` now cap each entry; the per-asset 3-10 count check was already there, and only the per-value length was missing. Found on a live publish where four of five values were fine and "Bases de datos vectoriales" (26) was not, and confirmed fixed by re-publishing the same snippet at 25 characters against a real account, where it applied and linked cleanly.
|
|
5849
|
+
|
|
5846
5850
|
### Testing a pre-release in sandboxes
|
|
5847
5851
|
|
|
5848
5852
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -2113,7 +2113,14 @@ var GOOGLE_ADS_LIMITS = {
|
|
|
2113
2113
|
// Google's published headers (`structured-snippet-headers.ts`), the longest
|
|
2114
2114
|
// of which is 29 characters. Only the values are capped.
|
|
2115
2115
|
structuredSnippetValuesMin: 3,
|
|
2116
|
-
structuredSnippetValuesMax: 10
|
|
2116
|
+
structuredSnippetValuesMax: 10,
|
|
2117
|
+
/**
|
|
2118
|
+
* Per VALUE, not per asset. Google rejects a 26-character value with a bare "Too long." at
|
|
2119
|
+
* `structured_snippet_asset.values[i]` — one red row inside an otherwise clean publish, plus
|
|
2120
|
+
* every link that depends on the asset. Confirmed live on v23: "Bases de datos vectoriales"
|
|
2121
|
+
* (26) rejected, its four neighbours accepted.
|
|
2122
|
+
*/
|
|
2123
|
+
structuredSnippetValueMax: 25
|
|
2117
2124
|
},
|
|
2118
2125
|
conversionAction: {
|
|
2119
2126
|
nameMax: 255
|
|
@@ -2296,9 +2303,24 @@ var ASSET_FIELD_TYPES = [
|
|
|
2296
2303
|
"HEADLINE",
|
|
2297
2304
|
"DESCRIPTION",
|
|
2298
2305
|
"LOGO",
|
|
2306
|
+
/**
|
|
2307
|
+
* Kept because a draft staged before {@link IMAGE_ASSET_LINK_MESSAGE} shipped may still carry one,
|
|
2308
|
+
* and because it is the field type an asset-group image occupies. It is refused on an
|
|
2309
|
+
* `assetLink.attach` — see that message for what Google actually does with it.
|
|
2310
|
+
*/
|
|
2299
2311
|
"MARKETING_IMAGE",
|
|
2300
2312
|
"BUSINESS_NAME"
|
|
2301
2313
|
];
|
|
2314
|
+
var IMAGE_ASSET_LINK_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
2315
|
+
"MARKETING_IMAGE",
|
|
2316
|
+
"SQUARE_MARKETING_IMAGE",
|
|
2317
|
+
"PORTRAIT_MARKETING_IMAGE",
|
|
2318
|
+
"AD_IMAGE"
|
|
2319
|
+
]);
|
|
2320
|
+
var IMAGE_ASSET_LINK_MESSAGE = "Google does not accept an image through an asset link. MARKETING_IMAGE is a Performance Max asset-group slot (use `asset-groups attach`), and AD_IMAGE \u2014 the field type Google names for a Search image extension \u2014 comes back UNSUPPORTED_FIELD_TYPE at campaign and ad group level alike. Image extensions are not reachable through the API: tell the user to add them in the Google Ads interface, and carry on with the rest of the job.";
|
|
2321
|
+
function isImageAssetLinkFieldType(fieldType) {
|
|
2322
|
+
return IMAGE_ASSET_LINK_FIELD_TYPES.has(fieldType);
|
|
2323
|
+
}
|
|
2302
2324
|
var ASSET_GROUP_ASSET_FIELD_TYPES = [
|
|
2303
2325
|
"MARKETING_IMAGE",
|
|
2304
2326
|
"SQUARE_MARKETING_IMAGE",
|
|
@@ -3151,7 +3173,7 @@ var structuredSnippetHeaderSchema = z4.string().min(1).transform((header, ctx) =
|
|
|
3151
3173
|
var structuredSnippetAssetSchema = z4.object({
|
|
3152
3174
|
type: z4.literal("structuredSnippet"),
|
|
3153
3175
|
header: structuredSnippetHeaderSchema,
|
|
3154
|
-
values: z4.array(z4.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax)
|
|
3176
|
+
values: z4.array(z4.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValueMax)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax)
|
|
3155
3177
|
});
|
|
3156
3178
|
var callToActionAssetSchema = z4.object({ type: z4.literal("callToAction"), callToAction: z4.string().min(1) });
|
|
3157
3179
|
var assetCreateSchema = z4.discriminatedUnion("type", [
|
|
@@ -3171,7 +3193,7 @@ var assetUpdateSchema = z4.object({
|
|
|
3171
3193
|
finalUrls: z4.array(httpsUrlSchema2).min(1).optional(),
|
|
3172
3194
|
calloutText: z4.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax).optional(),
|
|
3173
3195
|
header: structuredSnippetHeaderSchema.optional(),
|
|
3174
|
-
values: z4.array(z4.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax).optional(),
|
|
3196
|
+
values: z4.array(z4.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValueMax)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax).optional(),
|
|
3175
3197
|
callToAction: z4.string().min(1).optional(),
|
|
3176
3198
|
text: z4.string().min(1).optional()
|
|
3177
3199
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
@@ -3179,7 +3201,11 @@ var assetLinkAttachSchema = z4.object({
|
|
|
3179
3201
|
level: z4.enum(["campaign", "adGroup", "customer"]),
|
|
3180
3202
|
parent: refSchema.optional(),
|
|
3181
3203
|
asset: refSchema,
|
|
3182
|
-
|
|
3204
|
+
// A plain string, not `z.enum(ASSET_FIELD_TYPES)`, so the image refusal below can answer with
|
|
3205
|
+
// the reason instead of an enum listing. An agent reaching for AD_IMAGE is following Google's
|
|
3206
|
+
// own documentation; "Invalid option: expected one of …" sends it to guess another field type,
|
|
3207
|
+
// which is the failure this whole refusal exists to end.
|
|
3208
|
+
fieldType: z4.string().min(1)
|
|
3183
3209
|
}).superRefine((value, ctx) => {
|
|
3184
3210
|
if (value.level !== "customer" && !value.parent) {
|
|
3185
3211
|
ctx.addIssue({
|
|
@@ -3188,6 +3214,15 @@ var assetLinkAttachSchema = z4.object({
|
|
|
3188
3214
|
message: `parent is required for a ${value.level}-level asset link (--parent-ref)`
|
|
3189
3215
|
});
|
|
3190
3216
|
}
|
|
3217
|
+
if (isImageAssetLinkFieldType(value.fieldType)) {
|
|
3218
|
+
ctx.addIssue({ code: z4.ZodIssueCode.custom, path: ["fieldType"], message: IMAGE_ASSET_LINK_MESSAGE });
|
|
3219
|
+
} else if (!ASSET_FIELD_TYPES.includes(value.fieldType)) {
|
|
3220
|
+
ctx.addIssue({
|
|
3221
|
+
code: z4.ZodIssueCode.custom,
|
|
3222
|
+
path: ["fieldType"],
|
|
3223
|
+
message: `expected one of ${ASSET_FIELD_TYPES.join(" | ")}`
|
|
3224
|
+
});
|
|
3225
|
+
}
|
|
3191
3226
|
});
|
|
3192
3227
|
var assetGroupCreateSchema = z4.object({
|
|
3193
3228
|
campaign: refSchema,
|
|
@@ -14861,7 +14896,7 @@ var assetsUpdateCommand = defineCommand30({
|
|
|
14861
14896
|
"final-urls": { type: "string", description: "Comma-separated sitelink final URLs" },
|
|
14862
14897
|
"callout-text": { type: "string", description: "Callout text" },
|
|
14863
14898
|
header: { type: "string", description: "Structured snippet header" },
|
|
14864
|
-
values: { type: "string", description: "Comma-separated structured snippet values" },
|
|
14899
|
+
values: { type: "string", description: "Comma-separated structured snippet values (3-10, max 25 characters each)" },
|
|
14865
14900
|
cta: { type: "string", description: "Call-to-action text" },
|
|
14866
14901
|
text: { type: "string", description: "Text asset content" }
|
|
14867
14902
|
},
|
|
@@ -14886,7 +14921,7 @@ var assetsUpdateCommand = defineCommand30({
|
|
|
14886
14921
|
var assetsCommand = defineCommand30({
|
|
14887
14922
|
meta: {
|
|
14888
14923
|
name: "assets",
|
|
14889
|
-
description: "Stage asset create/update + asset-link attach/detach (via --file). For a high-performance Search campaign add \u22654 sitelinks, \u22653 callouts
|
|
14924
|
+
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. Images are not among them: Google refuses every image asset link, so image extensions have to be added in the Google Ads interface."
|
|
14890
14925
|
},
|
|
14891
14926
|
subCommands: {
|
|
14892
14927
|
create: fileCreateCommand(
|
|
@@ -14895,7 +14930,9 @@ var assetsCommand = defineCommand30({
|
|
|
14895
14930
|
"Stage an asset (text/image/sitelink/callout/structuredSnippet/\u2026)"
|
|
14896
14931
|
),
|
|
14897
14932
|
update: assetsUpdateCommand,
|
|
14898
|
-
attach: fileCreateCommand("attach", "google.assetLink.attach", "Attach an asset to a campaign/adGroup/customer"
|
|
14933
|
+
attach: fileCreateCommand("attach", "google.assetLink.attach", "Attach an asset to a campaign/adGroup/customer", [
|
|
14934
|
+
"Images are not attachable here at all \u2014 Google refuses every image field type through an asset link, at every level. Image extensions have to be added in the Google Ads interface; say so and carry on. Performance Max asset-group images are a different mechanism and do work (`asset-groups attach`)."
|
|
14935
|
+
]),
|
|
14899
14936
|
detach: statusCommand2("google.assetLink.detach", "asset link")
|
|
14900
14937
|
}
|
|
14901
14938
|
});
|