@koda-sl/baker-cli 0.26.0 → 0.27.1-dev.bcbc31f8

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.
Files changed (104) hide show
  1. package/README.md +146 -0
  2. package/dist/cli.js +1 -1
  3. package/dist/commands/actions/create.d.ts.map +1 -1
  4. package/dist/commands/actions/create.js +10 -2
  5. package/dist/commands/actions/create.js.map +1 -1
  6. package/dist/commands/ads/index.d.ts.map +1 -1
  7. package/dist/commands/ads/index.js +7 -3
  8. package/dist/commands/ads/index.js.map +1 -1
  9. package/dist/commands/ads/linkedin/account.d.ts +20 -0
  10. package/dist/commands/ads/linkedin/account.d.ts.map +1 -0
  11. package/dist/commands/ads/linkedin/account.js +39 -0
  12. package/dist/commands/ads/linkedin/account.js.map +1 -0
  13. package/dist/commands/ads/linkedin/accounts.d.ts +20 -0
  14. package/dist/commands/ads/linkedin/accounts.d.ts.map +1 -0
  15. package/dist/commands/ads/linkedin/accounts.js +56 -0
  16. package/dist/commands/ads/linkedin/accounts.js.map +1 -0
  17. package/dist/commands/ads/linkedin/analytics.d.ts +84 -0
  18. package/dist/commands/ads/linkedin/analytics.d.ts.map +1 -0
  19. package/dist/commands/ads/linkedin/analytics.js +249 -0
  20. package/dist/commands/ads/linkedin/analytics.js.map +1 -0
  21. package/dist/commands/ads/linkedin/audience-size.d.ts +28 -0
  22. package/dist/commands/ads/linkedin/audience-size.d.ts.map +1 -0
  23. package/dist/commands/ads/linkedin/audience-size.js +75 -0
  24. package/dist/commands/ads/linkedin/audience-size.js.map +1 -0
  25. package/dist/commands/ads/linkedin/audit.d.ts +35 -0
  26. package/dist/commands/ads/linkedin/audit.d.ts.map +1 -0
  27. package/dist/commands/ads/linkedin/audit.js +136 -0
  28. package/dist/commands/ads/linkedin/audit.js.map +1 -0
  29. package/dist/commands/ads/linkedin/bid-pricing.d.ts +38 -0
  30. package/dist/commands/ads/linkedin/bid-pricing.d.ts.map +1 -0
  31. package/dist/commands/ads/linkedin/bid-pricing.js +76 -0
  32. package/dist/commands/ads/linkedin/bid-pricing.js.map +1 -0
  33. package/dist/commands/ads/linkedin/campaign-groups.d.ts +32 -0
  34. package/dist/commands/ads/linkedin/campaign-groups.d.ts.map +1 -0
  35. package/dist/commands/ads/linkedin/campaign-groups.js +50 -0
  36. package/dist/commands/ads/linkedin/campaign-groups.js.map +1 -0
  37. package/dist/commands/ads/linkedin/campaigns.d.ts +36 -0
  38. package/dist/commands/ads/linkedin/campaigns.d.ts.map +1 -0
  39. package/dist/commands/ads/linkedin/campaigns.js +57 -0
  40. package/dist/commands/ads/linkedin/campaigns.js.map +1 -0
  41. package/dist/commands/ads/linkedin/conversation.d.ts +36 -0
  42. package/dist/commands/ads/linkedin/conversation.d.ts.map +1 -0
  43. package/dist/commands/ads/linkedin/conversation.js +77 -0
  44. package/dist/commands/ads/linkedin/conversation.js.map +1 -0
  45. package/dist/commands/ads/linkedin/conversions.d.ts +2 -0
  46. package/dist/commands/ads/linkedin/conversions.d.ts.map +1 -0
  47. package/dist/commands/ads/linkedin/conversions.js +102 -0
  48. package/dist/commands/ads/linkedin/conversions.js.map +1 -0
  49. package/dist/commands/ads/linkedin/creatives.d.ts +36 -0
  50. package/dist/commands/ads/linkedin/creatives.d.ts.map +1 -0
  51. package/dist/commands/ads/linkedin/creatives.js +57 -0
  52. package/dist/commands/ads/linkedin/creatives.js.map +1 -0
  53. package/dist/commands/ads/linkedin/demographics.d.ts +40 -0
  54. package/dist/commands/ads/linkedin/demographics.d.ts.map +1 -0
  55. package/dist/commands/ads/linkedin/demographics.js +117 -0
  56. package/dist/commands/ads/linkedin/demographics.js.map +1 -0
  57. package/dist/commands/ads/linkedin/facets.d.ts +2 -0
  58. package/dist/commands/ads/linkedin/facets.d.ts.map +1 -0
  59. package/dist/commands/ads/linkedin/facets.js +95 -0
  60. package/dist/commands/ads/linkedin/facets.js.map +1 -0
  61. package/dist/commands/ads/linkedin/forecast.d.ts +50 -0
  62. package/dist/commands/ads/linkedin/forecast.d.ts.map +1 -0
  63. package/dist/commands/ads/linkedin/forecast.js +83 -0
  64. package/dist/commands/ads/linkedin/forecast.js.map +1 -0
  65. package/dist/commands/ads/linkedin/index.d.ts +19 -0
  66. package/dist/commands/ads/linkedin/index.d.ts.map +1 -0
  67. package/dist/commands/ads/linkedin/index.js +83 -0
  68. package/dist/commands/ads/linkedin/index.js.map +1 -0
  69. package/dist/commands/ads/linkedin/leads.d.ts +40 -0
  70. package/dist/commands/ads/linkedin/leads.d.ts.map +1 -0
  71. package/dist/commands/ads/linkedin/leads.js +75 -0
  72. package/dist/commands/ads/linkedin/leads.js.map +1 -0
  73. package/dist/commands/ads/linkedin/presets.d.ts +40 -0
  74. package/dist/commands/ads/linkedin/presets.d.ts.map +1 -0
  75. package/dist/commands/ads/linkedin/presets.js +193 -0
  76. package/dist/commands/ads/linkedin/presets.js.map +1 -0
  77. package/dist/commands/ads/linkedin/presets.test.d.ts +2 -0
  78. package/dist/commands/ads/linkedin/presets.test.d.ts.map +1 -0
  79. package/dist/commands/ads/linkedin/presets.test.js +98 -0
  80. package/dist/commands/ads/linkedin/presets.test.js.map +1 -0
  81. package/dist/commands/ads/linkedin/schemas.d.ts +2 -0
  82. package/dist/commands/ads/linkedin/schemas.d.ts.map +1 -0
  83. package/dist/commands/ads/linkedin/schemas.js +300 -0
  84. package/dist/commands/ads/linkedin/schemas.js.map +1 -0
  85. package/dist/commands/ads/linkedin/shared.d.ts +17 -0
  86. package/dist/commands/ads/linkedin/shared.d.ts.map +1 -0
  87. package/dist/commands/ads/linkedin/shared.js +116 -0
  88. package/dist/commands/ads/linkedin/shared.js.map +1 -0
  89. package/dist/commands/ads/linkedin/top-companies.d.ts +44 -0
  90. package/dist/commands/ads/linkedin/top-companies.d.ts.map +1 -0
  91. package/dist/commands/ads/linkedin/top-companies.js +86 -0
  92. package/dist/commands/ads/linkedin/top-companies.js.map +1 -0
  93. package/dist/env.d.ts +1 -0
  94. package/dist/env.d.ts.map +1 -1
  95. package/dist/env.js +4 -0
  96. package/dist/env.js.map +1 -1
  97. package/dist/error-handler.d.ts +1 -1
  98. package/dist/error-handler.d.ts.map +1 -1
  99. package/dist/error-handler.js +3 -0
  100. package/dist/error-handler.js.map +1 -1
  101. package/dist/output.d.ts +1 -0
  102. package/dist/output.d.ts.map +1 -1
  103. package/dist/output.js.map +1 -1
  104. package/package.json +1 -1
@@ -0,0 +1,40 @@
1
+ export declare const demographicsCommand: import("citty").CommandDef<{
2
+ readonly "campaign-id": {
3
+ readonly type: "string";
4
+ readonly description: "Comma-separated campaign IDs (required)";
5
+ };
6
+ readonly pivots: {
7
+ readonly type: "string";
8
+ readonly description: `CSV of pivots (default: ${string})`;
9
+ };
10
+ readonly "top-n": {
11
+ readonly type: "string";
12
+ readonly description: "Top rows per pivot (default: 10)";
13
+ };
14
+ readonly intent: {
15
+ readonly type: "string";
16
+ readonly description: "baseline | revenue | funnel | engagement | lead-gen (default: baseline)";
17
+ };
18
+ readonly start: {
19
+ readonly type: "string";
20
+ readonly description: "Start date YYYY-MM-DD";
21
+ };
22
+ readonly end: {
23
+ readonly type: "string";
24
+ readonly description: "End date YYYY-MM-DD";
25
+ };
26
+ readonly "last-days": {
27
+ readonly type: "string";
28
+ readonly description: "Window relative to today (default: 30)";
29
+ };
30
+ readonly "skip-cache": {
31
+ readonly type: "boolean";
32
+ readonly description: "Bypass server-side cache";
33
+ };
34
+ readonly output: {
35
+ readonly type: "string";
36
+ readonly description: "json";
37
+ readonly default: "json";
38
+ };
39
+ }>;
40
+ //# sourceMappingURL=demographics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demographics.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/demographics.ts"],"names":[],"mappings":"AA6CA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0F9B,CAAC"}
@@ -0,0 +1,117 @@
1
+ import { defineCommand } from "citty";
2
+ import { apiPost } from "../../../client.js";
3
+ import { writeAdsJson } from "../output.js";
4
+ import { csvOrJson, daysAgoIso, handleLinkedinError, todayIso } from "./shared.js";
5
+ const DEFAULT_PIVOTS = ["job-title", "company", "industry", "seniority", "job-function", "company-size"];
6
+ function numberOf(v) {
7
+ if (typeof v === "number")
8
+ return Number.isFinite(v) ? v : 0;
9
+ if (typeof v === "string") {
10
+ const n = Number(v);
11
+ return Number.isFinite(n) ? n : 0;
12
+ }
13
+ return 0;
14
+ }
15
+ function topByImpressions(rows, limit) {
16
+ return [...rows].sort((a, b) => numberOf(b.impressions) - numberOf(a.impressions)).slice(0, limit);
17
+ }
18
+ export const demographicsCommand = defineCommand({
19
+ meta: {
20
+ name: "demographics",
21
+ description: `Sweep all firmographic pivots in one command — LinkedIn's superpower.
22
+
23
+ Default pivots:
24
+ job-title, company, industry, seniority, job-function, company-size
25
+
26
+ Use --pivots to narrow the sweep. Output is one section per pivot, each with
27
+ top-N rows by impressions (configurable via --top-n).
28
+
29
+ Demographic data is delayed 12-24h with a ≥3-event privacy floor — small
30
+ buckets are silently dropped. The CLI surfaces this in 'warnings' when the
31
+ result set comes back unexpectedly empty.
32
+
33
+ Examples:
34
+ baker ads linkedin demographics --campaign-id 1234
35
+ baker ads linkedin demographics --campaign-id 1234 --pivots job-title,company
36
+ baker ads linkedin demographics --campaign-id 1234 --last-days 30 --top-n 25`,
37
+ },
38
+ args: {
39
+ "campaign-id": { type: "string", description: "Comma-separated campaign IDs (required)" },
40
+ pivots: { type: "string", description: `CSV of pivots (default: ${DEFAULT_PIVOTS.join(",")})` },
41
+ "top-n": { type: "string", description: "Top rows per pivot (default: 10)" },
42
+ intent: { type: "string", description: "baseline | revenue | funnel | engagement | lead-gen (default: baseline)" },
43
+ start: { type: "string", description: "Start date YYYY-MM-DD" },
44
+ end: { type: "string", description: "End date YYYY-MM-DD" },
45
+ "last-days": { type: "string", description: "Window relative to today (default: 30)" },
46
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
47
+ output: { type: "string", description: "json", default: "json" },
48
+ },
49
+ run: async ({ args }) => {
50
+ const fmt = csvOrJson(args);
51
+ if (fmt !== "json") {
52
+ writeAdsJson({
53
+ ok: false,
54
+ error: {
55
+ code: "UNSUPPORTED_FORMAT",
56
+ message: "demographics returns a structured per-pivot report — only --output json supported.",
57
+ },
58
+ });
59
+ process.exit(1);
60
+ }
61
+ const campaignIdsRaw = args["campaign-id"];
62
+ if (!campaignIdsRaw) {
63
+ handleLinkedinError(new Error("--campaign-id is required (CSV for multi)."));
64
+ }
65
+ const ids = campaignIdsRaw
66
+ .split(",")
67
+ .map((s) => s.trim())
68
+ .filter(Boolean);
69
+ const pivotsRaw = args.pivots?.split(",").map((s) => s.trim().toLowerCase());
70
+ const pivots = (pivotsRaw && pivotsRaw.length > 0 ? pivotsRaw : DEFAULT_PIVOTS);
71
+ const topN = args["top-n"] ? Number(args["top-n"]) : 10;
72
+ const intent = args.intent ?? "baseline";
73
+ const { start, end } = resolveRange(args);
74
+ try {
75
+ const results = [];
76
+ for (const pivot of pivots) {
77
+ const data = await apiPost("/api/ads/linkedin/analytics", {
78
+ request: {
79
+ level: "campaign",
80
+ ids,
81
+ intent,
82
+ pivot,
83
+ start,
84
+ end,
85
+ granularity: "ALL",
86
+ limit: 500,
87
+ },
88
+ skipCache: Boolean(args["skip-cache"]),
89
+ });
90
+ results.push({ pivot, rows: topByImpressions(data.rows, topN), warnings: data.warnings });
91
+ }
92
+ writeAdsJson({
93
+ ok: true,
94
+ data: {
95
+ query: { campaigns: ids, start, end, intent, topN },
96
+ pivots: results,
97
+ },
98
+ });
99
+ }
100
+ catch (err) {
101
+ handleLinkedinError(err);
102
+ }
103
+ },
104
+ });
105
+ function resolveRange(args) {
106
+ const start = args.start;
107
+ const end = args.end;
108
+ if (start) {
109
+ return { start, end };
110
+ }
111
+ const days = args["last-days"] ? Number(args["last-days"]) : 30;
112
+ if (!Number.isFinite(days) || days < 1) {
113
+ handleLinkedinError(new Error("Invalid --last-days; must be a positive integer."));
114
+ }
115
+ return { start: daysAgoIso(days), end: todayIso() };
116
+ }
117
+ //# sourceMappingURL=demographics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demographics.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/demographics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const facetsCommand: import("citty").CommandDef<import("citty").ArgsDef>;
2
+ //# sourceMappingURL=facets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facets.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/facets.ts"],"names":[],"mappings":"AA4FA,eAAO,MAAM,aAAa,qDAcxB,CAAC"}
@@ -0,0 +1,95 @@
1
+ import { defineCommand } from "citty";
2
+ import { apiGet } from "../../../client.js";
3
+ import { writeAdsJson, writeAdsOutput } from "../output.js";
4
+ import { csvOrJson, handleLinkedinError } from "./shared.js";
5
+ const listCmd = defineCommand({
6
+ meta: {
7
+ name: "list",
8
+ description: `List every targeting facet LinkedIn supports.
9
+
10
+ Cached 7 days. Use this to discover what dimensions you can target on (industries,
11
+ seniorities, titles, employers, growthRate, companyCategory, skills, etc.).`,
12
+ },
13
+ args: {
14
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
15
+ output: { type: "string", description: "json|csv|jsonl|md", default: "json" },
16
+ },
17
+ run: async ({ args }) => {
18
+ try {
19
+ const params = {};
20
+ if (args["skip-cache"])
21
+ params["skip-cache"] = "true";
22
+ const data = await apiGet("/api/ads/linkedin/facets", params);
23
+ const fmt = csvOrJson(args);
24
+ if (fmt !== "json") {
25
+ writeAdsOutput(data, fmt);
26
+ return;
27
+ }
28
+ writeAdsJson({ ok: true, data });
29
+ }
30
+ catch (err) {
31
+ handleLinkedinError(err);
32
+ }
33
+ },
34
+ });
35
+ const valuesCmd = defineCommand({
36
+ meta: {
37
+ name: "values",
38
+ description: `Look up entity values for a single facet — full list or typeahead search.
39
+
40
+ Examples:
41
+ baker ads linkedin facets values --facet seniorities — all seniority URNs
42
+ baker ads linkedin facets values --facet titles --query "marketing director" — typeahead
43
+ baker ads linkedin facets values --facet industries --output csv
44
+
45
+ The --facet flag accepts the bare name (industries, seniorities, titles, etc.)
46
+ or the full URN (urn:li:adTargetingFacet:industries).`,
47
+ },
48
+ args: {
49
+ facet: { type: "string", description: "Facet name (e.g. industries) or URN", required: true },
50
+ query: { type: "string", description: "Typeahead query (auto-switches finder to typeahead)" },
51
+ finder: { type: "string", description: "adTargetingFacet | typeahead | similarEntities (default: auto)" },
52
+ locale: { type: "string", description: "Locale (default: en_US)" },
53
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
54
+ output: { type: "string", description: "json|csv|jsonl|md", default: "json" },
55
+ },
56
+ run: async ({ args }) => {
57
+ try {
58
+ const params = { facet: String(args.facet) };
59
+ const finder = args.finder ?? (args.query ? "typeahead" : "adTargetingFacet");
60
+ params.finder = finder;
61
+ if (args.query)
62
+ params.query = String(args.query);
63
+ if (args.locale)
64
+ params.locale = String(args.locale);
65
+ if (args["skip-cache"])
66
+ params["skip-cache"] = "true";
67
+ const data = await apiGet("/api/ads/linkedin/facets/entities", params);
68
+ const fmt = csvOrJson(args);
69
+ if (fmt !== "json") {
70
+ writeAdsOutput(data, fmt);
71
+ return;
72
+ }
73
+ writeAdsJson({ ok: true, data });
74
+ }
75
+ catch (err) {
76
+ handleLinkedinError(err);
77
+ }
78
+ },
79
+ });
80
+ export const facetsCommand = defineCommand({
81
+ meta: {
82
+ name: "facets",
83
+ description: `LinkedIn targeting facets and entity lookup.
84
+
85
+ Subcommands:
86
+ list — every facet (industries, seniorities, titles, employers, …)
87
+ values --facet titles — entity URNs for one facet
88
+ values --facet titles --query "marketing director" — typeahead`,
89
+ },
90
+ subCommands: {
91
+ list: listCmd,
92
+ values: valuesCmd,
93
+ },
94
+ });
95
+ //# sourceMappingURL=facets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facets.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/facets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ export declare const forecastCommand: import("citty").CommandDef<{
2
+ readonly "account-id": {
3
+ readonly type: "string";
4
+ readonly description: "Numeric account ID or urn:li:sponsoredAccount:N";
5
+ };
6
+ readonly "account-urn": {
7
+ readonly type: "string";
8
+ readonly description: "Alias for --account-id";
9
+ };
10
+ readonly objective: {
11
+ readonly type: "string";
12
+ readonly description: "Objective type";
13
+ readonly required: true;
14
+ };
15
+ readonly "cost-type": {
16
+ readonly type: "string";
17
+ readonly description: "CPC | CPM | CPV | CPS";
18
+ readonly required: true;
19
+ };
20
+ readonly "daily-budget": {
21
+ readonly type: "string";
22
+ readonly description: "e.g. '200 USD' or '200'";
23
+ };
24
+ readonly "total-budget": {
25
+ readonly type: "string";
26
+ readonly description: "e.g. '6000 USD'";
27
+ };
28
+ readonly bid: {
29
+ readonly type: "string";
30
+ readonly description: "Bid e.g. '8 USD'";
31
+ };
32
+ readonly targeting: {
33
+ readonly type: "string";
34
+ readonly description: "Inline JSON targetingCriteria";
35
+ };
36
+ readonly "targeting-file": {
37
+ readonly type: "string";
38
+ readonly description: "Path to JSON file with targetingCriteria";
39
+ };
40
+ readonly "skip-cache": {
41
+ readonly type: "boolean";
42
+ readonly description: "Bypass server-side cache";
43
+ };
44
+ readonly output: {
45
+ readonly type: "string";
46
+ readonly description: "json";
47
+ readonly default: "json";
48
+ };
49
+ }>;
50
+ //# sourceMappingURL=forecast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/forecast.ts"],"names":[],"mappings":"AA+CA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4C1B,CAAC"}
@@ -0,0 +1,83 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { defineCommand } from "citty";
3
+ import { apiPost } from "../../../client.js";
4
+ import { writeAdsJson } from "../output.js";
5
+ import { handleLinkedinError, resolveAccountIdArg } from "./shared.js";
6
+ function loadTargeting(args) {
7
+ const inline = args.targeting;
8
+ if (inline) {
9
+ try {
10
+ return JSON.parse(inline);
11
+ }
12
+ catch {
13
+ handleLinkedinError(new Error("--targeting must be valid JSON."));
14
+ }
15
+ }
16
+ const file = args["targeting-file"];
17
+ if (file) {
18
+ try {
19
+ return JSON.parse(readFileSync(file, "utf-8"));
20
+ }
21
+ catch (e) {
22
+ handleLinkedinError(new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`));
23
+ }
24
+ }
25
+ handleLinkedinError(new Error("Pass --targeting-file <path> or --targeting '{...JSON...}'"));
26
+ }
27
+ function parseMoney(raw) {
28
+ if (!raw)
29
+ return undefined;
30
+ // Accept either "100 USD" or just "100" (defaults to USD).
31
+ const m = /^(\d+(?:\.\d+)?)(?:\s+([A-Z]{3}))?$/.exec(raw.trim());
32
+ if (!m) {
33
+ handleLinkedinError(new Error(`Invalid money "${raw}". Use "100" or "100 EUR".`));
34
+ }
35
+ return { amount: m[1] ?? "0", currencyCode: m[2] ?? "USD" };
36
+ }
37
+ export const forecastCommand = defineCommand({
38
+ meta: {
39
+ name: "forecast",
40
+ description: `Forecast reach + impressions + clicks + spend for a hypothetical campaign.
41
+
42
+ Wraps /rest/adSupplyForecasts. Useful for greenfield (§14) — answers
43
+ "if we launch with this budget + targeting + objective, what's the expected delivery?"
44
+
45
+ Examples:
46
+ baker ads linkedin forecast --account-id 503001492 --objective LEAD_GENERATION --cost-type CPC \\
47
+ --daily-budget "200 USD" --bid "8 USD" --targeting-file targeting.json`,
48
+ },
49
+ args: {
50
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
51
+ "account-urn": { type: "string", description: "Alias for --account-id" },
52
+ objective: { type: "string", description: "Objective type", required: true },
53
+ "cost-type": { type: "string", description: "CPC | CPM | CPV | CPS", required: true },
54
+ "daily-budget": { type: "string", description: "e.g. '200 USD' or '200'" },
55
+ "total-budget": { type: "string", description: "e.g. '6000 USD'" },
56
+ bid: { type: "string", description: "Bid e.g. '8 USD'" },
57
+ targeting: { type: "string", description: "Inline JSON targetingCriteria" },
58
+ "targeting-file": { type: "string", description: "Path to JSON file with targetingCriteria" },
59
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
60
+ output: { type: "string", description: "json", default: "json" },
61
+ },
62
+ run: async ({ args }) => {
63
+ const accountId = resolveAccountIdArg(args);
64
+ const targetingCriteria = loadTargeting(args);
65
+ try {
66
+ const data = await apiPost("/api/ads/linkedin/forecast", {
67
+ accountId,
68
+ objectiveType: String(args.objective),
69
+ costType: String(args["cost-type"]).toUpperCase(),
70
+ targetingCriteria,
71
+ dailyBudget: parseMoney(args["daily-budget"]),
72
+ totalBudget: parseMoney(args["total-budget"]),
73
+ bid: parseMoney(args.bid),
74
+ skipCache: Boolean(args["skip-cache"]),
75
+ });
76
+ writeAdsJson({ ok: true, data });
77
+ }
78
+ catch (err) {
79
+ handleLinkedinError(err);
80
+ }
81
+ },
82
+ });
83
+ //# sourceMappingURL=forecast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forecast.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/forecast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import "./schemas.ts";
2
+ /**
3
+ * LinkedIn Ads CLI — designed around LinkedIn's distinguishing strength:
4
+ * firmographic (per-job-title, per-company, per-industry, per-seniority)
5
+ * pivots on adAnalytics. AI agents should reach for `linkedin analytics
6
+ * --pivot job-title` and `--pivot company` when answering ABM/persona
7
+ * questions — Meta and Google can't do that.
8
+ *
9
+ * Read-only v1. All analytics queries default to `--level account --intent
10
+ * baseline --granularity DAILY --last-days 7`. When pivoting on a MEMBER_*
11
+ * dimension, the CLI auto-forces granularity=ALL (LinkedIn rejects
12
+ * DAILY + demographic) and surfaces a "demographic delayed 12-24h" warning.
13
+ *
14
+ * Authentication: requires the LinkedIn integration to be connected in the
15
+ * dashboard with `r_ads` and `r_ads_reporting` scopes. CLI talks to Baker's
16
+ * backend, which holds the OAuth token.
17
+ */
18
+ export declare const linkedinCommand: import("citty").CommandDef<import("citty").ArgsDef>;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/index.ts"],"names":[],"mappings":"AACA,OAAO,cAAc,CAAC;AAkBtB;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,qDA+C1B,CAAC"}
@@ -0,0 +1,83 @@
1
+ import { defineCommand } from "citty";
2
+ import "./schemas.js"; // side-effect import: registers `baker schema ads.linkedin.*` entries
3
+ import { accountCommand } from "./account.js";
4
+ import { accountsCommand } from "./accounts.js";
5
+ import { analyticsCommand } from "./analytics.js";
6
+ import { audienceSizeCommand } from "./audience-size.js";
7
+ import { auditCommand } from "./audit.js";
8
+ import { bidPricingCommand } from "./bid-pricing.js";
9
+ import { campaignGroupsCommand } from "./campaign-groups.js";
10
+ import { campaignsCommand } from "./campaigns.js";
11
+ import { conversationCommand } from "./conversation.js";
12
+ import { conversionsCommand } from "./conversions.js";
13
+ import { creativesCommand } from "./creatives.js";
14
+ import { demographicsCommand } from "./demographics.js";
15
+ import { facetsCommand } from "./facets.js";
16
+ import { forecastCommand } from "./forecast.js";
17
+ import { leadsCommand } from "./leads.js";
18
+ import { topCompaniesCommand } from "./top-companies.js";
19
+ /**
20
+ * LinkedIn Ads CLI — designed around LinkedIn's distinguishing strength:
21
+ * firmographic (per-job-title, per-company, per-industry, per-seniority)
22
+ * pivots on adAnalytics. AI agents should reach for `linkedin analytics
23
+ * --pivot job-title` and `--pivot company` when answering ABM/persona
24
+ * questions — Meta and Google can't do that.
25
+ *
26
+ * Read-only v1. All analytics queries default to `--level account --intent
27
+ * baseline --granularity DAILY --last-days 7`. When pivoting on a MEMBER_*
28
+ * dimension, the CLI auto-forces granularity=ALL (LinkedIn rejects
29
+ * DAILY + demographic) and surfaces a "demographic delayed 12-24h" warning.
30
+ *
31
+ * Authentication: requires the LinkedIn integration to be connected in the
32
+ * dashboard with `r_ads` and `r_ads_reporting` scopes. CLI talks to Baker's
33
+ * backend, which holds the OAuth token.
34
+ */
35
+ export const linkedinCommand = defineCommand({
36
+ meta: {
37
+ name: "linkedin",
38
+ description: `LinkedIn Marketing API — AI-first command surface for B2B ad insights.
39
+
40
+ Discovery:
41
+ baker ads linkedin accounts — accounts in this company's connected scope
42
+ baker ads linkedin accounts --include-all — every account the token can see
43
+ baker ads linkedin account --account-id 503001492 — single-account detail (currency, type, status)
44
+
45
+ Hierarchy (default ACTIVE-only — pass --all-statuses to widen):
46
+ baker ads linkedin campaign-groups --account-id 503001492
47
+ baker ads linkedin campaigns --account-id 503001492
48
+ baker ads linkedin campaigns --account-id 503001492 --campaign-group-id 12345
49
+ baker ads linkedin creatives --account-id 503001492 --campaign-id 67890
50
+
51
+ Performance — the workhorse (3 axes):
52
+ baker ads linkedin analytics — defaults: level=account, intent=baseline, last_7d, DAILY
53
+ baker ads linkedin analytics --intent revenue --last-days 28
54
+ baker ads linkedin analytics --level campaign --campaign-id 1234 --pivot job-title — LinkedIn's superpower (per-title perf)
55
+ baker ads linkedin analytics --level campaign --campaign-id 1234 --pivot company — top companies seeing the ad (ABM gold)
56
+ baker ads linkedin analytics --level campaign --campaign-id 1234 --intent ranking — fatigue: derives frequency
57
+ baker ads linkedin analytics --list-intents
58
+ baker ads linkedin analytics --list-pivots
59
+
60
+ Account ID format:
61
+ --account-id accepts numeric (503001492) or URN (urn:li:sponsoredAccount:503001492).
62
+ Set BAKER_LINKEDIN_AD_ACCOUNT_ID env to skip --account-id on every call.`,
63
+ },
64
+ subCommands: {
65
+ accounts: accountsCommand,
66
+ account: accountCommand,
67
+ "campaign-groups": campaignGroupsCommand,
68
+ campaigns: campaignsCommand,
69
+ creatives: creativesCommand,
70
+ analytics: analyticsCommand,
71
+ demographics: demographicsCommand,
72
+ "top-companies": topCompaniesCommand,
73
+ facets: facetsCommand,
74
+ "audience-size": audienceSizeCommand,
75
+ "bid-pricing": bidPricingCommand,
76
+ forecast: forecastCommand,
77
+ leads: leadsCommand,
78
+ conversions: conversionsCommand,
79
+ conversation: conversationCommand,
80
+ audit: auditCommand,
81
+ },
82
+ });
83
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,cAAc,CAAC,CAAC,sEAAsE;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;IAC3C,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;2EAwB0D;KACxE;IACD,WAAW,EAAE;QACX,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,cAAc;QACvB,iBAAiB,EAAE,qBAAqB;QACxC,SAAS,EAAE,gBAAgB;QAC3B,SAAS,EAAE,gBAAgB;QAC3B,SAAS,EAAE,gBAAgB;QAC3B,YAAY,EAAE,mBAAmB;QACjC,eAAe,EAAE,mBAAmB;QACpC,MAAM,EAAE,aAAa;QACrB,eAAe,EAAE,mBAAmB;QACpC,aAAa,EAAE,iBAAiB;QAChC,QAAQ,EAAE,eAAe;QACzB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,kBAAkB;QAC/B,YAAY,EAAE,mBAAmB;QACjC,KAAK,EAAE,YAAY;KACpB;CACF,CAAC,CAAC"}
@@ -0,0 +1,40 @@
1
+ export declare const leadsCommand: import("citty").CommandDef<{
2
+ readonly "account-id": {
3
+ readonly type: "string";
4
+ readonly description: "Numeric account ID or urn:li:sponsoredAccount:N";
5
+ };
6
+ readonly "account-urn": {
7
+ readonly type: "string";
8
+ readonly description: "Alias for --account-id";
9
+ };
10
+ readonly "form-id": {
11
+ readonly type: "string";
12
+ readonly description: "Filter by Lead Gen Form ID";
13
+ };
14
+ readonly "campaign-id": {
15
+ readonly type: "string";
16
+ readonly description: "Filter by campaign ID";
17
+ };
18
+ readonly "since-days": {
19
+ readonly type: "string";
20
+ readonly description: "Only responses submitted in the last N days";
21
+ };
22
+ readonly "since-ms": {
23
+ readonly type: "string";
24
+ readonly description: "Only responses submitted at or after this epoch ms (alternative to --since-days)";
25
+ };
26
+ readonly limit: {
27
+ readonly type: "string";
28
+ readonly description: "Max rows (default: 500)";
29
+ };
30
+ readonly "skip-cache": {
31
+ readonly type: "boolean";
32
+ readonly description: "Bypass server-side cache";
33
+ };
34
+ readonly output: {
35
+ readonly type: "string";
36
+ readonly description: "json|csv|jsonl|md";
37
+ readonly default: "json";
38
+ };
39
+ }>;
40
+ //# sourceMappingURL=leads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leads.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/leads.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DvB,CAAC"}