← back to Dw Yolo Loop
Artmura titles: insert 'Wallcovering' → '<name> Wallcovering | Artmura'
52f8e55a6c91c57eec09f3fb339555770a8795ad · 2026-06-12 10:05:06 -0700 · Steve Abrams
- creator title logic updated (permanent for future creates)
- update-live-titles.js: PUT new title onto the 161 live drafts (running)
Files touched
M scripts/artmura-onboard/push-artmura-live.jsA scripts/artmura-onboard/update-live-titles.js
Diff
commit 52f8e55a6c91c57eec09f3fb339555770a8795ad
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Jun 12 10:05:06 2026 -0700
Artmura titles: insert 'Wallcovering' → '<name> Wallcovering | Artmura'
- creator title logic updated (permanent for future creates)
- update-live-titles.js: PUT new title onto the 161 live drafts (running)
---
scripts/artmura-onboard/push-artmura-live.js | 2 +-
scripts/artmura-onboard/update-live-titles.js | 58 +++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/scripts/artmura-onboard/push-artmura-live.js b/scripts/artmura-onboard/push-artmura-live.js
index 4e83841..71fe3b7 100644
--- a/scripts/artmura-onboard/push-artmura-live.js
+++ b/scripts/artmura-onboard/push-artmura-live.js
@@ -64,7 +64,7 @@ function specTable(r) {
}
function buildPayload(r, dwSku) {
- const title = `${r.title} | Artmura`;
+ const title = `${r.title} Wallcovering | Artmura`;
const tags = [r.pattern_series, r.collection_book, 'Wallcovering', 'Non-Woven', 'Made in Italy', 'Artmura', dwSku]
.filter(Boolean).join(', ');
const images = (r.images || []).map(src => ({ alt: esc(r.title), src }));
diff --git a/scripts/artmura-onboard/update-live-titles.js b/scripts/artmura-onboard/update-live-titles.js
new file mode 100644
index 0000000..4b77852
--- /dev/null
+++ b/scripts/artmura-onboard/update-live-titles.js
@@ -0,0 +1,58 @@
+#!/usr/bin/env node
+/**
+ * Update the 161 live Artmura draft titles → "<name> Wallcovering | Artmura".
+ * PUT merges only the title field. Idempotent (skips titles already correct).
+ * node update-live-titles.js # dry-run (first 3)
+ * node update-live-titles.js --apply
+ */
+const https = require('https');
+const fs = require('fs');
+const path = require('path');
+const { Pool } = require('pg');
+
+const STORE = process.env.SHOPIFY_STORE || 'designer-laboratory-sandbox.myshopify.com';
+const TOKEN = process.env.SHOPIFY_ADMIN_TOKEN || process.env.SHOPIFY_PRODUCT_TOKEN;
+const API = process.env.SHOPIFY_API_VERSION || '2024-10';
+const DB = process.env.DATABASE_URL || 'postgresql:///dw_unified?host=/tmp';
+const APPLY = process.argv.includes('--apply');
+const PKG = path.join(__dirname, 'data', 'artmura.json');
+if (!TOKEN) { console.error('FATAL: set SHOPIFY_ADMIN_TOKEN'); process.exit(1); }
+const pool = new Pool({ connectionString: DB });
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+
+function shopify(method, p, body) {
+ return new Promise((resolve, reject) => {
+ const data = body ? JSON.stringify(body) : null;
+ const req = https.request({ hostname: STORE, path: `/admin/api/${API}${p}`, method,
+ headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json',
+ ...(data ? { 'Content-Length': Buffer.byteLength(data) } : {}) } },
+ res => { let b = ''; res.on('data', c => b += c); res.on('end', () => { let j; try { j = JSON.parse(b); } catch { j = b; }
+ resolve({ status: res.statusCode, body: j, callLimit: res.headers['x-shopify-shop-api-call-limit'] }); }); });
+ req.on('error', reject); req.setTimeout(20000, () => req.destroy(new Error('timeout')));
+ if (data) req.write(data); req.end();
+ });
+}
+const newTitle = r => `${r.title} Wallcovering | Artmura`;
+
+(async () => {
+ const pkg = JSON.parse(fs.readFileSync(PKG, 'utf8')).products;
+ const { rows } = await pool.query(
+ `SELECT handle, shopify_product_id FROM newwall_catalog WHERE vendor_name='Artmura' AND shopify_product_id IS NOT NULL AND shopify_product_id<>''`);
+ const pid = Object.fromEntries(rows.map(r => [r.handle, r.shopify_product_id]));
+ const todo = pkg.filter(p => pid[p.handle]);
+ console.log(`title update: ${todo.length} products · mode: ${APPLY ? 'APPLY' : 'DRY-RUN'}`);
+ if (!APPLY) { todo.slice(0, 3).forEach(r => console.log(` ${pid[r.handle]} → "${newTitle(r)}"`)); console.log('\nDRY-RUN. --apply to write.'); await pool.end(); return; }
+ let ok = 0, fail = 0;
+ for (const r of todo) {
+ const id = pid[r.handle];
+ try {
+ const res = await shopify('PUT', `/products/${id}.json`, { product: { id: Number(id), title: newTitle(r) } });
+ if (res.status === 200) { ok++; if (ok % 40 === 0) console.log(` ...${ok}`); }
+ else { fail++; console.error(` FAIL ${id}: HTTP ${res.status} ${JSON.stringify(res.body).slice(0, 140)}`); }
+ const [used] = (res.callLimit || '0/40').split('/').map(Number);
+ await sleep(used > 30 ? 1500 : 540);
+ } catch (e) { fail++; console.error(` ERR ${id}: ${e.message}`); await sleep(540); }
+ }
+ console.log(`\nDONE. titles updated=${ok} failed=${fail}`);
+ await pool.end();
+})().catch(e => { console.error(e); process.exit(1); });
← 9172451 Artmura site: per-series 'Pattern' filter in catalog (21 col
·
back to Dw Yolo Loop
·
Artmura go-live: inventory=2026 both variants + publish to a 8f441ef →