Embed Widget
Embed the widget directly into your platform
Embed the Unigox buy/sell flow into your site with a single <script> tag. The loader creates a cross-origin <iframe> pointing at https://unigox.com/embed, wires up the required browser permissions, and exposes callbacks for trade and auth events.
Live playground: widgets.unigox.app
Use it to try every option below in your browser and copy the generated snippet straight into your page.
Quickstart
<div id="unigox-widget"></div>
<script src="https://unigox.com/widget.js"></script>
<script>
const widget = UnigoxWidget.init({
container: "#unigox-widget",
crypto: "USDT",
fiat: "USD",
amount: 100,
onTradeCompleted: function (e) {
console.log("trade", e.tradeId);
},
});
</script>That's it. The loader injects the iframe with the right sandbox and allow attributes — you do not need to construct the iframe yourself.
No registration, partner agreement or API key is required to embed the widget. All options below are optional unless marked otherwise.
Need a starting point for your stack? Copy one of the
examplesfolders — vanilla HTML, React, or WordPress — and tweak from there. Each example mirrors this guide and stays in sync with releases.
Earn referrals from your traffic
If you have a Unigox account and want every signup that goes through the widget on your site to count as your referral, just pass your Unigox username as ref:
That's the entire integration. Anyone who signs up while the widget is loaded on your page is attributed to your account — same mechanism as the unigox.com/?ref=… link, but built into the widget so you can earn off the buy flow directly on your site.
Init options
Pass these to UnigoxWidget.init(options).
container
string | HTMLElement
yes
—
CSS selector or DOM element. The iframe is appended to it.
partner
string
no
—
Free-form attribution identifier — any string you want to see in your reports. Not validated. Optional.
ref
string
no
—
Your Unigox username. New signups initiated inside the widget are credited to this user (referral). Use this for no-integration deployments — paste your username and earn referrals from anyone who signs up via the widget on your site.
type
"buy" | "sell" | "buy-sell" | "buy-with-sendout"
no
"buy-sell"
Which side opens first. "buy-sell" shows the full buy/sell toggle. "buy-with-sendout" adds an automatic sendout step — see below. "both" is still accepted as an alias for "buy-sell" for back-compat.
sendoutAddress
string
conditional
—
Required when type=buy-with-sendout. Destination address the purchased crypto is sent to after the trade (EVM 0x… or Solana base58).
sendoutNetwork
string
conditional
—
Required when type=buy-with-sendout. Destination network as a blockchain ticker or name. Accepted values: "ethereum" / "eth", "optimism" / "op", "polygon" / "pol", "unichain" / "uni", "base", "arbitrum" / "arb", "avalanche" / "avax", "hyperevm" / "hype", "solana" / "sol". Numeric chain ids are not accepted.
crypto
string
no
auto
Pre-selected crypto ticker ("USDT", "USDC" are available). Falls back to USDT or the user's balance.
fiat
string
no
auto
Pre-selected fiat code (e.g. "USD", "EUR", "VND"). Falls back to the user's country currency.
amount
number
no
—
Pre-filled amount. For type=buy this is the fiat side ("You spend"); for type=sell it is the crypto side.
email
string
no
—
Prefills the login email. Combined with requireLogin it drives the auto-login flow.
theme
"light" | "dark"
no
"light"
Visual theme.
language
"en" | "es"
no
"en"
UI language. Unsupported values fall back to "en". More locales arrive as they are translated.
loginMethods
"email" | "web3" | "ton" | "all" or multiple options
no
"all"
Which login options to show. Pass a single value, "all" for all three, or multiple options separated by commas: "email,web3", "email,ton", "web3,ton".
requireLogin
boolean
no
false
If true, force the login screen before the widget opens even when anonymous trading would otherwise be possible.
applyAttribution
boolean
no
true
Toggles the "Powered by Unigox" footer inside the widget.
width
string
no
"100%"
Iframe width (any CSS length).
height
string
no
"700px"
Iframe height. When omitted, the widget auto-resizes to fit its content.
Callbacks
All callbacks are informational, not authoritative. They are fired from the iframe via
window.postMessage— anything running in the top-level page can spoof or replay them. Use callbacks for UX (loading state, redirect after success, fire your own analytics) and for non-financial logging. Do not use them as proof-of-state for business decisions like releasing a product, crediting an account, or paying out funds. For those, verify via the Unigox API (server-to-server) or, when applicable, via independent on-chain confirmation.Server-signed webhooks are on the roadmap and will be the authoritative channel; until they ship, treat every event below as a hint, not a fact.
onReady
—
The widget finished its initial render.
UX-only
onAuthChange
{ isAuthenticated }
The user signs in or signs out.
UX-only
onTradeStarted
{ tradeId, tradeType }
The user confirmed a trade.
Verify via API
onTradeCompleted
{ tradeId }
A trade reached a terminal success.
Verify via API
onSendoutStarted
{ tradeId, address, chainId }
(buy-with-sendout only) The bridge to the partner address was submitted.
Verify via API
onSendoutCompleted
{ tradeId, address, chainId, txHash? }
(buy-with-sendout only) The bridge confirmed on the destination chain.
txHash independently verifiable on-chain
onSendoutFailed
{ tradeId, code, message }
(buy-with-sendout only) The sendout step failed. code is one of the SENDOUT_* codes — see Error codes.
UX-only
onWidgetError
{ code, message }
A misconfig error fired before any trade existed (e.g. missing/invalid sendoutAddress). code is one of the WIDGET_* codes.
UX-only
Handle methods
init returns a handle for live control:
configure accepts the same shape as the init URL params (type, crypto, fiat, amount, vendor).
Host-page headers
Skip this section if your site does not set a
Content-Security-Policyor aPermissions-Policyheader. The widget works out of the box on the default browser permissions — these rules only matter if you have already tightened them.
One-block paste (strict-CSP sites)
If your site ships both a strict CSP and a Permissions-Policy, drop these two response headers on every page that loads the widget:
Merge them into your existing directives — do not replace what you already have. Each line below explains what it unlocks and what breaks without it.
Content-Security-Policy
script-src https://unigox.com
Allows widget.js to execute. Without it the loader silently fails with a CSP-violation error in the console — no iframe is created.
frame-src https://unigox.com
Allows the iframe at unigox.com/embed to load. Without it the iframe stays blank. (child-src on the legacy directive.)
Anything else (connect-src, style-src, img-src) does not need a Unigox entry: all those requests originate inside the iframe, which has its own document and is not constrained by the host page's CSP.
Permissions-Policy
The widget asks for several powerful browser features via the iframe's allow attribute (set automatically by widget.js). If your top-level page also sets a Permissions-Policy, the host's policy wins — you must delegate those features to unigox.com for the allow attribute to take effect:
storage-access
Ambient session reuse — users have to log in on every visit instead of reusing their unigox.com session.
publickey-credentials-get/create
Passkey (WebAuthn) sign-in stops working.
Buy with sendout
type="buy-with-sendout" turns the widget into a one-shot fiat → crypto → partner-address flow. The user buys crypto normally, and the widget then automatically opens a sendout step that bridges the funds to a partner-configured external address over our existing bridge relay.
Behaviour
The buy/sell toggle is hidden — only BUY is available in this mode.
A persistent banner shows the sendout destination on every pre-sendout screen (
Sendout to 0xAb…cd on Ethereum).After the trade reaches terminal success and the purchased crypto lands in the user's internal Unigox wallet, the widget auto-navigates to the sendout view (~1.5 s after completion).
The sendout view shows a locked amount (matching the trade result), the destination, an expandable quote breakdown, and — if the account has it enabled — inline 2FA fields. The user confirms with a single click.
Bridge progress, fees and final tx hash are shown inline. The host is notified via
onSendoutStarted / onSendoutCompleted / onSendoutFailed.
Requirements & constraints
sendoutAddressmust match the chosen network's address format. EVM networks require a0x…address that passes EIP-55 checksum validation when mixed-case; Solana requires a base58 address. Malformed addresses render a "Widget misconfigured" screen before any trade is created, so the user cannot proceed.sendoutNetworkmust be a ticker the widget recognises (ethereum/eth,optimism/op,polygon/pol,unichain/uni,base,arbitrum/arb,avalanche/avax,hyperevm/hype,solana/sol) and the resulting chain must be supported by the Unigox bridge for the chosencrypto. Unsupported combinations render a "Sendout misconfigured" screen inside the widget. Unknown tickers render a "Missing requiredsendoutNetworkparameter." configuration error.Today the bridge supports USDC and USDT as source assets. If you plan to use other tickers, contact support first.
The crypto selector inside the widget is not filtered — the user can still pick any listed token; misconfigurations surface at the sendout step rather than at selection time.
Error codes
Error events carry a stable code field — branch on code for business logic, treat message as a human-readable hint that may be reworded between releases. Codes never change shape or meaning within the v1 loader.
WIDGET_* — onWidgetError({ code, message })
WIDGET_* — onWidgetError({ code, message })These fire before any trade exists. Recovery is always a configuration fix on the partner side; the user cannot continue. The widget also displays a "Widget misconfigured" screen so end-users see something coherent.
WIDGET_MISSING_SENDOUT_ADDRESS
type=buy-with-sendout was used without sendoutAddress.
Re-init with a non-empty sendoutAddress.
WIDGET_MISSING_SENDOUT_NETWORK
type=buy-with-sendout was used without sendoutNetwork, or the ticker is unknown.
Re-init with a recognised ticker (see sendoutNetwork).
WIDGET_INVALID_SENDOUT_ADDRESS
sendoutAddress does not match the chosen network's format (bad EIP-55 checksum on EVM, or non-base58 on Solana).
Re-init with an address valid for the chosen sendoutNetwork.
SENDOUT_* — onSendoutFailed({ tradeId, code, message })
SENDOUT_* — onSendoutFailed({ tradeId, code, message })These fire after a trade exists. The user can usually retry from inside the widget; the partner is informed so it can react in its own UI / analytics.
SENDOUT_NOT_SUPPORTED
The combination of the user's chosen crypto and sendoutNetwork is not on the bridge. The widget shows a "Sendout misconfigured" screen.
No
No — partner-side fix only (different sendoutNetwork or restrict crypto).
SENDOUT_QUOTE_FAILED
The bridge quote API rejected the request (no liquidity, network down, etc.).
No
Yes — user retries from inside the widget.
SENDOUT_BRIDGE_FAILED
Source-chain transaction submitted but destination did not confirm, or the relay errored mid-flight.
Maybe — funds may be in flight.
Yes inside the widget; if it keeps failing, recovery via unigox.com/wallet and contact support.
SENDOUT_UNKNOWN
Unclassified upstream failure. Treat as SENDOUT_BRIDGE_FAILED for retry purposes.
Maybe
Yes — same recovery path.
Branching example
Versioning & compatibility
The loader at https://unigox.com/widget.js auto-updates — every page load fetches the latest. We commit to the following stability rules within the v1 loader:
Init options. No existing option is ever removed or renamed. Accepted types and the required-vs-optional split do not change. New optional options may be added; partners should ignore options they do not recognise.
Callbacks. Existing payload fields are not renamed or removed. New optional fields may be added; partners should ignore unknown fields and not rely on absence.
postMessage protocol. Existing
typevalues and existing payload fields are stable. Newtypes and new optional payload fields may appear.Direct
/embedURL params. Same rules as init options.
The widget UI (visual design, copy, internal step ordering, error wording) is not covered by these rules — it changes continuously. Build your integration on the contract above, not on screen flow or DOM structure.
Breaking changes
When a breaking change is unavoidable we ship it as a new loader URL — https://unigox.com/widget.v2.js — and keep the previous URL serving the previous major for at least 90 days. During that window both URLs work and partners migrate by changing the <script src> and reading the migration notes in CHANGELOG.md.
We never publish breaking changes by silently flipping widget.js.
Tracking changes
All partner-visible changes are recorded in CHANGELOG.md. Watch the file on GitHub if you want a notification on every release.
Examples
Stack-specific copy/paste examples live in examples . Each folder is self-contained — no build step beyond what your stack already needs.
vanilla-html/
One HTML file, one <div>, one <script>. The minimum integration.
react/
A reusable UnigoxWidget wrapper plus a sample page. SSR-safe.
wordpress/
Snippet for the WordPress "Custom HTML" block, plus notes on caching plugins, AMP and CSP.
The examples track the v1 loader, so they auto-pick up additive changes without edits. When the contract changes (v2), the examples folder is updated alongside.
Last updated
