Browse docs

Developers

Embed a Pay button

Drop a "Pay with Soca" button onto any website with one script tag. It opens Soca’s hosted checkout in a popup and can tell your page when the payment completes.

The embed is the fastest way to take a payment from a site you already have: paste one script tag and one button, and you have a working "Pay with Soca" button. No framework, no build step, no keys on the page. It works on plain HTML, and inside React, Vue, Webflow, WordPress, or a no-code builder.

How the embed relates to the hosted checkout

The button does not render a payment form on your page. It opens Soca’s hosted, non-custodial checkout (the same checkout_url the API returns) in a centered popup. Checkout stays on Soca because wallet signing cannot run safely inside a third-party site. This is the same model as Stripe Payment Links and Coinbase Commerce.

Add the button

Create an invoice (one-time) or a plan (subscription) first — from the dashboard or the API — and copy its id. Then add the script once, and a button wherever you want it:

One-time payment (invoice)
<!-- Load once, anywhere on the page -->
<script src="https://YOUR-SOCA-ORIGIN/embed.js" async></script>
<!-- Repeat this button as many times as you like -->
<button data-soca data-soca-invoice="inv_123">Pay with Soca</button>
Subscription (plan price)
<button data-soca data-soca-price="price_123">Subscribe with Soca</button>

Replace YOUR-SOCA-ORIGIN with your Soca domain (the same origin your dashboard and checkout_urls use). If you already have a full checkout_url, you can skip the ids and point the button straight at it with data-soca-url.

Options

Configure a button with data- attributes. If the button element is empty, the script styles it and fills in the label; if it already has your own markup, the script leaves the look alone and only wires up the click.

AttributeValuesWhat it does
data-soca(flag)Marks the element as a Soca pay button. Required.
data-soca-invoiceinvoice idOpens the checkout for a one-time invoice.
data-soca-priceprice idOpens the checkout for a subscription plan price.
data-soca-urlcheckout URLAn explicit checkout_url. Overrides invoice/price.
data-soca-modepopup · tab · redirectHow checkout opens. Default popup; falls back to a new tab if popups are blocked.
data-soca-labeltextButton text, used only when the element is empty.
data-soca-themelight · darkStyle of the auto-rendered button. Default light.

Know when a payment completes

When the popup checkout confirms a payment, Soca sends a message back to your page. Listen for it to show a thank-you, unlock content, or redirect. Two equivalent ways:

Success callback
<script>
// Runs once the embed script has loaded
window.addEventListener('load', function () {
Soca.on('success', function (detail) {
// e.g. show a confirmation, redirect, or reveal a download
console.log('Payment complete', detail);
});
});
// Or listen for the DOM event, from anywhere
document.addEventListener('soca:success', function (e) {
console.log('Payment complete', e.detail);
});
</script>

Confirm real payments server-side

The success message is a convenience for updating your UI. It is not proof of payment and can be spoofed by a hostile page. For anything that must be trustworthy — fulfilling an order, granting access — rely on the `invoice.paid` / `subscription.active` webhook, which is signed and authoritative.

Programmatic use

You do not need the data- button at all. Call the checkout yourself — handy in a single-page app or when the amount is decided at runtime:

// Open checkout for an invoice you just created
Soca.checkout({ invoice: 'inv_123' });
// Or a subscription, in a new tab instead of a popup
Soca.checkout({ price: 'price_123', mode: 'tab' });
// Or an explicit hosted URL
Soca.checkout({ url: 'https://YOUR-SOCA-ORIGIN/invoice/inv_123' });
// If you inject buttons after page load, re-scan for them
Soca.refresh();

Good to know

  • The script is dependency-free and self-contained; it derives your Soca origin from its own src, so there is nothing to configure.
  • No secrets ever touch the page. The button only points at a hosted checkout URL — your API key stays on your server.
  • Checkout cannot be shown in an <iframe> on your site (it is frame-denied on purpose, and wallet signing does not work framed). The popup model is deliberate, not a limitation to work around.
  • Card and bank checkout are coming soon; today the hosted checkout the button opens settles in USDC.

Was this page helpful?

A quick signal helps us improve the right pages.