@wrangled/cli 0.3.14 → 0.3.15
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/dist/guide.js +3 -0
- package/dist/main.js +30 -2
- package/package.json +1 -1
package/dist/guide.js
CHANGED
|
@@ -172,6 +172,8 @@ Ads not made here (built by hand or by an agency, names in no pattern) get the m
|
|
|
172
172
|
|
|
173
173
|
To suggest tags, write them as JSON and run \`${cli} ads tag --file tags.json\` (or pipe it on stdin), up to 500 ads at a time: \`{"ads": [{"ad_id": "120214567890123", "tags": {"angle": "discovery", "desire": "money", "hook_spot": "spoken", "hook_text": "$29,000 is the smallest lead", "hook_kind": "big_win", "format": "video", "style": "presenter", "tag_reasons": {"worry": "none"}}, "confidence": "medium", "evidence": {"ad_name": "County lead v2", "transcript_start": "$29,000 is the smallest lead"}}]}\`. The tag fields are \`marketing\`, \`offer_key\`, \`landing_funnel_key\`, \`landing_step_key\`, \`persona\`, \`awareness\`, \`concept\`, \`angle\`, \`desire\`, \`hook_spot\`, \`hook_text\`, \`hook_kind\`, \`hook2_spot\`, \`hook2_kind\`, \`format\`, \`style\`, \`speaker\`, \`cta\`, \`proof\` and \`worry\`; leave out what you did not judge. A part with no value goes in \`tag_reasons\` as \`none\` (nothing on its list applies) or \`unclear\` (too little to judge, never \`high\` confidence). Confidence is \`high\`, \`medium\` or \`low\`. A value off its list is refused with the allowed values. New tags replace an ad's proposed ones, which stay as \`replaced\`; an ad whose tags a person confirmed is kept as it is.
|
|
174
174
|
|
|
175
|
+
To have the server tag ads for you, run \`${cli} ads autotag\` (\`--limit <n>\`, 1 to 100, default 25; \`--ad <id>\` for one ad; \`--json\`). It takes the biggest spenders with no tags yet, so each run moves on to the next ones (with \`--ad\`, that ad, its proposed tags asked about again and confirmed ones kept), reads each one's copy, video transcript and picture description, and asks TypeSafe's Jev the grammar's questions through the tool gateway, so a run's tool cap applies. Ads with the same copy, headlines, button, link and media are asked about once and share the tags; asking again about an unchanged ad costs nothing. It costs a tiny fraction of a cent per ad. The tags are proposed, with each part's confidence in the evidence; read them with \`${cli} ads tags\`.
|
|
176
|
+
|
|
175
177
|
For what worked, query the \`ad_performance_tagged\` view: every Meta ad's daily results with its live tags next to them, \`tags_source\` (\`ad_tags\`, or null when untagged) and \`tags_status\`.
|
|
176
178
|
|
|
177
179
|
## Ad words
|
|
@@ -285,6 +287,7 @@ ${cli} funnels draft --file <map.json> [--note <why>] [--evidence '<json>' | @fi
|
|
|
285
287
|
${cli} facts [--kind <kind>] [--subject <type>[:<ref>]] [--status <status>] [--json] | facts show <id> settled facts about the data, to treat as true
|
|
286
288
|
${cli} facts propose --file <fact.json> suggest a fact for a person to confirm
|
|
287
289
|
${cli} ads tags [--ad <id>] [--status <status>] [--limit <n>] | ads tag --file <tags.json> the marketing tags of ads not made here, and suggesting them
|
|
290
|
+
${cli} ads autotag [--limit <n>] [--ad <id>] have the server propose tags for the biggest spenders not yet tagged
|
|
288
291
|
${cli} grammar [--format json] every list ads are tagged from, this client's personas and concepts included
|
|
289
292
|
${cli} grammar propose --file <values.json> suggest personas and concepts for a person to confirm
|
|
290
293
|
${cli} voice [--kind opener|objection|phrase] [--limit <n>] [--json] what customers keep saying, grouped and counted, with real quotes
|
package/dist/main.js
CHANGED
|
@@ -1156,6 +1156,32 @@ const commands = {
|
|
|
1156
1156
|
console.log(`Kept as they are, since a person confirmed their tags: ${result.kept.map((k) => k.adId).join(", ")}.`);
|
|
1157
1157
|
},
|
|
1158
1158
|
},
|
|
1159
|
+
"ads autotag": {
|
|
1160
|
+
usage: "ads autotag [--limit <n>] [--ad <id>] [--json] propose marketing tags for the biggest-spending ads not yet tagged, or one ad",
|
|
1161
|
+
async run(args, options) {
|
|
1162
|
+
if (args.length > 0)
|
|
1163
|
+
throw new CliError("Usage: ads autotag [--limit <n>] [--ad <id>] [--json]", exitCodes.usage);
|
|
1164
|
+
const body = { ...(options.ad ? { ad_ids: [options.ad] } : {}), ...(options.limit ? { limit: Number(options.limit) } : {}) };
|
|
1165
|
+
const result = await api(await resolveConnection(options.apiUrl), AD_AUTOTAG_PATH, body);
|
|
1166
|
+
if (options.format === "json")
|
|
1167
|
+
return printJson(result);
|
|
1168
|
+
const plural = (n) => `${n} ${n === 1 ? "ad" : "ads"}`;
|
|
1169
|
+
console.log(`Proposed tags for ${plural(result.proposed.length)}, asking about ${result.creatives} ${result.creatives === 1 ? "creative" : "creatives"} for $${result.costUsd.toFixed(4)}. A person confirms or rejects them in the app.`);
|
|
1170
|
+
if (result.proposed.length > 0)
|
|
1171
|
+
console.log(renderTable(["ad", "id", "confidence"], result.proposed.map((p) => ({ ad: p.adId, id: p.id, confidence: p.confidence }))));
|
|
1172
|
+
if (result.kept.length > 0)
|
|
1173
|
+
console.log(`Kept as they are, since a person confirmed their tags: ${result.kept.join(", ")}.`);
|
|
1174
|
+
for (const reason of ["not_marketing", "gate_unclear", "no_content", "not_found"]) {
|
|
1175
|
+
const ids = result.skipped.filter((s) => s.reason === reason).map((s) => s.adId);
|
|
1176
|
+
if (ids.length > 0)
|
|
1177
|
+
console.log(`${SKIP_REASONS[reason]}: ${ids.join(", ")}.`);
|
|
1178
|
+
}
|
|
1179
|
+
for (const failure of result.failed)
|
|
1180
|
+
console.log(`Failed for ${failure.adIds.join(", ")}: ${failure.error}`);
|
|
1181
|
+
if (result.stopped === "tool_cap")
|
|
1182
|
+
console.log("Stopped early: the run's tool spending cap was reached.");
|
|
1183
|
+
},
|
|
1184
|
+
},
|
|
1159
1185
|
"facts show": {
|
|
1160
1186
|
usage: "facts show <id> one fact with its value and evidence",
|
|
1161
1187
|
async run(args, options) {
|
|
@@ -1683,6 +1709,8 @@ function printReport(title, report, labels, numbers) {
|
|
|
1683
1709
|
const agentPath = (options) => `/api/v1/agents/${encodeURIComponent(options.agent)}`;
|
|
1684
1710
|
const FACTS_PATH = "/api/v1/facts";
|
|
1685
1711
|
const AD_TAGS_PATH = "/api/v1/ad-tags";
|
|
1712
|
+
const AD_AUTOTAG_PATH = "/api/v1/ad-tags/autotag";
|
|
1713
|
+
const SKIP_REASONS = { not_marketing: "Not marketing, so only that answer was saved", gate_unclear: "Could not tell whether it is marketing, so only that was saved", no_content: "Nothing to read", not_found: "No such ad" };
|
|
1686
1714
|
const AD_TAG_COLUMNS = ["id", "ad", "status", "confidence", "offer", "persona", "angle", "hook", "format", "author"];
|
|
1687
1715
|
const GRAMMAR_PATH = "/api/v1/grammar";
|
|
1688
1716
|
const VOICE_LISTS_PATH = "/api/v1/voice-lists";
|
|
@@ -1818,9 +1846,9 @@ Options:
|
|
|
1818
1846
|
--from, --to <n> with content diff, the two versions to compare (default: the one before the current one, and the current one)
|
|
1819
1847
|
--sort <column> how content search sorts: recent (default) or a content_scorecard number, such as click_rate or roas
|
|
1820
1848
|
--order desc|asc content search's sort direction (default: desc, best or newest first)
|
|
1821
|
-
--limit <n> how many results content search, creatives list, campaigns, voice and ads tags return
|
|
1849
|
+
--limit <n> how many results content search, creatives list, campaigns, voice and ads tags return, or how many ads ads autotag tags
|
|
1822
1850
|
--library <slug> with knowledge search, only this library, such as creative-cartel
|
|
1823
|
-
--ad <id> with ads tags, only this Meta ad's tags
|
|
1851
|
+
--ad <id> with ads tags, only this Meta ad's tags; with ads autotag, only this ad
|
|
1824
1852
|
--max-seconds <n> stop a runner's run after this many seconds, if that comes before its deadline
|
|
1825
1853
|
--workspace <slug> for worker promote and worker drop: the workspace whose hand they change
|
|
1826
1854
|
-h, --help show this help
|