[object Object]

← back to Pattern Vault

etsy: split compound tags into <=20-char atoms instead of dropping them (contrarian fix — was leaving 6 generic tags/listing; now min 7/avg 8.6)

71cadbe1ff82349c23e96128e0dfe05fd50c4395 · 2026-07-04 10:10:08 -0700 · Steve Abrams

Files touched

Diff

commit 71cadbe1ff82349c23e96128e0dfe05fd50c4395
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sat Jul 4 10:10:08 2026 -0700

    etsy: split compound tags into <=20-char atoms instead of dropping them (contrarian fix — was leaving 6 generic tags/listing; now min 7/avg 8.6)
---
 data/etsy-listings-plan.json | 37 ++++++++++++++++++++++++++++++++++---
 scripts/etsy-list.mjs        | 18 +++++++++++++++---
 2 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/data/etsy-listings-plan.json b/data/etsy-listings-plan.json
index e8361f1..a4fad58 100644
--- a/data/etsy-listings-plan.json
+++ b/data/etsy-listings-plan.json
@@ -50,12 +50,19 @@
         "type": "download",
         "is_supply": false,
         "tags": [
+          "muybridge",
+          "plate",
+          "saddle",
+          "mocha",
           "seamless pattern",
           "original design",
           "wallpaper",
           "surface design",
           "repeat pattern",
-          "print ready"
+          "print ready",
+          "Muybridge",
+          "style",
+          "sequential"
         ],
         "should_auto_renew": false
       },
@@ -76,12 +83,18 @@
         "type": "download",
         "is_supply": false,
         "tags": [
+          "chinoiserie",
+          "champagne",
+          "linen",
           "seamless pattern",
           "original design",
           "wallpaper",
           "surface design",
           "repeat pattern",
-          "print ready"
+          "print ready",
+          "Hand",
+          "painted",
+          "look"
         ],
         "should_auto_renew": false
       },
@@ -336,6 +349,9 @@
         "type": "download",
         "is_supply": false,
         "tags": [
+          "designer",
+          "scenic",
+          "chamois",
           "seamless pattern",
           "original design",
           "wallpaper",
@@ -363,6 +379,9 @@
         "type": "download",
         "is_supply": false,
         "tags": [
+          "geometric",
+          "block",
+          "leaves",
           "seamless pattern",
           "original design",
           "wallpaper",
@@ -468,6 +487,10 @@
         "type": "download",
         "is_supply": false,
         "tags": [
+          "muybridge",
+          "plate",
+          "saddle",
+          "mocha",
           "seamless pattern",
           "original design",
           "wallpaper",
@@ -495,12 +518,17 @@
         "type": "download",
         "is_supply": false,
         "tags": [
+          "chinoiserie",
+          "smoke",
+          "ash",
           "seamless pattern",
           "original design",
           "wallpaper",
           "surface design",
           "repeat pattern",
-          "print ready"
+          "print ready",
+          "Chinoiserie",
+          "branchwork"
         ],
         "should_auto_renew": false
       },
@@ -547,6 +575,9 @@
         "type": "download",
         "is_supply": false,
         "tags": [
+          "stripe",
+          "antique",
+          "brass",
           "seamless pattern",
           "original design",
           "wallpaper",
diff --git a/scripts/etsy-list.mjs b/scripts/etsy-list.mjs
index 3b31039..6c077ae 100644
--- a/scripts/etsy-list.mjs
+++ b/scripts/etsy-list.mjs
@@ -71,13 +71,25 @@ const rows = raw.slice(1).map((r) => ({
 
 // Etsy caps: title <=140 chars; <=13 tags, each <=20 chars.
 const clampTitle = (t) => (t.length <= 140 ? t : t.slice(0, 137).trimEnd() + '…');
-const clampTags = (tags) => tags.filter((t) => t.length <= 20).slice(0, 13);
+// Etsy caps tags at 20 chars. DON'T drop long tags (that silently kills the most distinctive
+// compound tags like "muybridge-plate · saddle-mocha") — split them into <=20-char atoms so the
+// differentiating terms survive. Dedupe, keep order, cap at 13.
+const clampTags = (tags) => {
+  const atoms = [];
+  for (const t of tags) {
+    const s = t.trim();
+    if (!s) continue;
+    if (s.length <= 20) atoms.push(s);
+    else s.split(/[\s·|/·]+|(?<=\w)-(?=\w)/).map((a) => a.trim()).filter((a) => a.length >= 3 && a.length <= 20).forEach((a) => atoms.push(a));
+  }
+  return [...new Set(atoms)].slice(0, 13);
+};
 
 function buildPayload(row) {
   const warnings = [];
   if (row.title.length > 140) warnings.push('title>140 (clamped)');
-  const dropped = row.tags.filter((t) => t.length > 20);
-  if (dropped.length) warnings.push(`tags dropped (>20 chars): ${dropped.join('|')}`);
+  const long = row.tags.filter((t) => t.length > 20);
+  if (long.length) warnings.push(`tags split into <=20-char atoms (were >20): ${long.join('|')}`);
   return {
     imageFile: row.image, // relative to kits/  -> kits/_images/*.png
     body: {

← 1909be7 etsy: auto-resolve digital-pattern taxonomy_id at wire-up (g  ·  back to Pattern Vault  ·  kits: add marketplace-compliant AI-generation disclosure to 11f60d9 →