@koda-sl/baker-cli 0.434.0 → 0.436.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 CHANGED
@@ -621,6 +621,18 @@ baker ads google campaigns create --customer-id 1234567890 --name "Brand — Sea
621
621
  # New campaigns are declared as NOT containing EU political advertising (Google requires the
622
622
  # declaration on every create); pass --eu-political-ads only when the campaign does contain it.
623
623
  # On update, --eu-political-ads / --eu-political-ads=false corrects an existing declaration.
624
+ # Text guidelines (AI Max Search and Performance Max) stage on update only:
625
+ baker ads google campaigns update <campaign-id> --customer-id 1234567890 \
626
+ --term-exclusion "cheap" --messaging-restriction "Never promise a delivery date"
627
+ # --term-exclusion (repeatable, up to 25 × 30 chars) and --messaging-restriction (repeatable,
628
+ # up to 40 × 300 chars) each REPLACE the campaign's list; --clear-term-exclusions /
629
+ # --clear-messaging-restrictions empty one. A Search campaign needs AI Max with text
630
+ # customization on (in the same update or before), or staging is refused with the reason.
631
+ # AI Max for Search stages on create and update: --ai-max / --ai-max=false (off turns both
632
+ # features off too), --ai-max-text (text customization, needs AI Max) and
633
+ # --ai-max-url-expansion (final URL expansion, needs text customization). An omitted switch
634
+ # keeps the campaign's value; a combination Google refuses is refused at staging.
635
+ baker ads google campaigns update <campaign-id> --customer-id 1234567890 --ai-max --ai-max-text
624
636
  baker ads google ad-groups create --customer-id 1234567890 --name "Brand terms" --campaign-ref g_temp_<campaign>
625
637
  baker ads google keywords add --customer-id 1234567890 --ad-group-ref g_temp_<adgroup> --text "brand name" --match-type EXACT
626
638
  # Shared negative keyword list → attach to the campaign
@@ -1171,7 +1183,8 @@ baker ads linkedin bid-pricing --account-id 503001492 \
1171
1183
  **`analytics`** — the 3-axis workhorse:
1172
1184
  - `--level account` (override: `campaign-group|campaign|creative`)
1173
1185
  - `--intent baseline` field bundle. Intents: `baseline | revenue | funnel | engagement | video | lead-gen | inmail | document | ranking | identity`. List with `--list-intents`.
1174
- - `--pivot none`. Pivots: `none | campaign | campaign-group | creative | company | account | conversion | job-title | job-function | seniority | industry | company-size | country | region | device | placement | serving-location | card-index | objective | conversation-node | conversation-node-button`. List with `--list-pivots`.
1186
+ - `--pivot none`. Pivots: `none | campaign | campaign-group | creative | company | account | conversion | job-title | job-function | seniority | industry | company-size | country | region | dma | device | placement | serving-location | card-index | objective | conversation-node | conversation-node-button`. List with `--list-pivots`.
1187
+ - `--pivot dma` — US Nielsen Designated Market Areas, with region names resolved. LinkedIn's terms: any report built from it writes "DMA®" each time and carries "DMA® is a registered service mark of The Nielsen Company." — the `DMA_ATTRIBUTION_REQUIRED` warning repeats this on every call.
1175
1188
  - `--granularity DAILY`. Auto-forced to `ALL` when pivoting on a `MEMBER_*` dim (LinkedIn rejects DAILY + demographic) — surfaced in stderr + `warnings`.
1176
1189
  - `--last-days 7` unless you pass `--start`/`--end`.
1177
1190
  - Sort: `costInUsd` descending. `--no-sort` to disable.
@@ -1277,6 +1290,8 @@ baker ads linkedin campaigns exclude-companies 123456 --segment urn:li:dmpSegmen
1277
1290
  # Conversions with playbook-default windows
1278
1291
  baker ads linkedin conversions create --name "Demo booked" --type LEAD --method INSIGHT_TAG \
1279
1292
  --post-click-window 30 --view-window 7
1293
+ # Windows are 1|7|30|90 days; 180 and 365 only for LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD,
1294
+ # SALES_QUALIFIED_LEAD, PURCHASE, ADD_TO_CART, SUBMIT_APPLICATION — refused at stage time otherwise
1280
1295
 
1281
1296
  # Safe duplication — stage-time read of the source → staged DRAFT create ("Duplicate ad", never "Link to original")
1282
1297
  baker ads linkedin campaigns duplicate 123456 --name "New variant"
package/dist/cli.js CHANGED
@@ -23868,11 +23868,11 @@ var LINKEDIN_LIMITS = {
23868
23868
  },
23869
23869
  conversion: {
23870
23870
  nameMax: 255,
23871
- // 365 is accepted only for the types in
23872
- // `CONVERSION_TYPES_ALLOWING_365_DAY_WINDOW`; enforced cross-field in
23871
+ // 180 and 365 are accepted only for the types in
23872
+ // `CONVERSION_TYPES_ALLOWING_LONG_WINDOWS`; enforced cross-field in
23873
23873
  // `conversionCreateSchema`, since the enum alone cannot express it.
23874
- postClickWindows: [1, 7, 30, 90, 365],
23875
- viewThroughWindows: [1, 7, 30, 90, 365]
23874
+ postClickWindows: [1, 7, 30, 90, 180, 365],
23875
+ viewThroughWindows: [1, 7, 30, 90, 180, 365]
23876
23876
  },
23877
23877
  leadForm: {
23878
23878
  nameMax: 256,
@@ -24006,12 +24006,14 @@ var CONVERSION_TYPES = [
24006
24006
  "VIEW_CONTENT",
24007
24007
  "VIEW_VIDEO"
24008
24008
  ];
24009
- var CONVERSION_TYPES_ALLOWING_365_DAY_WINDOW = [
24009
+ var CONVERSION_TYPES_ALLOWING_LONG_WINDOWS = [
24010
24010
  "SUBMIT_APPLICATION",
24011
24011
  "PURCHASE",
24012
24012
  "ADD_TO_CART",
24013
24013
  "QUALIFIED_LEAD",
24014
- "LEAD"
24014
+ "LEAD",
24015
+ "MARKETING_QUALIFIED_LEAD",
24016
+ "SALES_QUALIFIED_LEAD"
24015
24017
  ];
24016
24018
  var CONVERSION_METHODS = ["INSIGHT_TAG", "CONVERSIONS_API"];
24017
24019
  var ATTRIBUTION_TYPES = ["LAST_TOUCH_BY_CAMPAIGN", "LAST_TOUCH_BY_CONVERSION"];
@@ -24610,13 +24612,14 @@ var conversionCreateSchema = z7.object({
24610
24612
  urlMatchRuleExpression: z7.array(z7.array(z7.record(z7.string(), z7.string()))).optional(),
24611
24613
  associateAllCampaigns: z7.boolean().optional()
24612
24614
  }).superRefine((p, ctx) => {
24613
- const allowed365 = CONVERSION_TYPES_ALLOWING_365_DAY_WINDOW.includes(p.type);
24615
+ const allowsLong = CONVERSION_TYPES_ALLOWING_LONG_WINDOWS.includes(p.type);
24614
24616
  for (const field of ["postClickAttributionWindowSize", "viewThroughAttributionWindowSize"]) {
24615
- if (p[field] === 365 && !allowed365) {
24617
+ const days = p[field];
24618
+ if (days !== void 0 && days > 90 && !allowsLong) {
24616
24619
  ctx.addIssue({
24617
24620
  code: "custom",
24618
24621
  path: [field],
24619
- message: `a 365-day window is only available for ${CONVERSION_TYPES_ALLOWING_365_DAY_WINDOW.join(", ")} \u2014 ${p.type} caps at 90`
24622
+ message: `a ${days}-day window is only available for ${CONVERSION_TYPES_ALLOWING_LONG_WINDOWS.join(", ")} \u2014 ${p.type} caps at 90`
24620
24623
  });
24621
24624
  }
24622
24625
  }
@@ -24891,7 +24894,13 @@ var GOOGLE_ADS_LIMITS = {
24891
24894
  /** `campaign.url_custom_parameters` — Google caps a single entity at 8 `{_name}` parameters. */
24892
24895
  urlCustomParametersMax: 8,
24893
24896
  urlCustomParameterKeyMax: 16,
24894
- urlCustomParameterValueMax: 250
24897
+ urlCustomParameterValueMax: 250,
24898
+ /** `campaign.text_guidelines.term_exclusions` — words AI Max and Performance Max must never write. */
24899
+ termExclusionsMax: 25,
24900
+ termExclusionMax: 30,
24901
+ /** `campaign.text_guidelines.messaging_restrictions` — freeform rules for generated text. */
24902
+ messagingRestrictionsMax: 40,
24903
+ messagingRestrictionMax: 300
24895
24904
  },
24896
24905
  adGroup: {
24897
24906
  nameMax: 255
@@ -25873,6 +25882,49 @@ var geoTargetTypeSettingSchema = z9.strictObject({
25873
25882
  (p) => p.positiveGeoTargetType !== void 0 || p.negativeGeoTargetType !== void 0,
25874
25883
  "geoTargetTypeSetting needs positiveGeoTargetType and/or negativeGeoTargetType"
25875
25884
  );
25885
+ var textGuidelinesSchema = z9.strictObject({
25886
+ termExclusions: z9.array(z9.string().trim().min(1).max(GOOGLE_ADS_LIMITS.campaign.termExclusionMax)).max(GOOGLE_ADS_LIMITS.campaign.termExclusionsMax).optional(),
25887
+ messagingRestrictions: z9.array(z9.string().trim().min(1).max(GOOGLE_ADS_LIMITS.campaign.messagingRestrictionMax)).max(GOOGLE_ADS_LIMITS.campaign.messagingRestrictionsMax).refine(
25888
+ (rules) => new Set(rules.map((rule) => rule.toLowerCase())).size === rules.length,
25889
+ "each messaging restriction must be unique"
25890
+ ).optional()
25891
+ }).refine(
25892
+ (p) => p.termExclusions !== void 0 || p.messagingRestrictions !== void 0,
25893
+ "textGuidelines needs termExclusions and/or messagingRestrictions"
25894
+ );
25895
+ var AI_MAX_TEXT_NEEDS_AI_MAX_MESSAGE = "AI Max text customization only works with AI Max on: also turn AI Max on, or leave text customization off.";
25896
+ var AI_MAX_URL_NEEDS_TEXT_MESSAGE = "AI Max final URL expansion only works with text customization on: also turn text customization on, or leave URL expansion off.";
25897
+ var aiMaxSchema = z9.strictObject({
25898
+ enabled: z9.boolean().optional(),
25899
+ textCustomization: z9.boolean().optional(),
25900
+ finalUrlExpansion: z9.boolean().optional()
25901
+ }).superRefine((p, ctx) => {
25902
+ if (p.enabled === void 0 && p.textCustomization === void 0 && p.finalUrlExpansion === void 0) {
25903
+ ctx.addIssue({ code: "custom", message: "aiMax needs enabled, textCustomization and/or finalUrlExpansion" });
25904
+ }
25905
+ if (p.enabled === false && p.textCustomization === true) {
25906
+ ctx.addIssue({ code: "custom", path: ["textCustomization"], message: AI_MAX_TEXT_NEEDS_AI_MAX_MESSAGE });
25907
+ }
25908
+ if (p.textCustomization === false && p.finalUrlExpansion === true) {
25909
+ ctx.addIssue({ code: "custom", path: ["finalUrlExpansion"], message: AI_MAX_URL_NEEDS_TEXT_MESSAGE });
25910
+ }
25911
+ });
25912
+ var AI_MAX_SEARCH_ONLY_MESSAGE = "AI Max exists only on Search campaigns.";
25913
+ function aiMaxCreateRefusal(channelType, aiMax) {
25914
+ if (!aiMax) {
25915
+ return void 0;
25916
+ }
25917
+ if (channelType !== "SEARCH") {
25918
+ return AI_MAX_SEARCH_ONLY_MESSAGE;
25919
+ }
25920
+ if (aiMax.enabled !== true && aiMax.textCustomization === true) {
25921
+ return AI_MAX_TEXT_NEEDS_AI_MAX_MESSAGE;
25922
+ }
25923
+ if (aiMax.textCustomization !== true && aiMax.finalUrlExpansion === true) {
25924
+ return AI_MAX_URL_NEEDS_TEXT_MESSAGE;
25925
+ }
25926
+ return void 0;
25927
+ }
25876
25928
  var campaignCreateSchema2 = z9.strictObject({
25877
25929
  name: z9.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax),
25878
25930
  channelType: z9.enum(ADVERTISING_CHANNEL_TYPES),
@@ -25902,6 +25954,8 @@ var campaignCreateSchema2 = z9.strictObject({
25902
25954
  * every campaign create (FieldError.REQUIRED without it); omitted means it does not.
25903
25955
  */
25904
25956
  euPoliticalAds: z9.boolean().optional(),
25957
+ /** AI Max for Search. A new campaign has it off unless this turns it on. */
25958
+ aiMax: aiMaxSchema.optional(),
25905
25959
  status: stageableStatusSchema2.default("PAUSED")
25906
25960
  }).superRefine((p, ctx) => {
25907
25961
  if (!p.bidding && !p.biddingStrategy) {
@@ -25928,6 +25982,10 @@ var campaignCreateSchema2 = z9.strictObject({
25928
25982
  if (p.startDate && p.endDate && p.endDate <= p.startDate) {
25929
25983
  ctx.addIssue({ code: "custom", path: ["endDate"], message: "endDate must be after startDate" });
25930
25984
  }
25985
+ const aiMaxRefusal = aiMaxCreateRefusal(p.channelType, p.aiMax);
25986
+ if (aiMaxRefusal) {
25987
+ ctx.addIssue({ code: "custom", path: ["aiMax"], message: aiMaxRefusal });
25988
+ }
25931
25989
  });
25932
25990
  var campaignUpdateSchema2 = z9.strictObject({
25933
25991
  name: z9.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax).optional(),
@@ -25946,6 +26004,10 @@ var campaignUpdateSchema2 = z9.strictObject({
25946
26004
  urlCustomParameters: urlCustomParametersSchema.optional(),
25947
26005
  /** Corrects the campaign's EU political advertising declaration (true = contains, false = does not). */
25948
26006
  euPoliticalAds: z9.boolean().optional(),
26007
+ /** AI Max / Performance Max text guidelines. Google refuses them on a Search campaign without AI Max. */
26008
+ textGuidelines: textGuidelinesSchema.optional(),
26009
+ /** Turns AI Max or its features on or off. Search campaigns only (checked against the live channel). */
26010
+ aiMax: aiMaxSchema.optional(),
25949
26011
  status: z9.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
25950
26012
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
25951
26013
  var adGroupCreateSchema = z9.strictObject({
@@ -49037,6 +49099,74 @@ function urlCustomParametersFromFlags(args8, rawArgs) {
49037
49099
  return { key: entry.slice(0, split), value: entry.slice(split + 1) };
49038
49100
  });
49039
49101
  }
49102
+ var aiMaxArgs = {
49103
+ "ai-max": {
49104
+ type: "boolean",
49105
+ description: "AI Max for Search: --ai-max turns it on (Google then matches searches beyond your keywords), --ai-max=false turns it off along with its text customization and URL expansion. Search campaigns only."
49106
+ },
49107
+ "ai-max-text": {
49108
+ type: "boolean",
49109
+ description: "AI Max text customization: --ai-max-text lets Google write ad text from your landing page and ads (needs AI Max on); --ai-max-text=false stops it. Required before text guidelines."
49110
+ },
49111
+ "ai-max-url-expansion": {
49112
+ type: "boolean",
49113
+ description: "AI Max final URL expansion: --ai-max-url-expansion lets Google send clicks to the most relevant page of your site (needs text customization on); --ai-max-url-expansion=false keeps every click on your final URLs."
49114
+ }
49115
+ };
49116
+ function aiMaxFromFlags(args8) {
49117
+ const flag2 = (name) => typeof args8[name] === "boolean" ? args8[name] : void 0;
49118
+ const aiMax = {
49119
+ enabled: flag2("ai-max"),
49120
+ textCustomization: flag2("ai-max-text"),
49121
+ finalUrlExpansion: flag2("ai-max-url-expansion")
49122
+ };
49123
+ const stated = Object.entries(aiMax).filter(([, v]) => v !== void 0);
49124
+ return stated.length > 0 ? Object.fromEntries(stated) : void 0;
49125
+ }
49126
+ var textGuidelinesArgs = {
49127
+ "term-exclusion": {
49128
+ type: "string",
49129
+ description: `Text guidelines (AI Max Search and Performance Max): a word or phrase Google's generated ad text must never use, up to 30 characters (e.g. --term-exclusion "cheap"). Repeat for several; Google allows 25. REPLACES the campaign's whole list.`
49130
+ },
49131
+ "messaging-restriction": {
49132
+ type: "string",
49133
+ description: `Text guidelines (AI Max Search and Performance Max): a plain-language rule for Google's generated ad text, up to 300 characters (e.g. --messaging-restriction "Never promise a delivery date"). Repeat for several; Google allows 40. REPLACES the campaign's whole list.`
49134
+ },
49135
+ "clear-term-exclusions": {
49136
+ type: "boolean",
49137
+ description: "Remove every term exclusion from this campaign's text guidelines."
49138
+ },
49139
+ "clear-messaging-restrictions": {
49140
+ type: "boolean",
49141
+ description: "Remove every messaging restriction from this campaign's text guidelines."
49142
+ }
49143
+ };
49144
+ function guidelineListFromFlags(args8, rawArgs, flag2, clearFlag) {
49145
+ const values = repeatedValues(rawArgs, flag2, args8[flag2]).filter((v) => v.length > 0);
49146
+ if (values.length === 0) {
49147
+ return args8[clearFlag] === true ? [] : void 0;
49148
+ }
49149
+ if (args8[clearFlag] === true) {
49150
+ failWriteValidation2(`--${clearFlag} removes the whole list \u2014 pass it OR --${flag2}, not both`);
49151
+ }
49152
+ return values;
49153
+ }
49154
+ function textGuidelinesFromFlags(args8, rawArgs) {
49155
+ const termExclusions = guidelineListFromFlags(args8, rawArgs, "term-exclusion", "clear-term-exclusions");
49156
+ const messagingRestrictions = guidelineListFromFlags(
49157
+ args8,
49158
+ rawArgs,
49159
+ "messaging-restriction",
49160
+ "clear-messaging-restrictions"
49161
+ );
49162
+ if (termExclusions === void 0 && messagingRestrictions === void 0) {
49163
+ return void 0;
49164
+ }
49165
+ return {
49166
+ ...termExclusions !== void 0 ? { termExclusions } : {},
49167
+ ...messagingRestrictions !== void 0 ? { messagingRestrictions } : {}
49168
+ };
49169
+ }
49040
49170
  var geoTargetTypeArgs = {
49041
49171
  "geo-target-type": {
49042
49172
  type: "string",
@@ -49188,6 +49318,7 @@ var campaignsCommand3 = defineCommand57({
49188
49318
  ...urlOptionsArgs,
49189
49319
  ...geoTargetTypeArgs,
49190
49320
  ...networksArg,
49321
+ ...aiMaxArgs,
49191
49322
  objective: { type: "string", description: "Advisory UI objective (SALES, LEADS, \u2026)" },
49192
49323
  "start-date": { type: "string", description: "YYYY-MM-DD" },
49193
49324
  "end-date": { type: "string", description: "YYYY-MM-DD" },
@@ -49214,6 +49345,7 @@ var campaignsCommand3 = defineCommand57({
49214
49345
  startDate: args8["start-date"],
49215
49346
  endDate: args8["end-date"],
49216
49347
  euPoliticalAds: args8["eu-political-ads"],
49348
+ aiMax: aiMaxFromFlags(args8),
49217
49349
  status: args8.status
49218
49350
  });
49219
49351
  await stageCreate("google.campaign.create", customerId, payload, [
@@ -49225,7 +49357,7 @@ var campaignsCommand3 = defineCommand57({
49225
49357
  update: defineCommand57({
49226
49358
  meta: {
49227
49359
  name: "update",
49228
- description: `Stage a change to an existing campaign's name, budget, bidding or settings. ${STAGED_WRITE}`
49360
+ description: `Stage a change to an existing campaign's name, budget, bidding, settings, AI Max switches or text guidelines (what AI Max and Performance Max ad text must avoid). ${STAGED_WRITE}`
49229
49361
  },
49230
49362
  args: {
49231
49363
  ...customerIdArg,
@@ -49253,6 +49385,8 @@ var campaignsCommand3 = defineCommand57({
49253
49385
  ...urlOptionsArgs,
49254
49386
  ...geoTargetTypeArgs,
49255
49387
  ...networksArg,
49388
+ ...textGuidelinesArgs,
49389
+ ...aiMaxArgs,
49256
49390
  "eu-political-ads": {
49257
49391
  type: "boolean",
49258
49392
  description: "Corrects the campaign's EU political advertising declaration: --eu-political-ads if it contains EU political ads, --eu-political-ads=false if it does not. Existing campaigns without a declaration block location-targeting changes until one is set."
@@ -49283,6 +49417,8 @@ var campaignsCommand3 = defineCommand57({
49283
49417
  trackingUrlTemplate: args8["tracking-template"],
49284
49418
  urlCustomParameters: urlCustomParametersFromFlags(args8, rawArgs),
49285
49419
  euPoliticalAds: args8["eu-political-ads"],
49420
+ textGuidelines: textGuidelinesFromFlags(args8, rawArgs),
49421
+ aiMax: aiMaxFromFlags(args8),
49286
49422
  status: args8.status
49287
49423
  });
49288
49424
  await stageUpdate("google.campaign.update", customerId, target2, payload);
@@ -51079,6 +51215,7 @@ registerSchema({
51079
51215
  "company-size",
51080
51216
  "country",
51081
51217
  "region",
51218
+ "dma",
51082
51219
  "device",
51083
51220
  "placement",
51084
51221
  "serving-location",
@@ -51720,8 +51857,16 @@ registerSchema({
51720
51857
  required: true
51721
51858
  },
51722
51859
  method: { type: "string", description: "INSIGHT_TAG|CONVERSIONS_API", required: true },
51723
- "post-click-window": { type: "string", description: "1|7|30|90 days", required: false },
51724
- "view-window": { type: "string", description: "1|7|30 days", required: false },
51860
+ "post-click-window": {
51861
+ type: "string",
51862
+ description: "1|7|30|90 days; 180|365 only for LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD, SALES_QUALIFIED_LEAD, PURCHASE, ADD_TO_CART, SUBMIT_APPLICATION",
51863
+ required: false
51864
+ },
51865
+ "view-window": {
51866
+ type: "string",
51867
+ description: "1|7|30|90 days; 180|365 only for LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD, SALES_QUALIFIED_LEAD, PURCHASE, ADD_TO_CART, SUBMIT_APPLICATION",
51868
+ required: false
51869
+ },
51725
51870
  "attribution-type": {
51726
51871
  type: "string",
51727
51872
  description: "LAST_TOUCH_BY_CAMPAIGN|LAST_TOUCH_BY_CONVERSION",
@@ -51742,8 +51887,16 @@ registerSchema({
51742
51887
  id: { type: "positional", description: "Conversion rule id or URN", required: true },
51743
51888
  ...writeAccountArgs,
51744
51889
  name: { type: "string", description: "New name", required: false },
51745
- "post-click-window": { type: "string", description: "1|7|30|90 days", required: false },
51746
- "view-window": { type: "string", description: "1|7|30 days", required: false },
51890
+ "post-click-window": {
51891
+ type: "string",
51892
+ description: "1|7|30|90 days; 180|365 only for LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD, SALES_QUALIFIED_LEAD, PURCHASE, ADD_TO_CART, SUBMIT_APPLICATION",
51893
+ required: false
51894
+ },
51895
+ "view-window": {
51896
+ type: "string",
51897
+ description: "1|7|30|90 days; 180|365 only for LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD, SALES_QUALIFIED_LEAD, PURCHASE, ADD_TO_CART, SUBMIT_APPLICATION",
51898
+ required: false
51899
+ },
51747
51900
  "attribution-type": { type: "string", description: "New attribution type", required: false },
51748
51901
  enabled: { type: "string", description: "on|off", required: false },
51749
51902
  file: { type: "string", description: "JSON file with fields to change", required: false }
@@ -52588,8 +52741,14 @@ Example: baker ads linkedin conversions create --name "Demo booked" --type LEAD
52588
52741
  description: "Conversion type. Common: LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD, SALES_QUALIFIED_LEAD, SIGN_UP, DOWNLOAD, PURCHASE, KEY_PAGE_VIEW, ADD_TO_CART, BOOK_APPOINTMENT, SUBMIT_APPLICATION, OTHER \u2014 `baker schema ads.linkedin.conversions.create` lists all 34"
52589
52742
  },
52590
52743
  method: { type: "string", description: "INSIGHT_TAG|CONVERSIONS_API" },
52591
- "post-click-window": { type: "string", description: "1|7|30|90 days (playbook default 30)" },
52592
- "view-window": { type: "string", description: "1|7|30 days (playbook default 7)" },
52744
+ "post-click-window": {
52745
+ type: "string",
52746
+ description: "1|7|30|90 days (playbook default 30); 180|365 only for LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD, SALES_QUALIFIED_LEAD, PURCHASE, ADD_TO_CART, SUBMIT_APPLICATION"
52747
+ },
52748
+ "view-window": {
52749
+ type: "string",
52750
+ description: "1|7|30|90 days (playbook default 7); 180|365 only for LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD, SALES_QUALIFIED_LEAD, PURCHASE, ADD_TO_CART, SUBMIT_APPLICATION"
52751
+ },
52593
52752
  "attribution-type": { type: "string", description: "LAST_TOUCH_BY_CAMPAIGN|LAST_TOUCH_BY_CONVERSION" },
52594
52753
  "associate-all-campaigns": { type: "boolean", description: "Auto-associate with active campaigns" },
52595
52754
  file: { type: "string", description: "JSON file with the full payload (e.g. urlMatchRuleExpression)" }
@@ -52618,8 +52777,14 @@ Example: baker ads linkedin conversions update 104988516 --post-click-window 30
52618
52777
  id: { type: "positional", description: "Conversion rule id or URN", required: true },
52619
52778
  ...accountArgs,
52620
52779
  name: { type: "string", description: "New name" },
52621
- "post-click-window": { type: "string", description: "1|7|30|90 days" },
52622
- "view-window": { type: "string", description: "1|7|30 days" },
52780
+ "post-click-window": {
52781
+ type: "string",
52782
+ description: "1|7|30|90 days; 180|365 only for LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD, SALES_QUALIFIED_LEAD, PURCHASE, ADD_TO_CART, SUBMIT_APPLICATION"
52783
+ },
52784
+ "view-window": {
52785
+ type: "string",
52786
+ description: "1|7|30|90 days; 180|365 only for LEAD, QUALIFIED_LEAD, MARKETING_QUALIFIED_LEAD, SALES_QUALIFIED_LEAD, PURCHASE, ADD_TO_CART, SUBMIT_APPLICATION"
52787
+ },
52623
52788
  "attribution-type": { type: "string", description: "LAST_TOUCH_BY_CAMPAIGN|LAST_TOUCH_BY_CONVERSION" },
52624
52789
  enabled: { type: "string", description: "on|off" },
52625
52790
  file: { type: "string", description: "JSON file with fields to change" }
@@ -52965,7 +53130,8 @@ var MEMBER_PIVOTS = /* @__PURE__ */ new Set([
52965
53130
  "industry",
52966
53131
  "company-size",
52967
53132
  "country",
52968
- "region"
53133
+ "region",
53134
+ "dma"
52969
53135
  ]);
52970
53136
  var ALL_PIVOTS = [
52971
53137
  "none",
@@ -52982,6 +53148,7 @@ var ALL_PIVOTS = [
52982
53148
  "company-size",
52983
53149
  "country",
52984
53150
  "region",
53151
+ "dma",
52985
53152
  "device",
52986
53153
  "placement",
52987
53154
  "serving-location",
@@ -53119,7 +53286,7 @@ var analyticsCommand = defineCommand62({
53119
53286
  Three-axis design (LinkedIn's superpower over Meta/Google):
53120
53287
  --level account | campaign-group | campaign | creative
53121
53288
  --intent baseline | revenue | funnel | engagement | video | lead-gen | inmail | document | ranking | identity
53122
- --pivot none | job-title | company | industry | seniority | function | company-size | country | region
53289
+ --pivot none | job-title | company | industry | seniority | function | company-size | country | region | dma
53123
53290
  | device | placement | serving-location | card-index | objective
53124
53291
  | conversation-node | conversation-node-button
53125
53292
 
@@ -53127,6 +53294,8 @@ Smart defaults:
53127
53294
  --level account, --intent baseline, --pivot none, --granularity DAILY, last 7 days
53128
53295
  Pivot on a MEMBER_* dim \u2192 granularity auto-forced to ALL (LinkedIn rejects DAILY+demographic)
53129
53296
  Demographic data delayed 12-24h with \u22653-event privacy floor \u2014 the CLI flags this in warnings.
53297
+ --pivot dma \u2192 US Nielsen DMA\xAE regions, names resolved. Any report built from it must write "DMA\xAE"
53298
+ and carry Nielsen's notice (returned as the DMA_ATTRIBUTION_REQUIRED warning).
53130
53299
  Derived metrics injected client-side: ctr, cpc, cpm, frequency, leadCompletionRate
53131
53300
 
53132
53301
  Examples \u2014 common AI questions: