@wrangled/cli 0.3.27 → 0.3.28

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 CHANGED
@@ -195,7 +195,7 @@ For what worked, query the \`ad_performance_tagged\` view: every Meta ad's daily
195
195
 
196
196
  Emails, text messages and landing pages in the content library get the same grammar's tags, by content item id. \`${cli} content tags [<item-id>]\` lists them (\`--kind email|text|page\`, \`--status proposed|confirmed|rejected|replaced\`, \`--limit <n>\`, \`--json\`); by default the live ones. Each row names the version of the item's words it describes (\`contentHash\`). Only the parts that fit the kind are filled: an email's or text's job (invite, reminder, last chance and so on), no job for a page, and no secondary hook for a text, whose format (sms or mms) comes from whether it carries a picture.
197
197
 
198
- To have the server tag them, run \`${cli} content autotag\` (\`--limit <n>\`, 1 to 100, default 25; \`--kind email,text\` to narrow; item ids as arguments for those items; \`--json\`). It takes the items whose current words have no tags yet, the ones that brought in the most sales first, then the most clicks, then the newest, so a repeat run spends nothing on what it already tagged. Items that read the same, such as one email sent to several lists, are asked about once and share the tags. An email whose body was never stored is asked only whether it is marketing, its hook and its job. When an item's words change, its next run replaces its tags, even confirmed ones, since a person confirmed the old words. \`${cli} content to-check\` lists the emails and texts whose tags wait for a person, most sales first, then most clicks; the same rows are in the \`content_tags\` table.
198
+ To have the server tag them, run \`${cli} content autotag\` (\`--limit <n>\`, 1 to 100, default 25; \`--kind email,text\` to narrow; item ids as arguments for those items; \`--json\`). It takes the items whose current words have no tags yet, the ones that brought in the most sales first, then the most clicks, then the newest, so a repeat run spends nothing on what it already tagged. Items that read the same, such as one email sent to several lists, are asked about once and share the tags. An email whose body was never stored is asked only whether it is marketing, its hook and its job. When an item's words change, its next run replaces its tags, even confirmed ones, since a person confirmed the old words. \`${cli} content to-check\` lists the emails, texts and landing pages whose tags wait for a person, most sales first, then most clicks; the same rows are in the \`content_tags\` table.
199
199
 
200
200
  ## Ad words
201
201
 
package/dist/main.js CHANGED
@@ -1277,7 +1277,7 @@ const commands = {
1277
1277
  },
1278
1278
  },
1279
1279
  "content to-check": {
1280
- usage: "content to-check [--limit <n>] [--json] the emails and texts whose tags wait for a person, most sales first, then most clicks",
1280
+ usage: "content to-check [--limit <n>] [--json] the emails, texts and landing pages whose tags wait for a person, most sales first, then most clicks",
1281
1281
  async run(args, options) {
1282
1282
  if (args.length > 0)
1283
1283
  throw new CliError("Usage: content to-check [--limit <n>] [--json]", exitCodes.usage);
@@ -1286,7 +1286,7 @@ const commands = {
1286
1286
  if (options.format === "json")
1287
1287
  return printJson({ tags });
1288
1288
  if (tags.length === 0)
1289
- return console.log("No email or text tags wait for a person.");
1289
+ return console.log("No email, text or landing page tags wait for a person.");
1290
1290
  console.log(renderTable(["item", "kind", "revenue", "clicks", ...CONTENT_TAG_COLUMNS.slice(4)], tags.map((t) => ({ ...contentTagRow(t), revenue: t.revenue, clicks: t.clicks }))));
1291
1291
  },
1292
1292
  },
@@ -2593,10 +2593,25 @@ function printContent(content, format) {
2593
2593
  versions: content.versions && content.versions.length > 1 ? content.versions.length : null,
2594
2594
  transcript: content.transcripts?.map((t) => (t.text ? excerpt(t.text, 80) : t.status)).join(" | ") || null,
2595
2595
  description: descriptionLine(content.descriptions?.find((d) => d.version === version.version)),
2596
+ shape: content.shape ? shapeLine(content.shape) : null,
2596
2597
  ...scoreFields(content.scorecards ?? []),
2597
2598
  };
2598
2599
  printFields(rows);
2599
2600
  }
2601
+ /** A page's shape in one line: "640 words, 3 sections, first ask 20% down, video, 2 pictures, 1 button, 3 form fields, price shown". */
2602
+ function shapeLine(shape) {
2603
+ const plural = (n, word) => `${n} ${word}${n === 1 ? "" : "s"}`;
2604
+ return [
2605
+ plural(shape.words, "word"),
2606
+ plural(shape.sections, "section"),
2607
+ shape.firstAskAt === null ? "no form or button" : `first ask ${Math.round(shape.firstAskAt * 100)}% down`,
2608
+ shape.hasVideo ? "video" : "no video",
2609
+ plural(shape.images, "picture"),
2610
+ plural(shape.buttons, "button"),
2611
+ plural(shape.formFields, "form field"),
2612
+ shape.priceShown ? "price shown" : "no price",
2613
+ ].join(", ");
2614
+ }
2600
2615
  /** The current version's picture description in one line: its kind, and the words printed on it. */
2601
2616
  function descriptionLine(d) {
2602
2617
  if (!d)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrangled/cli",
3
- "version": "0.3.27",
3
+ "version": "0.3.28",
4
4
  "description": "Command-line access to your marketing data warehouse, for people and coding agents",
5
5
  "type": "module",
6
6
  "bin": {