[object Object]

← back to Ads Dashboard

Cycle 3: real acquisition panel from Shopify order referrers (/api/acquisition, DW-only, 10-min cache)

d0226041cfaa038f2232cefb7a08b827417a32c0 · 2026-08-02 18:48:26 -0700 · Steve Abrams

Files touched

Diff

commit d0226041cfaa038f2232cefb7a08b827417a32c0
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Aug 2 18:48:26 2026 -0700

    Cycle 3: real acquisition panel from Shopify order referrers (/api/acquisition, DW-only, 10-min cache)
---
 public/index.html | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/public/index.html b/public/index.html
index 9e1a835..ac7d959 100644
--- a/public/index.html
+++ b/public/index.html
@@ -68,6 +68,14 @@
     <div class="empty" id="campEmpty" hidden>No campaigns wired yet — /yoloforever will populate this. Data source: /api/campaigns</div>
   </div>
 
+  <div class="section-h">Acquisition — where orders come from <span style="text-transform:none;font-weight:400">(real, from Shopify order referrers)</span></div>
+  <div class="card">
+    <table id="acqTable"><thead><tr>
+      <th>Channel</th><th>Orders</th><th>Revenue</th>
+    </tr></thead><tbody id="acqBody"></tbody></table>
+    <div class="empty" id="acqEmpty" hidden></div>
+  </div>
+
   <div class="section-h">Competitor Ad Signals</div>
   <div class="card">
     <div id="signals"></div>
@@ -113,6 +121,21 @@ async function boot(){
   $('signals').innerHTML = items.length
     ? items.map(s=>`<div><a href="${s.url||'#'}">${s.advertiser||s.title||'signal'}</a> <span class="badge">${s.platform||'—'}</span> <span class="when">🕓 ${fmtDate(s.seen_at||s.created_at)}</span></div>`).join('')
     : `<div class="empty">No competitor ad signals captured yet — feeds from the advertising-signals skill. Source: /api/signals</div>`;
+
+  // acquisition — real Shopify order referrers
+  const acq = await fetch('/api/acquisition').then(r=>r.json()).catch(()=>({present:false,reason:'fetch failed'}));
+  if (acq.present && (acq.channels||[]).length) {
+    $('acqEmpty').hidden = true;
+    $('acqBody').innerHTML = acq.channels.map(c=>`<tr>
+      <td><a href="/api/acquisition">${c.channel}</a></td>
+      <td>${c.orders}</td>
+      <td>$${c.revenue.toLocaleString()}</td>
+    </tr>`).join('') + `<tr style="font-weight:650"><td>Total (${acq.window})</td><td>${acq.totals.orders}</td><td>$${acq.totals.revenue.toLocaleString()}</td></tr>`;
+  } else {
+    $('acqBody').innerHTML = '';
+    $('acqEmpty').hidden = false;
+    $('acqEmpty').textContent = 'Acquisition data unavailable: ' + (acq.reason||'no data') + ' (source: /api/acquisition)';
+  }
 }
 
 let sortKey='newest';

← 370f723 auto-save: 2026-08-02T18:47:17 (1 files) — server.js  ·  back to Ads Dashboard  ·  Cycle 4: real UTM campaign attribution in /api/acquisition + ceae088 →