@koda-sl/baker-cli 0.432.0 → 0.433.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 +58 -24
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1121,6 +1121,7 @@ baker ads linkedin top-companies --campaign-id 1234 --last-days 30
|
|
|
1121
1121
|
# most engaged first ({org, name, impressions, clicks, engagements, costLocal}).
|
|
1122
1122
|
# Defaults: last 12 calendar months, the only selected ad account, top 100 (--full for all).
|
|
1123
1123
|
baker ads linkedin companies --account-id 1234
|
|
1124
|
+
baker ads linkedin companies --page 2 # companies 101-200, most engaged first
|
|
1124
1125
|
baker ads linkedin companies --by month --min-impressions 50 # months[] per company
|
|
1125
1126
|
baker ads linkedin companies --campaign-id 1,2 --by campaign # campaigns[] per company
|
|
1126
1127
|
baker ads linkedin companies --with-domains --stats --output csv # + domain/domainSource; read-quality stats
|
|
@@ -4018,13 +4019,14 @@ No write surface against HubSpot itself — a form's fields, redirect, or consen
|
|
|
4018
4019
|
|
|
4019
4020
|
### `baker accounts influenced | engagement | warm | company | campaigns | crm`
|
|
4020
4021
|
|
|
4021
|
-
Account insights: which companies the LinkedIn ads are warming, and which CRM deals they influenced. Reads Baker's nightly copy of LinkedIn and the CRM, so it is fast and covers up to 24 months; nothing is changed anywhere.
|
|
4022
|
+
Account insights: which companies the LinkedIn ads are warming, and which CRM deals they influenced. Reads Baker's nightly copy of LinkedIn and the CRM, so it is fast and covers up to 24 months; nothing is changed anywhere. Every company has it once a LinkedIn ad account is chosen; before the first nightly read the reports are empty — read live with `baker ads linkedin companies`. `--start`/`--end` must be real calendar days within 24 calendar months; a bad flag or an unsupported `--output` exits 1 with `INVALID_ARGS`.
|
|
4022
4023
|
|
|
4023
4024
|
```bash
|
|
4024
4025
|
baker accounts influenced # influenced pipeline, last 12 calendar months
|
|
4025
4026
|
baker accounts influenced --basis revenue --start 2026-01-01 --end 2026-06-30
|
|
4026
4027
|
baker accounts influenced --full # every deal in the period, influenced or not
|
|
4027
4028
|
baker accounts engagement --last-months 3 --limit 50 # companies reached, New/Rising, CRM match and deals
|
|
4029
|
+
baker accounts engagement --last-months 3 --limit 50 --page 2 # the next 50 (pageInfo.total counts them all)
|
|
4028
4030
|
baker accounts engagement --campaign-id 123456 --output csv
|
|
4029
4031
|
baker accounts warm --output csv > warm.csv # companyName,domain,organizationUrn
|
|
4030
4032
|
baker accounts company acme.com # or a LinkedIn company id / urn:li:organization:N
|
package/dist/cli.js
CHANGED
|
@@ -22414,7 +22414,12 @@ var crmSheetLinkSchema = z2.object({
|
|
|
22414
22414
|
var accountsCrmStatusResponseSchema = z2.object({
|
|
22415
22415
|
ok: z2.literal(true),
|
|
22416
22416
|
data: z2.object({
|
|
22417
|
-
|
|
22417
|
+
/**
|
|
22418
|
+
* Always true, for CLIs from when Account insights was a per-company
|
|
22419
|
+
* switch: they read its absence as "switched off". Drop it once no
|
|
22420
|
+
* Runtime runs one of them.
|
|
22421
|
+
*/
|
|
22422
|
+
enabled: z2.literal(true).optional(),
|
|
22418
22423
|
/** `hubspot` (Baker reads it), `api` (the client sends it), or null before anyone chose. */
|
|
22419
22424
|
source: z2.enum(["hubspot", "api"]).nullable(),
|
|
22420
22425
|
/** Where a client's system sends. */
|
|
@@ -22702,7 +22707,10 @@ var accountsEngagementRequestSchema = z3.object({
|
|
|
22702
22707
|
...windowFields,
|
|
22703
22708
|
/** One campaign's companies; every campaign together when absent. */
|
|
22704
22709
|
campaignId: z3.string().regex(/^\d+$/, "use the numeric campaign id").optional(),
|
|
22705
|
-
|
|
22710
|
+
/** Companies per page. */
|
|
22711
|
+
limit: z3.number().int().min(1).max(ACCOUNTS_ENGAGEMENT_MAX_LIMIT).default(ACCOUNTS_ENGAGEMENT_DEFAULT_LIMIT),
|
|
22712
|
+
/** Which page, 1-based, most engaged first. */
|
|
22713
|
+
page: z3.number().int().min(1).default(1)
|
|
22706
22714
|
}).superRefine(windowRules);
|
|
22707
22715
|
var accountsEngagementResponseSchema = z3.object({
|
|
22708
22716
|
ok: z3.literal(true),
|
|
@@ -22710,8 +22718,10 @@ var accountsEngagementResponseSchema = z3.object({
|
|
|
22710
22718
|
window: accountsWindowSchema,
|
|
22711
22719
|
previousWindow: accountsWindowSchema,
|
|
22712
22720
|
companies: z3.array(accountEngagementRowSchema),
|
|
22713
|
-
/** True when more companies were reached than
|
|
22721
|
+
/** True when more companies were reached than this page and the ones before it hold. */
|
|
22714
22722
|
truncated: z3.boolean(),
|
|
22723
|
+
/** Which page this is, and how many companies there are in all. Absent from older servers. */
|
|
22724
|
+
pageInfo: z3.object({ page: z3.number(), pageSize: z3.number(), total: z3.number(), hasMore: z3.boolean() }).optional(),
|
|
22715
22725
|
/** The company's influence rule (the default one before setup): the minimum `baker accounts warm` applies. */
|
|
22716
22726
|
rule: influenceParamsSchema.optional()
|
|
22717
22727
|
})
|
|
@@ -22860,7 +22870,6 @@ var accountsCampaignsResponseSchema = z3.object({
|
|
|
22860
22870
|
campaigns: z3.array(accountCampaignRowSchema)
|
|
22861
22871
|
})
|
|
22862
22872
|
});
|
|
22863
|
-
var ACCOUNTS_NOT_ENABLED_MESSAGE = "Account insights are not switched on for this company yet. The Baker team turns them on on request.";
|
|
22864
22873
|
var ACCOUNTS_NO_SETTINGS_MESSAGE = "Account insights are not set up yet: in Measure \u2192 Accounts, say where your deals are (HubSpot or another CRM) and what won and lost mean.";
|
|
22865
22874
|
|
|
22866
22875
|
// src/commands/accounts/index.ts
|
|
@@ -23718,6 +23727,8 @@ var linkedinCompaniesRequestSchema = z6.object({
|
|
|
23718
23727
|
withDomains: z6.boolean().default(false),
|
|
23719
23728
|
minImpressions: z6.number().int().min(0).default(0),
|
|
23720
23729
|
full: z6.boolean().default(false),
|
|
23730
|
+
/** Which page of 100 companies, most engaged first; ignored with `full`. */
|
|
23731
|
+
page: z6.number().int().min(1).default(1),
|
|
23721
23732
|
stats: z6.boolean().default(false),
|
|
23722
23733
|
skipCache: z6.boolean().optional()
|
|
23723
23734
|
}).superRefine((req, ctx) => {
|
|
@@ -23772,8 +23783,10 @@ var linkedinCompaniesStatsSchema = z6.object({
|
|
|
23772
23783
|
var linkedinCompaniesWarningSchema = z6.object({ code: z6.string(), message: z6.string() });
|
|
23773
23784
|
var linkedinCompaniesResponseSchema = z6.object({
|
|
23774
23785
|
rows: z6.array(linkedinCompanyRowSchema),
|
|
23775
|
-
/** Companies above minImpressions
|
|
23786
|
+
/** Companies above minImpressions, every page together. */
|
|
23776
23787
|
totalCompanies: z6.number(),
|
|
23788
|
+
/** Which page of 100 `rows` is (1 with `full`). Absent from older servers. */
|
|
23789
|
+
page: z6.number().optional(),
|
|
23777
23790
|
stats: linkedinCompaniesStatsSchema.optional(),
|
|
23778
23791
|
warnings: z6.array(linkedinCompaniesWarningSchema),
|
|
23779
23792
|
query: z6.object({
|
|
@@ -32953,7 +32966,6 @@ function refusedHints(lastLive) {
|
|
|
32953
32966
|
];
|
|
32954
32967
|
}
|
|
32955
32968
|
function statusHints(data) {
|
|
32956
|
-
if (!data.enabled) return ["Account insights is not switched on for this company; the Baker team switches it on."];
|
|
32957
32969
|
if (data.source === null) {
|
|
32958
32970
|
return [
|
|
32959
32971
|
"Nobody has said where the deals are yet. The user chooses in Measure \u2192 Accounts: HubSpot, or Another CRM (they send the deals)."
|
|
@@ -33039,15 +33051,6 @@ var crmCommand = defineCommand({
|
|
|
33039
33051
|
|
|
33040
33052
|
// src/commands/accounts/report.ts
|
|
33041
33053
|
function accountsRefusal(code, message) {
|
|
33042
|
-
if (code === "CONFLICT" && message.includes(ACCOUNTS_NOT_ENABLED_MESSAGE)) {
|
|
33043
|
-
return {
|
|
33044
|
-
code: "ACCOUNTS_NOT_ENABLED",
|
|
33045
|
-
fix: {
|
|
33046
|
-
action: "continue_without",
|
|
33047
|
-
explanation: "Account insights is not switched on for this company, so none of `baker accounts` can answer \u2014 do not retry it. Read the same thing live instead: `baker ads linkedin companies --with-domains` lists the companies the LinkedIn ads reached (--by month shows who is warming up); if HubSpot is connected, `baker hubspot companies search --domains <domain,\u2026> --with-deals` shows which are already customers or open deals. Say the numbers come from that live read, not from Account insights, and finish the rest of the task."
|
|
33048
|
-
}
|
|
33049
|
-
};
|
|
33050
|
-
}
|
|
33051
33054
|
if (code === "CONFLICT" && message.includes(ACCOUNTS_NO_SETTINGS_MESSAGE)) {
|
|
33052
33055
|
return {
|
|
33053
33056
|
code: "ACCOUNTS_NOT_SET_UP",
|
|
@@ -33111,6 +33114,14 @@ function engagementHints(data, request) {
|
|
|
33111
33114
|
`No company the LinkedIn ads reached shows up for ${data.window.start} to ${data.window.end}. The nightly sync may not have run since the campaigns started delivering, or LinkedIn left the companies out (fewer than 3 events in a month). Try a longer period (--last-months 12), or read the ad account live with \`baker ads linkedin companies\`.`
|
|
33112
33115
|
];
|
|
33113
33116
|
}
|
|
33117
|
+
const page = data.pageInfo;
|
|
33118
|
+
if (page?.hasMore) {
|
|
33119
|
+
const first = (page.page - 1) * page.pageSize + 1;
|
|
33120
|
+
const last = first + data.companies.length - 1;
|
|
33121
|
+
return [
|
|
33122
|
+
`Companies ${first}-${last} of ${page.total.toLocaleString("en")} shown. Read the next ones with --page ${page.page + 1} --limit ${page.pageSize}.`
|
|
33123
|
+
];
|
|
33124
|
+
}
|
|
33114
33125
|
return data.truncated ? [`More companies were reached than --limit ${request.limit}; raise it to see the tail.`] : [];
|
|
33115
33126
|
}
|
|
33116
33127
|
var ENGAGEMENT_TABLE_FIELDS = [
|
|
@@ -33392,21 +33403,27 @@ var ENGAGEMENT_ARGS = {
|
|
|
33392
33403
|
"campaign-id": { type: "string", description: "Only this campaign's companies (numeric id)", required: false },
|
|
33393
33404
|
limit: {
|
|
33394
33405
|
type: "string",
|
|
33395
|
-
description: `
|
|
33406
|
+
description: `Companies per page, 1-${ACCOUNTS_ENGAGEMENT_MAX_LIMIT} (default 500)`,
|
|
33407
|
+
required: false
|
|
33408
|
+
},
|
|
33409
|
+
page: {
|
|
33410
|
+
type: "string",
|
|
33411
|
+
description: "Which page to read, 1-based, most engaged first (default 1). pageInfo.hasMore says another page follows; pageInfo.total counts every company reached",
|
|
33396
33412
|
required: false
|
|
33397
33413
|
},
|
|
33398
33414
|
output: OUTPUT_ARG
|
|
33399
33415
|
};
|
|
33400
33416
|
registerSchema({
|
|
33401
33417
|
command: "accounts.engagement",
|
|
33402
|
-
description: "Every company the LinkedIn ads reached, most engaged first, with the period before for comparison, New/Rising flags, and where it stands in the CRM (matched company; dealStatus won > open > lost > none, lost meaning every deal it had was lost; lastLostAt). Default the last 3 calendar months. From the nightly sync, so it is fast and covers up to 24 months; for a live read of one ad account use `baker ads linkedin companies`.",
|
|
33418
|
+
description: "Every company the LinkedIn ads reached, most engaged first, with the period before for comparison, New/Rising flags, and where it stands in the CRM (matched company; dealStatus won > open > lost > none, lost meaning every deal it had was lost; lastLostAt). Default the last 3 calendar months. From the nightly sync, so it is fast and covers up to 24 months; for a live read of one ad account use `baker ads linkedin companies`. Paged: --limit companies per page, --page N; pageInfo {page, pageSize, total, hasMore}.",
|
|
33403
33419
|
args: ENGAGEMENT_ARGS
|
|
33404
33420
|
});
|
|
33405
33421
|
function engagementInput(args8, limit) {
|
|
33406
33422
|
return {
|
|
33407
33423
|
...windowInput(args8),
|
|
33408
33424
|
campaignId: optionalString(args8["campaign-id"])?.replace(/^urn:li:sponsoredCampaign:/, ""),
|
|
33409
|
-
limit: limit ?? optionalNumber(args8.limit)
|
|
33425
|
+
limit: limit ?? optionalNumber(args8.limit),
|
|
33426
|
+
page: limit === void 0 ? optionalNumber(args8.page) : void 0
|
|
33410
33427
|
};
|
|
33411
33428
|
}
|
|
33412
33429
|
var engagementCommand = defineCommand2({
|
|
@@ -33430,7 +33447,7 @@ var engagementCommand = defineCommand2({
|
|
|
33430
33447
|
writeJson({
|
|
33431
33448
|
...response,
|
|
33432
33449
|
data: { ...response.data, companies },
|
|
33433
|
-
meta: { count: companies.length },
|
|
33450
|
+
meta: { count: companies.length, ...response.data.pageInfo ? { total: response.data.pageInfo.total } : {} },
|
|
33434
33451
|
...hints2.length > 0 ? { hints: hints2 } : {}
|
|
33435
33452
|
});
|
|
33436
33453
|
} catch (err) {
|
|
@@ -51098,7 +51115,7 @@ registerSchema({
|
|
|
51098
51115
|
});
|
|
51099
51116
|
registerSchema({
|
|
51100
51117
|
command: "ads.linkedin.companies",
|
|
51101
|
-
description: "Which companies the LinkedIn ads reached \u2014 one row per company over the whole period ({org, name, impressions, clicks, engagements, costLocal}), most engaged first. Start here for warm accounts / ABM reporting. Defaults: last 12 calendar months, the only selected ad account,
|
|
51118
|
+
description: "Which companies the LinkedIn ads reached \u2014 one row per company over the whole period ({org, name, impressions, clicks, engagements, costLocal}), most engaged first. Start here for warm accounts / ABM reporting. Defaults: last 12 calendar months, the only selected ad account, 100 companies a page (--page N for the next, --full for all; totalCompanies counts them all). --by month|campaign adds a months[] or campaigns[] breakdown; --with-domains adds domain + domainSource for CRM matching; --stats adds row counts and cost/reach/domain coverage (no names). LinkedIn drops companies under 3 events a month.",
|
|
51102
51119
|
args: {
|
|
51103
51120
|
"account-id": {
|
|
51104
51121
|
type: "string",
|
|
@@ -51117,6 +51134,11 @@ registerSchema({
|
|
|
51117
51134
|
"with-domains": { type: "boolean", description: "Add website domain + domainSource per company", required: false },
|
|
51118
51135
|
"min-impressions": { type: "string", description: "Leave out companies under N impressions", required: false },
|
|
51119
51136
|
full: { type: "boolean", description: "Every company, plus videoViews", required: false },
|
|
51137
|
+
page: {
|
|
51138
|
+
type: "string",
|
|
51139
|
+
description: "Which page of 100 companies, most engaged first (default 1)",
|
|
51140
|
+
required: false
|
|
51141
|
+
},
|
|
51120
51142
|
stats: { type: "boolean", description: "Add read-quality stats (counts and rates only)", required: false },
|
|
51121
51143
|
"no-cache": NO_CACHE_ARG,
|
|
51122
51144
|
output: { type: "string", description: "json|csv|jsonl|md", required: false, default: "json" }
|
|
@@ -53618,6 +53640,7 @@ Examples:
|
|
|
53618
53640
|
|
|
53619
53641
|
// src/commands/ads/linkedin/companies.ts
|
|
53620
53642
|
import { defineCommand as defineCommand68 } from "citty";
|
|
53643
|
+
var COMPANIES_PAGE_SIZE = 100;
|
|
53621
53644
|
var COMPANIES_TIMEOUT_MS = 18e4;
|
|
53622
53645
|
var CSV_FIELDS = [
|
|
53623
53646
|
"org",
|
|
@@ -53651,8 +53674,12 @@ function companiesHints(data, request) {
|
|
|
53651
53674
|
);
|
|
53652
53675
|
}
|
|
53653
53676
|
if (data.totalCompanies > data.rows.length) {
|
|
53677
|
+
const page = data.page ?? 1;
|
|
53678
|
+
const first = (page - 1) * COMPANIES_PAGE_SIZE + 1;
|
|
53679
|
+
const last = first + data.rows.length - 1;
|
|
53680
|
+
const next = last < data.totalCompanies ? ` \u2014 --page ${page + 1} for the next ${COMPANIES_PAGE_SIZE}, ` : " \u2014 ";
|
|
53654
53681
|
hints2.push(
|
|
53655
|
-
`Showing
|
|
53682
|
+
`Showing companies ${first}-${last} of ${data.totalCompanies.toLocaleString("en")}, most engaged first${next}--full for all, or --min-impressions to trim the tail.`
|
|
53656
53683
|
);
|
|
53657
53684
|
}
|
|
53658
53685
|
if (data.query.by === "none" && data.rows.length > 0) {
|
|
@@ -53672,7 +53699,8 @@ var FLAG_OF_FIELD2 = {
|
|
|
53672
53699
|
start: "--start",
|
|
53673
53700
|
end: "--end",
|
|
53674
53701
|
by: "--by",
|
|
53675
|
-
minImpressions: "--min-impressions"
|
|
53702
|
+
minImpressions: "--min-impressions",
|
|
53703
|
+
page: "--page"
|
|
53676
53704
|
};
|
|
53677
53705
|
function flagOf(field) {
|
|
53678
53706
|
return FLAG_OF_FIELD2[field.split(".")[0] ?? ""] ?? (field || "args");
|
|
@@ -53690,10 +53718,11 @@ var companiesCommand = defineCommand68({
|
|
|
53690
53718
|
|
|
53691
53719
|
Start here for "which companies are our ads warming", ABM reporting, or building a warm-account list.
|
|
53692
53720
|
Rows: {org, name, impressions, clicks, engagements, costLocal}. Defaults: the last 12 calendar
|
|
53693
|
-
months, the only selected ad account,
|
|
53721
|
+
months, the only selected ad account, 100 companies a page (--page 2 for the next, --full for all).
|
|
53694
53722
|
|
|
53695
53723
|
Examples:
|
|
53696
53724
|
baker ads linkedin companies # last 12 months, whole account
|
|
53725
|
+
baker ads linkedin companies --page 2 # the next 100 companies
|
|
53697
53726
|
baker ads linkedin companies --by month --min-impressions 50 # when each company warmed up
|
|
53698
53727
|
baker ads linkedin companies --campaign-id 333728193,810055513 --by campaign
|
|
53699
53728
|
baker ads linkedin companies --with-domains --output csv # + website domain, for CRM matching
|
|
@@ -53714,7 +53743,11 @@ so small companies are undercounted. engagements = LinkedIn's totalEngagements.`
|
|
|
53714
53743
|
by: { type: "string", description: "none | month | campaign \u2014 break each company down (default none)" },
|
|
53715
53744
|
"with-domains": { type: "boolean", description: "Add each company's website domain and domainSource" },
|
|
53716
53745
|
"min-impressions": { type: "string", description: "Leave out companies under N impressions over the period" },
|
|
53717
|
-
full: { type: "boolean", description: "Every company (not just
|
|
53746
|
+
full: { type: "boolean", description: "Every company (not just a page of 100), plus videoViews" },
|
|
53747
|
+
page: {
|
|
53748
|
+
type: "string",
|
|
53749
|
+
description: "Which page of 100 companies, most engaged first (default 1); totalCompanies counts them all"
|
|
53750
|
+
},
|
|
53718
53751
|
stats: { type: "boolean", description: "Add read-quality stats: row counts, cost/reach/domain coverage" },
|
|
53719
53752
|
"no-cache": NO_CACHE_ARG,
|
|
53720
53753
|
output: { type: "string", description: "json|csv|jsonl|md", default: "json" }
|
|
@@ -53730,6 +53763,7 @@ so small companies are undercounted. engagements = LinkedIn's totalEngagements.`
|
|
|
53730
53763
|
withDomains: Boolean(args8["with-domains"]),
|
|
53731
53764
|
minImpressions: optionalNumber2(args8["min-impressions"]),
|
|
53732
53765
|
full: Boolean(args8.full),
|
|
53766
|
+
page: optionalNumber2(args8.page),
|
|
53733
53767
|
stats: Boolean(args8.stats),
|
|
53734
53768
|
skipCache: Boolean(args8["no-cache"])
|
|
53735
53769
|
};
|