← back to Estimate Instant
estimate-instant: add embeddable widget (embed.js iframe snippet + auto-height postMessage) — matches brief's 200+-site embed thesis
6ec2a7c0b53ee4222c31bd8e5058ac87ced0b86a · 2026-07-15 16:52:04 -0700 · Steve
Files touched
A public/embed.jsM public/index.html
Diff
commit 6ec2a7c0b53ee4222c31bd8e5058ac87ced0b86a
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Jul 15 16:52:04 2026 -0700
estimate-instant: add embeddable widget (embed.js iframe snippet + auto-height postMessage) — matches brief's 200+-site embed thesis
---
public/embed.js | 32 ++++++++++++++++++++++++++++++++
public/index.html | 4 ++++
2 files changed, 36 insertions(+)
diff --git a/public/embed.js b/public/embed.js
new file mode 100644
index 0000000..fe81dc2
--- /dev/null
+++ b/public/embed.js
@@ -0,0 +1,32 @@
+// estimate-instant — drop-in embed for any DW sister site.
+// Usage on the host page:
+// <div id="dw-estimate"></div>
+// <script src="https://estimate.designerwallcoverings.com/embed.js"
+// data-target="#dw-estimate" data-height="720"></script>
+// Renders the calculator in a sandboxed iframe so host-page CSS can't leak in
+// and captured emails post back to THIS origin (single source of truth for the
+// roll-math + the lead store). No host-page dependencies.
+(function () {
+ var s = document.currentScript;
+ if (!s) return;
+ // Origin the script itself was loaded from — the widget always talks home.
+ var origin = new URL(s.src, location.href).origin;
+ var sel = s.getAttribute('data-target') || '#dw-estimate';
+ var height = parseInt(s.getAttribute('data-height') || '720', 10);
+ var mount = document.querySelector(sel);
+ if (!mount) { console.warn('[estimate-instant] embed target not found:', sel); return; }
+
+ var f = document.createElement('iframe');
+ f.src = origin + '/?embed=1';
+ f.title = 'Wallpaper roll estimate';
+ f.loading = 'lazy';
+ f.setAttribute('scrolling', 'no');
+ f.style.cssText = 'width:100%;border:0;display:block;max-width:680px;margin:0 auto;height:' + height + 'px';
+ // Let the widget grow to fit its content once loaded (see index.html postMessage).
+ window.addEventListener('message', function (e) {
+ if (e.origin === origin && e.data && e.data.dwEstimateHeight) {
+ f.style.height = e.data.dwEstimateHeight + 'px';
+ }
+ });
+ mount.appendChild(f);
+})();
diff --git a/public/index.html b/public/index.html
index effe93e..cbc0961 100644
--- a/public/index.html
+++ b/public/index.html
@@ -99,7 +99,11 @@ async function calc(){
['Price per roll','$'+r.pricePerRoll],['Est. waste',r.wastePct+'%']
].map(([k,v])=>`<div>${k}: <b>${v}</b></div>`).join('');
$('result').classList.add('show'); $('done').style.display='none';
+ postHeight();
}
+// When embedded via embed.js, report our content height so the host iframe can grow.
+function postHeight(){ if(parent!==window){ try{ parent.postMessage({dwEstimateHeight:document.body.scrollHeight+24},'*'); }catch(e){} } }
+window.addEventListener('load',postHeight);
$('go').addEventListener('click',calc);
$('send').addEventListener('click',async()=>{
const email=$('email').value.trim();
← 324b6db estimate-instant: fix half-drop math (consume match), honest
·
back to Estimate Instant
·
estimate-instant: add embed-demo.html, fix /admin route + au f93b004 →