← back to Secrets Manager
update-collection-aeo-v2.py
70 lines
#!/usr/bin/env python3
"""
update-collection-aeo-v2.py — refine the live collection AEO block per Steve's feedback:
1. Banner height HALVED (min-height clamp 80/10.7vw/140 -> 40/5.35vw/70).
2. Intro elevated to trade/designer-facing dialogue (one sentence, ≤3 total w/ desc).
3. FAQ moved into a COLLAPSED <details> panel ("Learn about …") so it takes almost no
room and products surface immediately — content stays in the DOM (AEO-visible) and
the FAQPage JSON-LD schema is untouched.
Backs up first; idempotent (skips if v2 already applied).
Run: ! python3 ~/Projects/secrets-manager/update-collection-aeo-v2.py # dry-run
! python3 ~/Projects/secrets-manager/update-collection-aeo-v2.py --apply
"""
import re, json, sys, urllib.request
APPLY = '--apply' in sys.argv
env = open('/Users/macstudio3/Projects/secrets-manager/.env').read()
tok = re.search(r'^SHOPIFY_THEME_TOKEN=(.+)$', env, re.M).group(1).strip().strip('"').strip("'")
S = "designer-laboratory-sandbox.myshopify.com"; A = "2024-10"; TID = 144396058675
KEY = "sections/dw-collection-hero.liquid"
def get_asset():
r = urllib.request.Request(f"https://{S}/admin/api/{A}/themes/{TID}/assets.json?asset[key]={KEY}",
headers={"X-Shopify-Access-Token": tok})
return json.load(urllib.request.urlopen(r, timeout=30))['asset']['value']
def put_asset(v):
b = json.dumps({"asset": {"key": KEY, "value": v}}).encode()
r = urllib.request.Request(f"https://{S}/admin/api/{A}/themes/{TID}/assets.json", data=b,
method="PUT", headers={"X-Shopify-Access-Token": tok, "Content-Type": "application/json"})
return json.load(urllib.request.urlopen(r, timeout=30))
REPLACEMENTS = [
# 1 · halve the banner height
("clamp(80px,10.7vw,140px)", "clamp(40px,5.35vw,70px)"),
# 2 · elevated trade-facing intro (replace just the inner sentence)
("Browse {{ collection.products_count }} luxury {{ aeo_cat }}{% if collection.products_count != 1 %}s{% endif %} in the {{ collection.title }} collection at Designer Wallcoverings.",
"A curated {{ aeo_cat }} collection for the interior design trade — {{ collection.products_count }} designs, with samples and trade pricing on request."),
# 3 · FAQ -> collapsed <details> panel (visible-in-DOM, near-zero room; schema untouched)
('<div class="dw-collection-faq"><h2>Frequently Asked Questions</h2>\n{%- for item in aeo_faq -%}<h3>{{ item.q }}</h3><p>{{ item.a }}</p>{%- endfor -%}</div>',
'<details class="dw-collection-faq" style="max-width:900px;margin:.75rem auto 0;padding:0 1rem;">'
'<summary style="cursor:pointer;font:500 .95rem/1.4 inherit;letter-spacing:.02em;opacity:.75;">'
'Learn about {{ collection.title | remove: \' Collections\' | remove: \' Collection\' }}</summary>'
'<div style="padding:.5rem 0 .25rem;">'
'{%- for item in aeo_faq -%}<h3 style="font-size:1rem;margin:.75rem 0 .25rem;">{{ item.q }}</h3>'
'<p style="margin:0 0 .5rem;opacity:.85;">{{ item.a }}</p>{%- endfor -%}</div></details>'),
]
v = get_asset()
if 'interior design trade' in v:
print("v2 already applied — no change (idempotent)."); sys.exit(0)
backup = "/Users/macstudio3/Projects/secrets-manager/greenland-cleanup-backups/dw-collection-hero-BACKUP-v2pre.liquid"
open(backup, "w").write(v); print(f"backup: {backup}")
new = v
for old, rep in REPLACEMENTS:
if old not in new:
print(f"ABORT: could not find target substring: {old[:60]!r} — no write."); sys.exit(1)
new = new.replace(old, rep, 1)
print(f"3 edits located ✓ ({len(new)-len(v):+d} chars) banner=halved · intro=trade · FAQ=collapsed")
if not APPLY:
print("\nDRY-RUN — re-run with --apply to write the live theme."); sys.exit(0)
res = put_asset(new)
print("PUT:", "OK (valid Liquid)" if 'asset' in res else json.dumps(res)[:200])
back = get_asset()
print("verify: trade intro present =", 'interior design trade' in back, "| collapsed FAQ =", '<details class="dw-collection-faq"' in back)
print(f"rollback if needed: re-PUT {backup}")
print("Look: https://designerwallcoverings.com/collections/grasscloth-wallpapers (hard-refresh)")