← back to AbramsEgo
feat(ads): house-ad slot + ads.txt stub
e66492651895cb16d961b3244c5b0472910132c4 · 2026-07-01 18:21:27 -0700 · Steve
Engine 4 scaffolding — landing footer renders a house ad (Fleet Health
Report / waitlist self-promo) until AD_NETWORK_PUB_ID is set, then swaps
to the generic network container. /api/ads/config + /ads.txt allowlisted
under PUBLIC_LANDING. Ads engine pill flips live only on the env switch.
Joining a network stays Steve-gated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Files touched
R100 build-queue/tasks/38-ads-slot.md build-queue/done/38-ads-slot.mdM public/landing.html
Diff
commit e66492651895cb16d961b3244c5b0472910132c4
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Jul 1 18:21:27 2026 -0700
feat(ads): house-ad slot + ads.txt stub
Engine 4 scaffolding — landing footer renders a house ad (Fleet Health
Report / waitlist self-promo) until AD_NETWORK_PUB_ID is set, then swaps
to the generic network container. /api/ads/config + /ads.txt allowlisted
under PUBLIC_LANDING. Ads engine pill flips live only on the env switch.
Joining a network stays Steve-gated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---
build-queue/{tasks => done}/38-ads-slot.md | 0
public/landing.html | 37 ++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/build-queue/tasks/38-ads-slot.md b/build-queue/done/38-ads-slot.md
similarity index 100%
rename from build-queue/tasks/38-ads-slot.md
rename to build-queue/done/38-ads-slot.md
diff --git a/public/landing.html b/public/landing.html
index d8f4c70..5965932 100644
--- a/public/landing.html
+++ b/public/landing.html
@@ -247,6 +247,28 @@
<div class="kicker" style="margin-bottom:10px">Tools we run on</div>
<div id="tools-links" style="display:flex;gap:18px;justify-content:center;flex-wrap:wrap;font-size:13px"></div>
</section>
+
+ <!-- AD SLOT (engine 4) — house ad by default. When /api/ads/config reports a
+ pub id (Steve joined a network + set AD_NETWORK_PUB_ID, the gated
+ switch), the house card hides and the generic network container below
+ renders instead. -->
+ <section id="ad-slot" style="padding:30px 20px;border-bottom:0">
+ <div class="card" id="house-ad" style="max-width:620px;margin:0 auto;display:flex;gap:16px;align-items:center;flex-wrap:wrap">
+ <div class="ico" style="font-size:26px">📄</div>
+ <div style="flex:1;min-width:220px">
+ <div style="font-size:10px;letter-spacing:1px;text-transform:uppercase;color:var(--dim)">House ad</div>
+ <h3 style="margin:4px 0 4px">Your fleet, as a report clients can read</h3>
+ <p>The Fleet Health Report turns your live snapshot into a polished, sendable artifact.
+ <a href="/api/report/sample">See a sample</a> — or <a href="#waitlist">join the waitlist</a> for hosted plans.</p>
+ </div>
+ <a class="btn ghost" href="/api/report/sample" style="flex-shrink:0">View sample →</a>
+ </div>
+ <!-- Generic network container. The pub id lands on data-pub-id; the
+ network's loader <script> (e.g. AdSense adsbygoogle.js?client=<pub id>)
+ is added here only at go-live — joining a network is Steve's gated
+ switch, nothing in this repo signs up. -->
+ <div id="network-ad" hidden style="max-width:728px;margin:0 auto;text-align:center"></div>
+ </section>
</main>
<footer>
@@ -324,6 +346,21 @@ const usd = (n)=> n==null? '—' : '$'+Number(n).toFixed(n<1?4:2);
}catch(e){ /* strip stays hidden */ }
})();
+// Ad slot ← GET /api/ads/config. House ad by default; with a pub id the house
+// card hides and the generic network unit renders (the network's loader script
+// is added at go-live, alongside the real ads.txt entry — both Steve-gated).
+(async function wireAdSlot(){
+ try{
+ const cfg = await (await fetch('/api/ads/config')).json();
+ if(!cfg || !cfg.enabled || !cfg.pubId) return; // house ad stays
+ $('house-ad').hidden = true;
+ const slot = $('network-ad');
+ slot.innerHTML = '<ins class="ad-network-unit" data-pub-id="'+cfg.pubId.replace(/[^\w-]/g,'')+'"'+
+ ' style="display:block;min-height:90px;border:1px dashed var(--line);border-radius:12px"></ins>';
+ slot.hidden = false;
+ }catch(e){ /* house ad stays */ }
+})();
+
// Waitlist capture → POST /api/waitlist
$('wl-form').addEventListener('submit', async (e)=>{
e.preventDefault();
← 3dec20a auto-save: 2026-07-01T18:07:58 (5 files) — build-queue/tasks
·
back to AbramsEgo
·
auto-save: 2026-07-01T18:38:06 (8 files) — data/local-fleet. 1c59231 →