@koda-sl/baker-cli 0.25.0-dev.f89d9a60 → 0.25.1
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 +78 -55
- package/dist/cli.js +1 -1
- package/dist/commands/ads/index.d.ts.map +1 -1
- package/dist/commands/ads/index.js +8 -7
- package/dist/commands/ads/index.js.map +1 -1
- package/dist/commands/ads/meta/account.d.ts +11 -0
- package/dist/commands/ads/meta/account.d.ts.map +1 -0
- package/dist/commands/ads/meta/account.js +32 -0
- package/dist/commands/ads/meta/account.js.map +1 -0
- package/dist/commands/ads/meta/accounts.d.ts +20 -0
- package/dist/commands/ads/meta/accounts.d.ts.map +1 -0
- package/dist/commands/ads/meta/accounts.js +55 -0
- package/dist/commands/ads/meta/accounts.js.map +1 -0
- package/dist/commands/ads/meta/activities.d.ts +24 -0
- package/dist/commands/ads/meta/activities.d.ts.map +1 -0
- package/dist/commands/ads/meta/activities.js +44 -0
- package/dist/commands/ads/meta/activities.js.map +1 -0
- package/dist/commands/ads/meta/ads.d.ts +36 -0
- package/dist/commands/ads/meta/ads.d.ts.map +1 -0
- package/dist/commands/ads/meta/ads.js +57 -0
- package/dist/commands/ads/meta/ads.js.map +1 -0
- package/dist/commands/ads/meta/adsets.d.ts +32 -0
- package/dist/commands/ads/meta/adsets.d.ts.map +1 -0
- package/dist/commands/ads/meta/adsets.js +50 -0
- package/dist/commands/ads/meta/adsets.js.map +1 -0
- package/dist/commands/ads/meta/audiences.d.ts +20 -0
- package/dist/commands/ads/meta/audiences.d.ts.map +1 -0
- package/dist/commands/ads/meta/audiences.js +41 -0
- package/dist/commands/ads/meta/audiences.js.map +1 -0
- package/dist/commands/ads/meta/businesses.d.ts +12 -0
- package/dist/commands/ads/meta/businesses.d.ts.map +1 -0
- package/dist/commands/ads/meta/businesses.js +35 -0
- package/dist/commands/ads/meta/businesses.js.map +1 -0
- package/dist/commands/ads/meta/campaigns.d.ts +28 -0
- package/dist/commands/ads/meta/campaigns.d.ts.map +1 -0
- package/dist/commands/ads/meta/campaigns.js +51 -0
- package/dist/commands/ads/meta/campaigns.js.map +1 -0
- package/dist/commands/ads/meta/creatives.d.ts +24 -0
- package/dist/commands/ads/meta/creatives.d.ts.map +1 -0
- package/dist/commands/ads/meta/creatives.js +51 -0
- package/dist/commands/ads/meta/creatives.js.map +1 -0
- package/dist/commands/ads/meta/index.d.ts +17 -0
- package/dist/commands/ads/meta/index.d.ts.map +1 -0
- package/dist/commands/ads/meta/index.js +79 -0
- package/dist/commands/ads/meta/index.js.map +1 -0
- package/dist/commands/ads/meta/insights.d.ts +92 -0
- package/dist/commands/ads/meta/insights.d.ts.map +1 -0
- package/dist/commands/ads/meta/insights.js +260 -0
- package/dist/commands/ads/meta/insights.js.map +1 -0
- package/dist/commands/ads/meta/pixels.d.ts +33 -0
- package/dist/commands/ads/meta/pixels.d.ts.map +1 -0
- package/dist/commands/ads/meta/pixels.js +76 -0
- package/dist/commands/ads/meta/pixels.js.map +1 -0
- package/dist/commands/ads/meta/presets.d.ts +30 -0
- package/dist/commands/ads/meta/presets.d.ts.map +1 -0
- package/dist/commands/ads/meta/presets.js +86 -0
- package/dist/commands/ads/meta/presets.js.map +1 -0
- package/dist/commands/ads/meta/preview.d.ts +32 -0
- package/dist/commands/ads/meta/preview.d.ts.map +1 -0
- package/dist/commands/ads/meta/preview.js +90 -0
- package/dist/commands/ads/meta/preview.js.map +1 -0
- package/dist/commands/ads/meta/shared.d.ts +18 -0
- package/dist/commands/ads/meta/shared.d.ts.map +1 -0
- package/dist/commands/ads/meta/shared.js +86 -0
- package/dist/commands/ads/meta/shared.js.map +1 -0
- package/dist/env.d.ts +1 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +1 -4
- package/dist/env.js.map +1 -1
- package/dist/error-handler.d.ts +1 -1
- package/dist/error-handler.d.ts.map +1 -1
- package/dist/error-handler.js +3 -3
- package/dist/error-handler.js.map +1 -1
- package/package.json +1 -1
- package/dist/commands/ads/x/accounts.d.ts +0 -14
- package/dist/commands/ads/x/accounts.d.ts.map +0 -1
- package/dist/commands/ads/x/accounts.js +0 -73
- package/dist/commands/ads/x/accounts.js.map +0 -1
- package/dist/commands/ads/x/active-entities.d.ts +0 -43
- package/dist/commands/ads/x/active-entities.d.ts.map +0 -1
- package/dist/commands/ads/x/active-entities.js +0 -88
- package/dist/commands/ads/x/active-entities.js.map +0 -1
- package/dist/commands/ads/x/audiences.d.ts +0 -19
- package/dist/commands/ads/x/audiences.d.ts.map +0 -1
- package/dist/commands/ads/x/audiences.js +0 -65
- package/dist/commands/ads/x/audiences.js.map +0 -1
- package/dist/commands/ads/x/campaigns.d.ts +0 -34
- package/dist/commands/ads/x/campaigns.d.ts.map +0 -1
- package/dist/commands/ads/x/campaigns.js +0 -56
- package/dist/commands/ads/x/campaigns.js.map +0 -1
- package/dist/commands/ads/x/cards.d.ts +0 -19
- package/dist/commands/ads/x/cards.d.ts.map +0 -1
- package/dist/commands/ads/x/cards.js +0 -65
- package/dist/commands/ads/x/cards.js.map +0 -1
- package/dist/commands/ads/x/error-parser.d.ts +0 -3
- package/dist/commands/ads/x/error-parser.d.ts.map +0 -1
- package/dist/commands/ads/x/error-parser.js +0 -80
- package/dist/commands/ads/x/error-parser.js.map +0 -1
- package/dist/commands/ads/x/funding.d.ts +0 -19
- package/dist/commands/ads/x/funding.d.ts.map +0 -1
- package/dist/commands/ads/x/funding.js +0 -65
- package/dist/commands/ads/x/funding.js.map +0 -1
- package/dist/commands/ads/x/index.d.ts +0 -2
- package/dist/commands/ads/x/index.d.ts.map +0 -1
- package/dist/commands/ads/x/index.js +0 -50
- package/dist/commands/ads/x/index.js.map +0 -1
- package/dist/commands/ads/x/line-items.d.ts +0 -34
- package/dist/commands/ads/x/line-items.d.ts.map +0 -1
- package/dist/commands/ads/x/line-items.js +0 -55
- package/dist/commands/ads/x/line-items.js.map +0 -1
- package/dist/commands/ads/x/media.d.ts +0 -24
- package/dist/commands/ads/x/media.d.ts.map +0 -1
- package/dist/commands/ads/x/media.js +0 -70
- package/dist/commands/ads/x/media.js.map +0 -1
- package/dist/commands/ads/x/output.d.ts +0 -13
- package/dist/commands/ads/x/output.d.ts.map +0 -1
- package/dist/commands/ads/x/output.js +0 -75
- package/dist/commands/ads/x/output.js.map +0 -1
- package/dist/commands/ads/x/presets.d.ts +0 -15
- package/dist/commands/ads/x/presets.d.ts.map +0 -1
- package/dist/commands/ads/x/presets.js +0 -60
- package/dist/commands/ads/x/presets.js.map +0 -1
- package/dist/commands/ads/x/promoted-tweets.d.ts +0 -29
- package/dist/commands/ads/x/promoted-tweets.d.ts.map +0 -1
- package/dist/commands/ads/x/promoted-tweets.js +0 -74
- package/dist/commands/ads/x/promoted-tweets.js.map +0 -1
- package/dist/commands/ads/x/run-list.d.ts +0 -17
- package/dist/commands/ads/x/run-list.d.ts.map +0 -1
- package/dist/commands/ads/x/run-list.js +0 -60
- package/dist/commands/ads/x/run-list.js.map +0 -1
- package/dist/commands/ads/x/stats/index.d.ts +0 -2
- package/dist/commands/ads/x/stats/index.d.ts.map +0 -1
- package/dist/commands/ads/x/stats/index.js +0 -32
- package/dist/commands/ads/x/stats/index.js.map +0 -1
- package/dist/commands/ads/x/stats/job-create.d.ts +0 -58
- package/dist/commands/ads/x/stats/job-create.d.ts.map +0 -1
- package/dist/commands/ads/x/stats/job-create.js +0 -95
- package/dist/commands/ads/x/stats/job-create.js.map +0 -1
- package/dist/commands/ads/x/stats/job-status.d.ts +0 -18
- package/dist/commands/ads/x/stats/job-status.d.ts.map +0 -1
- package/dist/commands/ads/x/stats/job-status.js +0 -58
- package/dist/commands/ads/x/stats/job-status.js.map +0 -1
- package/dist/commands/ads/x/stats/job.d.ts +0 -63
- package/dist/commands/ads/x/stats/job.d.ts.map +0 -1
- package/dist/commands/ads/x/stats/job.js +0 -183
- package/dist/commands/ads/x/stats/job.js.map +0 -1
- package/dist/commands/ads/x/stats/sync.d.ts +0 -73
- package/dist/commands/ads/x/stats/sync.d.ts.map +0 -1
- package/dist/commands/ads/x/stats/sync.js +0 -151
- package/dist/commands/ads/x/stats/sync.js.map +0 -1
- package/dist/commands/ads/x/targeting-constants.d.ts +0 -34
- package/dist/commands/ads/x/targeting-constants.d.ts.map +0 -1
- package/dist/commands/ads/x/targeting-constants.js +0 -80
- package/dist/commands/ads/x/targeting-constants.js.map +0 -1
- package/dist/commands/ads/x/targeting-criteria.d.ts +0 -24
- package/dist/commands/ads/x/targeting-criteria.d.ts.map +0 -1
- package/dist/commands/ads/x/targeting-criteria.js +0 -69
- package/dist/commands/ads/x/targeting-criteria.js.map +0 -1
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { apiPost } from "../../../client.js";
|
|
3
|
+
import { writeAdsJson, writeAdsOutput } from "../output.js";
|
|
4
|
+
import { composeFields, getIntent, listIntents } from "./presets.js";
|
|
5
|
+
import { csvOrJson, getDateRange, handleMetaError } from "./shared.js";
|
|
6
|
+
const POLL_INTERVAL_MS = 5_000;
|
|
7
|
+
const POLL_MAX_MS = 10 * 60_000;
|
|
8
|
+
/** Default attribution windows — only these still work as of Jan 2026 (1d_view + 28d_click also valid but rarely used). */
|
|
9
|
+
const DEFAULT_ATTRIBUTION_WINDOWS = ["7d_click", "1d_view"];
|
|
10
|
+
/** Default filter — strip rows that didn't deliver. Almost always what we want. */
|
|
11
|
+
const DEFAULT_FILTERING = [{ field: "impressions", operator: "GREATER_THAN", value: 0 }];
|
|
12
|
+
function commaSplit(input) {
|
|
13
|
+
if (!input)
|
|
14
|
+
return undefined;
|
|
15
|
+
return input
|
|
16
|
+
.split(",")
|
|
17
|
+
.map((s) => s.trim())
|
|
18
|
+
.filter(Boolean);
|
|
19
|
+
}
|
|
20
|
+
function parseFiltering(raw) {
|
|
21
|
+
if (!raw)
|
|
22
|
+
return undefined;
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(raw);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
handleMetaError(new Error("Invalid --filtering JSON"));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function pickIntent(name) {
|
|
31
|
+
if (!name)
|
|
32
|
+
return "baseline";
|
|
33
|
+
const found = getIntent(name);
|
|
34
|
+
if (!found) {
|
|
35
|
+
handleMetaError(new Error(`Unknown --intent: ${name}. Use --list-intents to see options.`));
|
|
36
|
+
}
|
|
37
|
+
return found.name;
|
|
38
|
+
}
|
|
39
|
+
function pickLevel(args) {
|
|
40
|
+
const raw = args.level;
|
|
41
|
+
if (!raw)
|
|
42
|
+
return "account";
|
|
43
|
+
if (raw !== "account" && raw !== "campaign" && raw !== "adset" && raw !== "ad") {
|
|
44
|
+
handleMetaError(new Error("--level must be one of: account|campaign|adset|ad"));
|
|
45
|
+
}
|
|
46
|
+
return raw;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Auto-async heuristic. Heavy queries that would time out as sync go async
|
|
50
|
+
* automatically — the user shouldn't have to think about it.
|
|
51
|
+
*
|
|
52
|
+
* - level=ad with breakdowns
|
|
53
|
+
* - >2 breakdowns at any level
|
|
54
|
+
* - explicit time range > 90 days
|
|
55
|
+
* - level=ad over an account-level object with a wide window
|
|
56
|
+
*/
|
|
57
|
+
function shouldAutoAsync(body) {
|
|
58
|
+
const breakdownCount = (body.breakdowns ?? []).length;
|
|
59
|
+
if (body.level === "ad" && breakdownCount > 0 && body.object.startsWith("act_")) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if (breakdownCount > 2) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if (body.since && body.until) {
|
|
66
|
+
const days = (Date.parse(body.until) - Date.parse(body.since)) / 86_400_000;
|
|
67
|
+
if (days > 90) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
function applyDateRange(body, args) {
|
|
74
|
+
const range = getDateRange(args);
|
|
75
|
+
if (range.datePreset)
|
|
76
|
+
body.datePreset = range.datePreset;
|
|
77
|
+
if (range.since)
|
|
78
|
+
body.since = range.since;
|
|
79
|
+
if (range.until)
|
|
80
|
+
body.until = range.until;
|
|
81
|
+
if (!body.datePreset && !(body.since && body.until)) {
|
|
82
|
+
body.datePreset = "last_7d";
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function buildFiltering(args) {
|
|
86
|
+
const explicit = parseFiltering(args.filtering);
|
|
87
|
+
if (explicit)
|
|
88
|
+
return explicit;
|
|
89
|
+
if (args["include-undelivered"])
|
|
90
|
+
return undefined;
|
|
91
|
+
return DEFAULT_FILTERING;
|
|
92
|
+
}
|
|
93
|
+
function buildAttributionWindows(args) {
|
|
94
|
+
const explicit = commaSplit(args["attribution-windows"]);
|
|
95
|
+
if (explicit)
|
|
96
|
+
return explicit;
|
|
97
|
+
return DEFAULT_ATTRIBUTION_WINDOWS;
|
|
98
|
+
}
|
|
99
|
+
function buildBody(args) {
|
|
100
|
+
const intent = pickIntent(args.intent);
|
|
101
|
+
const level = pickLevel(args);
|
|
102
|
+
const intentDef = getIntent(intent);
|
|
103
|
+
const explicitFields = commaSplit(args.fields);
|
|
104
|
+
const fields = explicitFields ?? composeFields(intent, level);
|
|
105
|
+
const breakdowns = commaSplit(args.breakdowns);
|
|
106
|
+
const actionBreakdowns = commaSplit(args["action-breakdowns"]) ?? intentDef?.actionBreakdowns;
|
|
107
|
+
const body = {
|
|
108
|
+
object: args.object,
|
|
109
|
+
level,
|
|
110
|
+
fields,
|
|
111
|
+
timeIncrement: args["time-increment"],
|
|
112
|
+
breakdowns,
|
|
113
|
+
actionBreakdowns,
|
|
114
|
+
filtering: buildFiltering(args),
|
|
115
|
+
attributionWindows: buildAttributionWindows(args),
|
|
116
|
+
useAccountAttributionSetting: Boolean(args["use-account-attribution"]),
|
|
117
|
+
useUnifiedAttributionSetting: Boolean(args["use-unified-attribution"]),
|
|
118
|
+
limit: args.limit ? Number(args.limit) : 1000,
|
|
119
|
+
skipCache: Boolean(args["skip-cache"]),
|
|
120
|
+
};
|
|
121
|
+
applyDateRange(body, args);
|
|
122
|
+
return body;
|
|
123
|
+
}
|
|
124
|
+
async function pollAsync(reportRunId) {
|
|
125
|
+
const start = Date.now();
|
|
126
|
+
while (Date.now() - start < POLL_MAX_MS) {
|
|
127
|
+
const status = await apiPost(`/api/ads/meta/insights/async/status?report-run-id=${encodeURIComponent(reportRunId)}`, {});
|
|
128
|
+
if (status.async_status === "Job Completed")
|
|
129
|
+
return;
|
|
130
|
+
if (status.async_status === "Job Failed" || status.async_status === "Job Skipped") {
|
|
131
|
+
handleMetaError(new Error(`Async insights job ${status.async_status}`));
|
|
132
|
+
}
|
|
133
|
+
process.stderr.write(`Async insights ${status.async_status ?? "queued"} (${Math.round(status.async_percent_completion ?? 0)}%)…\n`);
|
|
134
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
135
|
+
}
|
|
136
|
+
handleMetaError(new Error("Async insights polling timed out after 10 minutes"));
|
|
137
|
+
}
|
|
138
|
+
async function runAsync(body) {
|
|
139
|
+
const submit = await apiPost("/api/ads/meta/insights/async", body);
|
|
140
|
+
process.stderr.write(`Async insights job: ${submit.reportRunId}\n`);
|
|
141
|
+
await pollAsync(submit.reportRunId);
|
|
142
|
+
return apiPost("/api/ads/meta/insights/async/result", {
|
|
143
|
+
reportRunId: submit.reportRunId,
|
|
144
|
+
fields: body.fields,
|
|
145
|
+
limit: body.limit,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/** Insights rows have nested `actions[]` arrays. Sort by the named action_type's value descending. */
|
|
149
|
+
function sortRowsBySpendDesc(rows) {
|
|
150
|
+
return [...rows].sort((a, b) => {
|
|
151
|
+
const sa = Number(a.spend ?? 0);
|
|
152
|
+
const sb = Number(b.spend ?? 0);
|
|
153
|
+
if (Number.isNaN(sa) || Number.isNaN(sb))
|
|
154
|
+
return 0;
|
|
155
|
+
return sb - sa;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
export const insightsCommand = defineCommand({
|
|
159
|
+
meta: {
|
|
160
|
+
name: "insights",
|
|
161
|
+
description: `Performance reporting — the main Meta tool for AI agents.
|
|
162
|
+
|
|
163
|
+
Smart defaults so the AI doesn't have to remember every flag:
|
|
164
|
+
--level account (set --level campaign|adset|ad to drill in)
|
|
165
|
+
--intent baseline (or revenue|funnel|ranking|video|identity)
|
|
166
|
+
--date-preset last_7d (override with --since/--until)
|
|
167
|
+
--attribution-windows 7d_click,1d_view (the only ones still working post Jan 2026)
|
|
168
|
+
filter: impressions > 0 (skip undelivered rows; --include-undelivered to keep)
|
|
169
|
+
sort: spend descending (when result fits in memory)
|
|
170
|
+
auto-async when query is heavy (level=ad + breakdowns, big date ranges, etc.)
|
|
171
|
+
|
|
172
|
+
Identity fields (campaign_name, ad_name etc.) are appended automatically based on --level so rows
|
|
173
|
+
are self-describing.
|
|
174
|
+
|
|
175
|
+
Examples — common AI questions:
|
|
176
|
+
# "How is GreenLeaf doing this week?"
|
|
177
|
+
baker ads meta insights --object act_123
|
|
178
|
+
|
|
179
|
+
# "Which campaigns are profitable?"
|
|
180
|
+
baker ads meta insights --object act_123 --level campaign --intent revenue --date-preset last_28d
|
|
181
|
+
|
|
182
|
+
# "Which creatives need a refresh?"
|
|
183
|
+
baker ads meta insights --object act_123 --level ad --intent ranking --date-preset last_14d
|
|
184
|
+
|
|
185
|
+
# "Where do users drop off the funnel?"
|
|
186
|
+
baker ads meta insights --object act_123 --intent funnel
|
|
187
|
+
|
|
188
|
+
# "Should we shift budget to Instagram?"
|
|
189
|
+
baker ads meta insights --object act_123 --level adset --breakdowns publisher_platform,platform_position
|
|
190
|
+
|
|
191
|
+
# Custom field set (escape hatch)
|
|
192
|
+
baker ads meta insights --object act_123 --fields impressions,spend,actions
|
|
193
|
+
|
|
194
|
+
Async is automatic for heavy queries; pass --async to force it, or --no-async to refuse fallback.`,
|
|
195
|
+
},
|
|
196
|
+
args: {
|
|
197
|
+
object: {
|
|
198
|
+
type: "string",
|
|
199
|
+
description: "Object ID — act_<id> for account, or a campaign/adset/ad ID",
|
|
200
|
+
},
|
|
201
|
+
level: { type: "string", description: "account|campaign|adset|ad (default: account)" },
|
|
202
|
+
intent: { type: "string", description: "baseline|revenue|funnel|ranking|video|identity (default: baseline)" },
|
|
203
|
+
fields: { type: "string", description: "Comma-separated field list (overrides --intent bundle)" },
|
|
204
|
+
"list-intents": { type: "boolean", description: "Print available intents and exit" },
|
|
205
|
+
"date-preset": { type: "string", description: "Meta date preset (last_7d, last_28d, today, ...)" },
|
|
206
|
+
since: { type: "string", description: "Custom start date YYYY-MM-DD" },
|
|
207
|
+
until: { type: "string", description: "Custom end date YYYY-MM-DD" },
|
|
208
|
+
"time-increment": { type: "string", description: "1 (day) | monthly | all_days" },
|
|
209
|
+
breakdowns: { type: "string", description: "Comma-separated breakdowns (e.g. publisher_platform,age)" },
|
|
210
|
+
"action-breakdowns": {
|
|
211
|
+
type: "string",
|
|
212
|
+
description: "Slice the actions[] array (default: action_type for revenue/funnel)",
|
|
213
|
+
},
|
|
214
|
+
filtering: { type: "string", description: "Override default filter — JSON array of {field,operator,value}" },
|
|
215
|
+
"include-undelivered": { type: "boolean", description: "Keep rows where impressions=0 (off by default)" },
|
|
216
|
+
"attribution-windows": {
|
|
217
|
+
type: "string",
|
|
218
|
+
description: "Override default 7d_click,1d_view (only 1d_view, 1d_click, 7d_click, 28d_click work post Jan 2026)",
|
|
219
|
+
},
|
|
220
|
+
"use-account-attribution": { type: "boolean", description: "Use account-saved attribution setting" },
|
|
221
|
+
"use-unified-attribution": { type: "boolean", description: "Use ad-set unified attribution setting" },
|
|
222
|
+
limit: { type: "string", description: "Max rows (default 1000)" },
|
|
223
|
+
async: { type: "boolean", description: "Force async submit-and-poll path" },
|
|
224
|
+
"no-async": { type: "boolean", description: "Refuse the auto-async fallback for heavy queries" },
|
|
225
|
+
"no-sort": { type: "boolean", description: "Skip default spend-desc sort" },
|
|
226
|
+
"skip-cache": { type: "boolean", description: "Bypass server-side cache" },
|
|
227
|
+
output: { type: "string", description: "Output format", default: "json" },
|
|
228
|
+
},
|
|
229
|
+
run: async ({ args }) => {
|
|
230
|
+
if (args["list-intents"]) {
|
|
231
|
+
writeAdsJson({ ok: true, data: listIntents() });
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (!args.object) {
|
|
235
|
+
writeAdsJson({
|
|
236
|
+
ok: false,
|
|
237
|
+
error: { code: "VALIDATION_ERROR", message: "Missing required argument: --object" },
|
|
238
|
+
});
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
const body = buildBody(args);
|
|
242
|
+
const fmt = csvOrJson(args);
|
|
243
|
+
const wantAsync = Boolean(args.async) || (!args["no-async"] && shouldAutoAsync(body));
|
|
244
|
+
try {
|
|
245
|
+
const rows = wantAsync
|
|
246
|
+
? await runAsync(body)
|
|
247
|
+
: await apiPost("/api/ads/meta/insights", body);
|
|
248
|
+
const sorted = args["no-sort"] ? rows : sortRowsBySpendDesc(rows);
|
|
249
|
+
if (fmt !== "json") {
|
|
250
|
+
writeAdsOutput(sorted, fmt, body.fields);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
writeAdsJson({ ok: true, data: sorted });
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
handleMetaError(err);
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
//# sourceMappingURL=insights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insights.js","sourceRoot":"","sources":["../../../../src/commands/ads/meta/insights.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const pixelsCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly "account-id": {
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly description: "Meta ad account ID";
|
|
5
|
+
};
|
|
6
|
+
readonly "pixel-id": {
|
|
7
|
+
readonly type: "string";
|
|
8
|
+
readonly description: "Pixel ID for --stats";
|
|
9
|
+
};
|
|
10
|
+
readonly stats: {
|
|
11
|
+
readonly type: "boolean";
|
|
12
|
+
readonly description: "Fetch firing stats for the pixel";
|
|
13
|
+
};
|
|
14
|
+
readonly aggregation: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly description: "stats aggregation: event|browser_type|host|pixel_fire";
|
|
17
|
+
readonly default: "event";
|
|
18
|
+
};
|
|
19
|
+
readonly days: {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
readonly description: "Lookback days for --stats (default 7)";
|
|
22
|
+
};
|
|
23
|
+
readonly "skip-cache": {
|
|
24
|
+
readonly type: "boolean";
|
|
25
|
+
readonly description: "Bypass server-side cache";
|
|
26
|
+
};
|
|
27
|
+
readonly output: {
|
|
28
|
+
readonly type: "string";
|
|
29
|
+
readonly description: "Output format";
|
|
30
|
+
readonly default: "json";
|
|
31
|
+
};
|
|
32
|
+
}>;
|
|
33
|
+
//# sourceMappingURL=pixels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pixels.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/meta/pixels.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCxB,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { apiGet } from "../../../client.js";
|
|
3
|
+
import { writeAdsJson, writeAdsOutput } from "../output.js";
|
|
4
|
+
import { csvOrJson, daysAgoIso, handleMetaError, resolveAccountIdArg, todayIso } from "./shared.js";
|
|
5
|
+
export const pixelsCommand = defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "pixels",
|
|
8
|
+
description: `List Meta Pixels for an ad account, or fetch firing stats for one pixel.
|
|
9
|
+
|
|
10
|
+
Examples:
|
|
11
|
+
baker ads meta pixels --account-id act_123
|
|
12
|
+
baker ads meta pixels --account-id act_123 --pixel-id 9876 --stats --days 7`,
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
"account-id": { type: "string", description: "Meta ad account ID" },
|
|
16
|
+
"pixel-id": { type: "string", description: "Pixel ID for --stats" },
|
|
17
|
+
stats: { type: "boolean", description: "Fetch firing stats for the pixel" },
|
|
18
|
+
aggregation: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "stats aggregation: event|browser_type|host|pixel_fire",
|
|
21
|
+
default: "event",
|
|
22
|
+
},
|
|
23
|
+
days: { type: "string", description: "Lookback days for --stats (default 7)" },
|
|
24
|
+
"skip-cache": { type: "boolean", description: "Bypass server-side cache" },
|
|
25
|
+
output: { type: "string", description: "Output format", default: "json" },
|
|
26
|
+
},
|
|
27
|
+
run: async ({ args }) => {
|
|
28
|
+
try {
|
|
29
|
+
if (args.stats) {
|
|
30
|
+
await runStats(args);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
await runList(args);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
handleMetaError(err);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
async function runStats(args) {
|
|
41
|
+
const pixelId = args["pixel-id"];
|
|
42
|
+
if (!pixelId) {
|
|
43
|
+
handleMetaError(new Error("--pixel-id is required when --stats is set"));
|
|
44
|
+
}
|
|
45
|
+
const days = args.days ? Number(args.days) : 7;
|
|
46
|
+
if (!Number.isInteger(days) || days <= 0 || days > 90) {
|
|
47
|
+
handleMetaError(new Error("--days must be a positive integer ≤ 90"));
|
|
48
|
+
}
|
|
49
|
+
const params = {
|
|
50
|
+
"pixel-id": pixelId,
|
|
51
|
+
aggregation: args.aggregation ?? "event",
|
|
52
|
+
"start-time": daysAgoIso(days),
|
|
53
|
+
"end-time": todayIso(),
|
|
54
|
+
};
|
|
55
|
+
if (args["skip-cache"])
|
|
56
|
+
params["skip-cache"] = "true";
|
|
57
|
+
const data = await apiGet("/api/ads/meta/pixel-stats", params);
|
|
58
|
+
emit(data, args);
|
|
59
|
+
}
|
|
60
|
+
async function runList(args) {
|
|
61
|
+
const accountId = resolveAccountIdArg(args);
|
|
62
|
+
const params = { "account-id": accountId };
|
|
63
|
+
if (args["skip-cache"])
|
|
64
|
+
params["skip-cache"] = "true";
|
|
65
|
+
const data = await apiGet("/api/ads/meta/pixels", params);
|
|
66
|
+
emit(data, args);
|
|
67
|
+
}
|
|
68
|
+
function emit(data, args) {
|
|
69
|
+
const fmt = csvOrJson(args);
|
|
70
|
+
if (fmt !== "json") {
|
|
71
|
+
writeAdsOutput(data, fmt);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
writeAdsJson({ ok: true, data });
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=pixels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pixels.js","sourceRoot":"","sources":["../../../../src/commands/ads/meta/pixels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Insights field bundles. Picked for AI agent ergonomics: small, focused field
|
|
3
|
+
* lists that answer one specific question without forcing the AI to enumerate
|
|
4
|
+
* Meta's 500+ insights fields.
|
|
5
|
+
*
|
|
6
|
+
* Two-axis design:
|
|
7
|
+
* --intent (field bundle, default: baseline) — what data to ask for
|
|
8
|
+
* --level (object granularity, default: account) — at what granularity
|
|
9
|
+
*
|
|
10
|
+
* Intents are independent of level — pass `--intent ranking --level ad` to flag
|
|
11
|
+
* creatives, or `--intent revenue --level campaign` for ROAS by campaign.
|
|
12
|
+
*
|
|
13
|
+
* Identity fields (campaign_name etc.) are appended automatically based on
|
|
14
|
+
* level so the AI can read rows without joining.
|
|
15
|
+
*/
|
|
16
|
+
export type InsightsLevel = "account" | "campaign" | "adset" | "ad";
|
|
17
|
+
export type InsightsIntent = "baseline" | "revenue" | "funnel" | "ranking" | "video" | "identity";
|
|
18
|
+
interface IntentDefinition {
|
|
19
|
+
name: InsightsIntent;
|
|
20
|
+
description: string;
|
|
21
|
+
fields: string[];
|
|
22
|
+
/** Action breakdowns to slice the actions[] array — empty if not needed. */
|
|
23
|
+
actionBreakdowns?: string[];
|
|
24
|
+
}
|
|
25
|
+
/** Compose final field list: intent metrics + level-specific identity fields, deduplicated. */
|
|
26
|
+
export declare function composeFields(intent: InsightsIntent, level: InsightsLevel): string[];
|
|
27
|
+
export declare function getIntent(name: string): IntentDefinition | undefined;
|
|
28
|
+
export declare function listIntents(): IntentDefinition[];
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/meta/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,CAAC;AAEpE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAElG,UAAU,gBAAgB;IACxB,IAAI,EAAE,cAAc,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAsDD,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,EAAE,CAYpF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAEpE;AAED,wBAAgB,WAAW,IAAI,gBAAgB,EAAE,CAEhD"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Insights field bundles. Picked for AI agent ergonomics: small, focused field
|
|
3
|
+
* lists that answer one specific question without forcing the AI to enumerate
|
|
4
|
+
* Meta's 500+ insights fields.
|
|
5
|
+
*
|
|
6
|
+
* Two-axis design:
|
|
7
|
+
* --intent (field bundle, default: baseline) — what data to ask for
|
|
8
|
+
* --level (object granularity, default: account) — at what granularity
|
|
9
|
+
*
|
|
10
|
+
* Intents are independent of level — pass `--intent ranking --level ad` to flag
|
|
11
|
+
* creatives, or `--intent revenue --level campaign` for ROAS by campaign.
|
|
12
|
+
*
|
|
13
|
+
* Identity fields (campaign_name etc.) are appended automatically based on
|
|
14
|
+
* level so the AI can read rows without joining.
|
|
15
|
+
*/
|
|
16
|
+
const INSIGHTS_INTENTS = {
|
|
17
|
+
baseline: {
|
|
18
|
+
name: "baseline",
|
|
19
|
+
description: "Spend, impressions, clicks, CTR, CPC, CPM. The default question: 'how is delivery?'",
|
|
20
|
+
fields: ["impressions", "reach", "frequency", "spend", "clicks", "ctr", "cpc", "cpm"],
|
|
21
|
+
},
|
|
22
|
+
revenue: {
|
|
23
|
+
name: "revenue",
|
|
24
|
+
description: "Spend, conversions, action_values, purchase_roas. 'How much money are we making?'",
|
|
25
|
+
fields: ["spend", "actions", "action_values", "conversions", "conversion_values", "purchase_roas"],
|
|
26
|
+
actionBreakdowns: ["action_type"],
|
|
27
|
+
},
|
|
28
|
+
funnel: {
|
|
29
|
+
name: "funnel",
|
|
30
|
+
description: "Impression → click → landing page → action. 'Where do users drop off?'",
|
|
31
|
+
fields: ["impressions", "clicks", "inline_link_clicks", "outbound_clicks", "actions", "spend"],
|
|
32
|
+
actionBreakdowns: ["action_type"],
|
|
33
|
+
},
|
|
34
|
+
ranking: {
|
|
35
|
+
name: "ranking",
|
|
36
|
+
description: "Quality, engagement, conversion-rate rankings. 'Which creatives need a refresh?'",
|
|
37
|
+
fields: ["impressions", "spend", "ctr", "quality_ranking", "engagement_rate_ranking", "conversion_rate_ranking"],
|
|
38
|
+
},
|
|
39
|
+
video: {
|
|
40
|
+
name: "video",
|
|
41
|
+
description: "Watch funnel, thruplay cost. 'How are video creatives holding attention?'",
|
|
42
|
+
fields: [
|
|
43
|
+
"impressions",
|
|
44
|
+
"spend",
|
|
45
|
+
"video_play_actions",
|
|
46
|
+
"video_p25_watched_actions",
|
|
47
|
+
"video_p50_watched_actions",
|
|
48
|
+
"video_p75_watched_actions",
|
|
49
|
+
"video_p100_watched_actions",
|
|
50
|
+
"video_thruplay_watched_actions",
|
|
51
|
+
"cost_per_thruplay",
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
identity: {
|
|
55
|
+
name: "identity",
|
|
56
|
+
description: "Just the names + spend — for cheap roll-up summaries.",
|
|
57
|
+
fields: ["spend", "impressions"],
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
const IDENTITY_FIELDS_BY_LEVEL = {
|
|
61
|
+
account: ["account_id", "account_name", "account_currency"],
|
|
62
|
+
campaign: ["campaign_id", "campaign_name", "objective"],
|
|
63
|
+
adset: ["adset_id", "adset_name", "campaign_id", "campaign_name"],
|
|
64
|
+
ad: ["ad_id", "ad_name", "adset_id", "adset_name", "campaign_id", "campaign_name"],
|
|
65
|
+
};
|
|
66
|
+
/** Compose final field list: intent metrics + level-specific identity fields, deduplicated. */
|
|
67
|
+
export function composeFields(intent, level) {
|
|
68
|
+
const intentFields = INSIGHTS_INTENTS[intent].fields;
|
|
69
|
+
const identity = IDENTITY_FIELDS_BY_LEVEL[level];
|
|
70
|
+
const seen = new Set();
|
|
71
|
+
const out = [];
|
|
72
|
+
for (const f of [...identity, ...intentFields]) {
|
|
73
|
+
if (!seen.has(f)) {
|
|
74
|
+
seen.add(f);
|
|
75
|
+
out.push(f);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
export function getIntent(name) {
|
|
81
|
+
return INSIGHTS_INTENTS[name];
|
|
82
|
+
}
|
|
83
|
+
export function listIntents() {
|
|
84
|
+
return Object.values(INSIGHTS_INTENTS);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../../../src/commands/ads/meta/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAcH,MAAM,gBAAgB,GAA6C;IACjE,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,qFAAqF;QAClG,MAAM,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;KACtF;IACD,OAAO,EAAE;QACP,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,mFAAmF;QAChG,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,mBAAmB,EAAE,eAAe,CAAC;QAClG,gBAAgB,EAAE,CAAC,aAAa,CAAC;KAClC;IACD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,wEAAwE;QACrF,MAAM,EAAE,CAAC,aAAa,EAAE,QAAQ,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,SAAS,EAAE,OAAO,CAAC;QAC9F,gBAAgB,EAAE,CAAC,aAAa,CAAC;KAClC;IACD,OAAO,EAAE;QACP,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,kFAAkF;QAC/F,MAAM,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,yBAAyB,CAAC;KACjH;IACD,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,2EAA2E;QACxF,MAAM,EAAE;YACN,aAAa;YACb,OAAO;YACP,oBAAoB;YACpB,2BAA2B;YAC3B,2BAA2B;YAC3B,2BAA2B;YAC3B,4BAA4B;YAC5B,gCAAgC;YAChC,mBAAmB;SACpB;KACF;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,uDAAuD;QACpE,MAAM,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC;KACjC;CACF,CAAC;AAEF,MAAM,wBAAwB,GAAoC;IAChE,OAAO,EAAE,CAAC,YAAY,EAAE,cAAc,EAAE,kBAAkB,CAAC;IAC3D,QAAQ,EAAE,CAAC,aAAa,EAAE,eAAe,EAAE,WAAW,CAAC;IACvD,KAAK,EAAE,CAAC,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,CAAC;IACjE,EAAE,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,CAAC;CACnF,CAAC;AAEF,+FAA+F;AAC/F,MAAM,UAAU,aAAa,CAAC,MAAsB,EAAE,KAAoB;IACxE,MAAM,YAAY,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IACrD,MAAM,QAAQ,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,EAAE,GAAG,YAAY,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,gBAAgB,CAAC,IAAsB,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const previewCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly "creative-id": {
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly description: "Existing creative ID";
|
|
5
|
+
};
|
|
6
|
+
readonly "ad-id": {
|
|
7
|
+
readonly type: "string";
|
|
8
|
+
readonly description: "Existing ad ID";
|
|
9
|
+
};
|
|
10
|
+
readonly "account-id": {
|
|
11
|
+
readonly type: "string";
|
|
12
|
+
readonly description: "Required when previewing an unpublished --creative spec";
|
|
13
|
+
};
|
|
14
|
+
readonly creative: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly description: "JSON spec of an unpublished creative (e.g. object_story_spec)";
|
|
17
|
+
};
|
|
18
|
+
readonly "ad-format": {
|
|
19
|
+
readonly type: "string";
|
|
20
|
+
readonly description: "Meta ad_format enum value";
|
|
21
|
+
readonly required: true;
|
|
22
|
+
};
|
|
23
|
+
readonly "out-file": {
|
|
24
|
+
readonly type: "string";
|
|
25
|
+
readonly description: "Save iframe HTML to this path";
|
|
26
|
+
};
|
|
27
|
+
readonly "skip-cache": {
|
|
28
|
+
readonly type: "boolean";
|
|
29
|
+
readonly description: "Bypass server-side cache";
|
|
30
|
+
};
|
|
31
|
+
}>;
|
|
32
|
+
//# sourceMappingURL=preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/meta/preview.ts"],"names":[],"mappings":"AAwCA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6CzB,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
import { apiPost } from "../../../client.js";
|
|
4
|
+
import { writeAdsJson } from "../output.js";
|
|
5
|
+
import { handleMetaError } from "./shared.js";
|
|
6
|
+
const VALID_AD_FORMATS = [
|
|
7
|
+
"DESKTOP_FEED_STANDARD",
|
|
8
|
+
"MOBILE_FEED_STANDARD",
|
|
9
|
+
"MOBILE_FEED_BASIC",
|
|
10
|
+
"RIGHT_COLUMN_STANDARD",
|
|
11
|
+
"MOBILE_FULLWIDTH",
|
|
12
|
+
"MOBILE_INTERSTITIAL",
|
|
13
|
+
"MOBILE_BANNER",
|
|
14
|
+
"MOBILE_MEDIUM_RECTANGLE",
|
|
15
|
+
"MOBILE_NATIVE",
|
|
16
|
+
"FACEBOOK_STORY_MOBILE",
|
|
17
|
+
"FACEBOOK_REELS_MOBILE",
|
|
18
|
+
"INSTAGRAM_STORY",
|
|
19
|
+
"INSTAGRAM_REELS",
|
|
20
|
+
"INSTAGRAM_REELS_OVERLAY",
|
|
21
|
+
"INSTAGRAM_STANDARD",
|
|
22
|
+
"INSTAGRAM_EXPLORE_CONTEXTUAL",
|
|
23
|
+
"INSTAGRAM_EXPLORE_GRID_HOME",
|
|
24
|
+
"INSTAGRAM_SHOP",
|
|
25
|
+
"INSTAGRAM_PROFILE_FEED",
|
|
26
|
+
"INSTREAM_VIDEO_DESKTOP",
|
|
27
|
+
"INSTREAM_VIDEO_MOBILE",
|
|
28
|
+
"FACEBOOK_REELS_BANNER",
|
|
29
|
+
"FACEBOOK_REELS_STICKER",
|
|
30
|
+
"MESSENGER_MOBILE_INBOX_MEDIA",
|
|
31
|
+
"MESSENGER_MOBILE_STORY_MEDIA",
|
|
32
|
+
"AUDIENCE_NETWORK_OUTSTREAM_VIDEO",
|
|
33
|
+
"AUDIENCE_NETWORK_INSTREAM_VIDEO_MOBILE",
|
|
34
|
+
"AUDIENCE_NETWORK_REWARDED_VIDEO",
|
|
35
|
+
"INSTANT_ARTICLE_STANDARD",
|
|
36
|
+
"MARKETPLACE_MOBILE",
|
|
37
|
+
"BIZ_DISCO_FEED_MOBILE",
|
|
38
|
+
];
|
|
39
|
+
export const previewCommand = defineCommand({
|
|
40
|
+
meta: {
|
|
41
|
+
name: "preview",
|
|
42
|
+
description: `Generate a Meta-hosted preview iframe for a creative or ad. Returns iframe HTML which you
|
|
43
|
+
can embed or save to a file. The iframe URL contains a short-lived access token — treat as secret.
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
baker ads meta preview --creative-id 6123 --ad-format MOBILE_FEED_STANDARD
|
|
47
|
+
baker ads meta preview --ad-id 9988 --ad-format INSTAGRAM_REELS --out-file /tmp/preview.html
|
|
48
|
+
baker ads meta preview --account-id act_123 --creative '{"object_story_spec":{...}}' --ad-format MOBILE_FEED_STANDARD`,
|
|
49
|
+
},
|
|
50
|
+
args: {
|
|
51
|
+
"creative-id": { type: "string", description: "Existing creative ID" },
|
|
52
|
+
"ad-id": { type: "string", description: "Existing ad ID" },
|
|
53
|
+
"account-id": { type: "string", description: "Required when previewing an unpublished --creative spec" },
|
|
54
|
+
creative: { type: "string", description: "JSON spec of an unpublished creative (e.g. object_story_spec)" },
|
|
55
|
+
"ad-format": { type: "string", description: "Meta ad_format enum value", required: true },
|
|
56
|
+
"out-file": { type: "string", description: "Save iframe HTML to this path" },
|
|
57
|
+
"skip-cache": { type: "boolean", description: "Bypass server-side cache" },
|
|
58
|
+
},
|
|
59
|
+
run: async ({ args }) => {
|
|
60
|
+
const adFormat = args["ad-format"];
|
|
61
|
+
if (!VALID_AD_FORMATS.includes(adFormat)) {
|
|
62
|
+
handleMetaError(new Error(`Invalid --ad-format "${adFormat}". Run with --help to see supported values.`));
|
|
63
|
+
}
|
|
64
|
+
const body = { adFormat };
|
|
65
|
+
if (args["creative-id"])
|
|
66
|
+
body.creativeId = args["creative-id"];
|
|
67
|
+
if (args["ad-id"])
|
|
68
|
+
body.adId = args["ad-id"];
|
|
69
|
+
if (args["account-id"])
|
|
70
|
+
body.accountId = args["account-id"];
|
|
71
|
+
if (args.creative)
|
|
72
|
+
body.creative = args.creative;
|
|
73
|
+
if (args["skip-cache"])
|
|
74
|
+
body.skipCache = true;
|
|
75
|
+
try {
|
|
76
|
+
const data = await apiPost("/api/ads/meta/preview", body);
|
|
77
|
+
const html = data.map((d) => d.body).join("\n");
|
|
78
|
+
if (args["out-file"]) {
|
|
79
|
+
writeFileSync(args["out-file"], html, "utf-8");
|
|
80
|
+
writeAdsJson({ ok: true, data: { file: args["out-file"], rows: data.length } });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
writeAdsJson({ ok: true, data });
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
handleMetaError(err);
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=preview.js.map
|