SDK
Embed widget — tab.js
Drop-in JavaScript that opens Tab's checkout in a modal iframe on your own page. No build step, no React requirement, no Tab cookies in the host page's context. ~3 KB minified.
Auto-wired buttons (zero JS)
<script src="https://thetab.bar/tab.js" defer></script> <button data-tab-checkout data-order-id="ord_8H3kZ"> Pay with Tab </button>
Every [data-tab-checkout] button on the page gets a click handler that opens the modal for the order id in its data-order-id. The script re-scans on DOM mutations so async-rendered buttons (React/Vue/Svelte) work too.
Programmatic open
<script src="https://thetab.bar/tab.js"></script>
<script>
Tab.checkout({
orderId: "ord_8H3kZ",
onComplete: (order) => {
console.log("Paid:", order.txHash);
window.location = "/thanks";
},
onClose: () => { /* dismissed without paying */ },
onError: (err) => { /* server-side load failure */ },
autoCloseOnComplete: true, // default
});
</script>What the iframe loads
The widget points the iframe at https://thetab.bar/embed/[orderId]. That page polls the order status and posts a complete message back to window.parent the moment settlement lands.
Security model
- Tab cookies stay in the iframe.Your host page can't read the buyer's session, can't see the wallet key, can't replay their signature.
- postMessage is origin-checked.The widget ignores messages from any source whose origin isn't the script's own origin.
- Payload is non-sensitive. The
completemessage contains order id, amount, currency, chain, and tx hash. No personal data, no addresses beyond what's already on chain. - You verify completion server-side anyway.The widget's job is UX. The on-chain settlement and the
order.completedwebhook are the source of truth — never ship code that grants access based on the widget's message alone.
Styling notes
The overlay is a fixed-position div with z-index: 2147483647. The iframe is centered, max 520px wide, max 90vh tall, with rounded corners. The host page can't style the iframe's contents (cross-origin) — pick your modal size by setting the script's host CSS instead.
Imperative close
Tab.close();
One-liner integration check
Open your browser console on any page where you've loaded tab.js:
Tab.checkout({ orderId: "ord_test_demo" });