@wrangled/cli 0.3.35 → 0.3.36
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 +4 -4
- package/dist/main.js +8 -6
- package/dist/playbooks.js +18 -2
- package/package.json +1 -1
package/dist/guide.js
CHANGED
|
@@ -40,13 +40,13 @@ ${brand.name} does not build pages; it hands whoever builds one what is already
|
|
|
40
40
|
|
|
41
41
|
## Which Facebook ads and pages won: winners and flops
|
|
42
42
|
|
|
43
|
-
\`${cli} winners\` says which Facebook ads won and which flopped, for one Monday-to-Sunday week and for the 30 days ending that Sunday, judged on real sales: each sale goes to the Facebook ad that first brought the buyer in, and payments typed into GoHighLevel by hand never count toward an ad. An ad with no sales that has spent less than twice the account's cost per sale is too new to judge on sales, so it is judged on cost per sign-up and listed apart. Each ad says in a sentence why it is on its list. It judges the landing pages the ads sent people to the same way, and each ad on each page as an ad-and-page pair: a page or pair counts only once the page reader has read the page and it got at least 100 visits in the dates, and pairs are listed only for an ad that sent people to two or more pages, or a page that got people from two or more ads, each naming what the same ad cost on its other pages. \`--week <YYYY-MM-DD>\` picks any day of the week (default: the latest complete week), \`--top <n>\` how many ads, pages or pairs each list shows (default 5, at most 20), and \`--format json\` gives the report as data.
|
|
43
|
+
\`${cli} winners\` says which Facebook ads won and which flopped, for one Monday-to-Sunday week and for the 30 days ending that Sunday, judged on real sales: each sale goes to the Facebook ad that first brought the buyer in, and payments typed into GoHighLevel by hand never count toward an ad. An ad with no sales that has spent less than twice the account's cost per sale is too new to judge on sales, so it is judged on cost per sign-up and listed apart. Each ad says in a sentence why it is on its list. Each currency also says how many of its Facebook sales could be tied to a specific ad (\`adSales\` of \`facebookSales\` in the JSON): a sale whose link names no single ad counts toward Facebook but toward no ad. It judges the landing pages the ads sent people to the same way, and each ad on each page as an ad-and-page pair: a page or pair counts only once the page reader has read the page and it got at least 100 visits in the dates, and pairs are listed only for an ad that sent people to two or more pages, or a page that got people from two or more ads, each naming what the same ad cost on its other pages. \`--week <YYYY-MM-DD>\` picks any day of the week (default: the latest complete week), \`--top <n>\` how many ads, pages or pairs each list shows (default 5, at most 20), and \`--format json\` gives the report as data.
|
|
44
44
|
|
|
45
45
|
## What winners and flops taught: lessons
|
|
46
46
|
|
|
47
|
-
Lessons are short plain sentences about why the winners won and the flops flopped, such as "Ads that open with a retiree's own money worry beat ads that open with a statistic: 4 of the top 5 this week, cost per sale $180 vs $410." A finished page or funnel test,
|
|
47
|
+
Lessons are short plain sentences about why the winners won and the flops flopped, such as "Ads that open with a retiree's own money worry beat ads that open with a statistic: 4 of the top 5 this week, cost per sale $180 vs $410." A finished page or funnel test, something learned about a funnel step, or a follow-up email, text or sequence that helps sales makes a lesson too. Each lists what proves it: ads, pages, funnel steps, tests, emails, texts or sequences. A lesson that holds on an ad and an email is one lesson with both as proof. Read them before writing ads or pages: \`${cli} lessons\` lists the ones that hold, the most often seen first (\`--status retired\` lists the ones no longer true, with why; \`--about ads|pages|funnel|messages\` only the ones with a proof of that kind, \`--about cross_channel\` only the ones proven on two or more of ads, pages and messages; \`--dimension <d>\`, repeatable, only the ones along that dimension), and the brief carries them too. No person approves a lesson.
|
|
48
48
|
|
|
49
|
-
Write one as JSON, \`{"text": "...", "dimension": "hook", "evidence": [{"ad": "<Meta ad id or SKU>", "numbers": "cost per sale $180 vs $410"}], "week": "2026-09-28"}\`, and run \`${cli} lessons add --file lesson.json\`. Each proof names exactly one of \`ad\`, \`page\` (a page's URL, kept as its page key, or a content item id), \`step\` (\`<funnel_key>.<step_key>\`)
|
|
49
|
+
Write one as JSON, \`{"text": "...", "dimension": "hook", "evidence": [{"ad": "<Meta ad id or SKU>", "numbers": "cost per sale $180 vs $410"}], "week": "2026-09-28"}\`, and run \`${cli} lessons add --file lesson.json\`. Each proof names exactly one of \`ad\`, \`page\` (a page's URL, kept as its page key, or a content item id), \`step\` (\`<funnel_key>.<step_key>\`), \`test\` (a funnel test id or Adzara test_id), \`message\` (an email or text's content item id, or its SKU, kept as its item id; one the content library does not have is refused) or \`sequence\` (\`ghl:<workflow id>\` or \`klaviyo:<flow id>\`), with its \`numbers\`. \`dimension\` (hook, angle, format, offer, persona, page, funnel_step, follow_up or other) and \`week\` (any day of the winners report's week; default the latest complete week) are optional. A lesson with the same words that still holds, or the one named in \`"reinforces": "<id>"\`, is reinforced instead of copied: it counts once more for a week it had not counted, so running the same week again changes no count. \`${cli} lessons retire <id> --note "<why>"\` retires one the numbers no longer back; it is kept with why. The \`lessons\` playbook (\`${cli} skill install lessons\` installs it as the \`${LESSONS_SKILL_NAME}\` skill) writes the week's lessons from the winners report.
|
|
50
50
|
|
|
51
51
|
## Sending winners to Exodus
|
|
52
52
|
|
|
@@ -348,7 +348,7 @@ ${cli} funnels evidence prices paid, buyer paths, GoHighLevel funnels, calenda
|
|
|
348
348
|
${cli} funnels draft --file <map.json> [--note <why>] [--evidence '<json>' | @file.json] [--based-on <n>] [--counts-from fix|<date>] [--questions @file.json] save the whole map; it goes live when every step can be counted
|
|
349
349
|
${cli} facts [--kind <kind>] [--subject <type>[:<ref>]] [--status <status>] [--json] | facts show <id> settled facts about the data, to treat as true
|
|
350
350
|
${cli} facts propose --file <fact.json> suggest a fact for a person to confirm
|
|
351
|
-
${cli} lessons [--status active|retired] [--about ads|pages|funnel] [--dimension <d>] | lessons add --file <lesson.json> | lessons retire <id> --note "<why>" lessons from winners and flops, writing one, retiring one
|
|
351
|
+
${cli} lessons [--status active|retired] [--about ads|pages|funnel|messages|cross_channel] [--dimension <d>] | lessons add --file <lesson.json> | lessons retire <id> --note "<why>" lessons from winners and flops, writing one, retiring one
|
|
352
352
|
${cli} tests [--status <status>] [--funnel <key>] [--limit <n>] | tests show <id> | tests draft --file <test.json> | tests start <id> | tests abandon <id> [--note "<why>"] funnel tests, one change each
|
|
353
353
|
${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
|
|
354
354
|
${cli} ads autotag [--limit <n>] [--ad <id>] have the server propose tags for the biggest spenders not yet tagged
|
package/dist/main.js
CHANGED
|
@@ -1401,10 +1401,10 @@ const commands = {
|
|
|
1401
1401
|
},
|
|
1402
1402
|
},
|
|
1403
1403
|
lessons: {
|
|
1404
|
-
usage: "lessons [list] [--status active|retired] [--about ads|pages|funnel] [--dimension <d>]... what earlier weeks' winners and flops
|
|
1404
|
+
usage: "lessons [list] [--status active|retired] [--about ads|pages|funnel|messages|cross_channel] [--dimension <d>]... what earlier weeks' winners and flops, page and funnel tests, and follow-up emails and texts taught, the most often seen first",
|
|
1405
1405
|
async run(args, options) {
|
|
1406
1406
|
if (!(args.length === 0 || (args.length === 1 && args[0] === "list"))) {
|
|
1407
|
-
throw new CliError("Usage: lessons [list] [--status active|retired] [--about ads|pages|funnel] [--dimension <d>]...", exitCodes.usage);
|
|
1407
|
+
throw new CliError("Usage: lessons [list] [--status active|retired] [--about ads|pages|funnel|messages|cross_channel] [--dimension <d>]...", exitCodes.usage);
|
|
1408
1408
|
}
|
|
1409
1409
|
const params = new URLSearchParams();
|
|
1410
1410
|
if (options.status)
|
|
@@ -1425,7 +1425,7 @@ const commands = {
|
|
|
1425
1425
|
},
|
|
1426
1426
|
},
|
|
1427
1427
|
"lessons add": {
|
|
1428
|
-
usage: "lessons add --file <lesson.json> | < lesson.json write down a lesson with the ads, pages, funnel steps or
|
|
1428
|
+
usage: "lessons add --file <lesson.json> | < lesson.json write down a lesson with the ads, pages, funnel steps, tests, emails, texts or sequences that prove it, or reinforce the one it repeats",
|
|
1429
1429
|
async run(args, options) {
|
|
1430
1430
|
if (args.length > 0)
|
|
1431
1431
|
throw new CliError("Usage: lessons add --file <lesson.json> | < lesson.json", exitCodes.usage);
|
|
@@ -2053,9 +2053,10 @@ function winnersWindowText(title, window) {
|
|
|
2053
2053
|
: s.accountCostPerSale === null
|
|
2054
2054
|
? "no sale credited to a Facebook ad in these dates"
|
|
2055
2055
|
: `the account paid ${money(s.accountCostPerSale, s.currency)} per sale`;
|
|
2056
|
+
const tied = s.adSales === null || !s.facebookSales ? "" : ` ${s.adSales} of ${counted(s.facebookSales, "Facebook sale")} could be tied to a specific ad.`;
|
|
2056
2057
|
const tests = s.tests.map((t) => `- Test ${t.testId}${t.hypothesisId ? ` (idea ${t.hypothesisId})` : ""}: ${counted(t.ads.length, "ad")}, spent ${money(t.spend, s.currency)}, ${counted(t.sales, "sale")}` +
|
|
2057
2058
|
`${t.costPerSale === null ? "" : `, ${money(t.costPerSale, s.currency)} per sale`}\n`);
|
|
2058
|
-
return (`\nIn ${s.currency}: ${account}
|
|
2059
|
+
return (`\nIn ${s.currency}: ${account}.${tied} ${s.adsJudgedOnSales} judged on sales, ${s.adsJudgedOnSignups} judged on sign-ups.\n` +
|
|
2059
2060
|
s.notes.map((note) => `${note}\n`).join("") +
|
|
2060
2061
|
list("Winners", s.winners) +
|
|
2061
2062
|
list("Flops", s.flops) +
|
|
@@ -2349,8 +2350,9 @@ Options:
|
|
|
2349
2350
|
--notes <text> what changed in the version skill publish adds
|
|
2350
2351
|
--note <why> why: what content create and edit changed, why lessons retire says a lesson is no longer true,
|
|
2351
2352
|
or why tests abandon drops one
|
|
2352
|
-
--about
|
|
2353
|
-
|
|
2353
|
+
--about <a> with lessons, only the lessons with a proof about ads, pages, funnel (steps and tests) or messages
|
|
2354
|
+
(emails, texts and sequences), or cross_channel: proven on two or more of ads, pages and messages
|
|
2355
|
+
--dimension <d> with lessons, only the lessons along that dimension (hook, angle, format, offer, persona, page, funnel_step, follow_up, other); repeat for several
|
|
2354
2356
|
--version <n> the map version funnels show prints (default: the confirmed one)
|
|
2355
2357
|
--based-on <n> the map version funnels draft was written from; refused when someone saved since
|
|
2356
2358
|
(leave it out only for the first map, when there is neither a map nor a draft)
|
package/dist/playbooks.js
CHANGED
|
@@ -1437,6 +1437,16 @@ export const lessonsExample = {
|
|
|
1437
1437
|
],
|
|
1438
1438
|
week: "2026-09-28",
|
|
1439
1439
|
};
|
|
1440
|
+
/** A lesson proven on an ad and an email, exported so a test checks the server accepts it. */
|
|
1441
|
+
export const lessonsMessageExample = {
|
|
1442
|
+
text: "The retiree money-worry angle that wins on Facebook also wins in the no-show email: the top ad and the top email this week.",
|
|
1443
|
+
dimension: "angle",
|
|
1444
|
+
evidence: [
|
|
1445
|
+
{ ad: "ABC-000123", numbers: "cost per sale $180 vs $410 for the account" },
|
|
1446
|
+
{ message: "ABC-000140", numbers: "2.1 sales per 1,000 sent vs 0.6" },
|
|
1447
|
+
],
|
|
1448
|
+
week: "2026-09-28",
|
|
1449
|
+
};
|
|
1440
1450
|
/** A lesson proven by a page and a test, exported so a test checks the server accepts it. */
|
|
1441
1451
|
export const lessonsPageExample = {
|
|
1442
1452
|
text: "A short video at the top of the webinar sign-up page beat the long letter: 38% sign-ups vs 29%.",
|
|
@@ -1454,7 +1464,7 @@ You work only through the \`${cli}\` CLI. Every command acts on the one workspac
|
|
|
1454
1464
|
|
|
1455
1465
|
## Rules that never bend
|
|
1456
1466
|
|
|
1457
|
-
- **Every lesson rests on
|
|
1467
|
+
- **Every lesson rests on proof and numbers.** Name at least one ad (its Meta ad id, or its SKU when it has one), or the page, funnel step, test, email, text or sequence that shows it, and quote the numbers as the report gives them. A thread seen in one ad or one email is a hunch, not a lesson: write it only when two or more show it, or one against the account's cost per sale by a wide margin.
|
|
1458
1468
|
- **Plain and short.** One or two sentences a business owner reads in five seconds, with the numbers in them: "Ads that open with a retiree's own money worry beat ads that open with a statistic: 4 of the top 5 this week, cost per sale $180 vs $410."
|
|
1459
1469
|
- **Sales first.** Judge on what the report judges on sales. A lesson from ads judged on sign-ups says so in its words.
|
|
1460
1470
|
- **Never add up money across currencies.** The report gives one section per currency; a lesson quotes one currency's numbers.
|
|
@@ -1494,6 +1504,12 @@ Ads are not the only proof. When the week's winners point at the page they send
|
|
|
1494
1504
|
${JSON.stringify(lessonsPageExample)}
|
|
1495
1505
|
\`\`\`
|
|
1496
1506
|
|
|
1507
|
+
Follow-up emails, texts and sequences are proof too. Name an email or text as \`message\` (its content item id, or its SKU when it was made here; one the content library does not have is refused) and a whole sequence as \`sequence\` (\`ghl:<workflow id>\` for a GoHighLevel workflow, \`klaviyo:<flow id>\` for a Klaviyo flow), and use the \`follow_up\` dimension for a lesson about them alone. When the same thread wins on an ad and in an email, write it as one lesson with both as proof, not one lesson per channel:
|
|
1508
|
+
|
|
1509
|
+
\`\`\`json
|
|
1510
|
+
${JSON.stringify(lessonsMessageExample)}
|
|
1511
|
+
\`\`\`
|
|
1512
|
+
|
|
1497
1513
|
Then:
|
|
1498
1514
|
|
|
1499
1515
|
\`\`\`sh
|
|
@@ -1520,7 +1536,7 @@ Finish with a short report in plain words for the owner: the lessons you added,
|
|
|
1520
1536
|
|
|
1521
1537
|
\`\`\`
|
|
1522
1538
|
${cli} winners [--week <YYYY-MM-DD>] --format json the week's winners and flops, with each ad's tags
|
|
1523
|
-
${cli} lessons [--status active|retired] [--about ads|pages|funnel] --format json the lessons that hold, or the retired ones
|
|
1539
|
+
${cli} lessons [--status active|retired] [--about ads|pages|funnel|messages|cross_channel] --format json the lessons that hold, or the retired ones
|
|
1524
1540
|
${cli} ads tags --ad <ad id> --format json one ad's marketing tags
|
|
1525
1541
|
${cli} lessons add --file <lesson.json> write a lesson, or reinforce the one it repeats
|
|
1526
1542
|
${cli} lessons retire <id> --note "<why>" retire a lesson the numbers no longer back
|