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 complete message 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 theorder.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" });