The classic widget.
The classic widget adds Octany checkout to any HTML page. You add an <octany-widget> element, load checkout.js from your Octany account, and Octany handles the payment flow.
§ 01.1 What you're embedding #
The integration uses a single hosted checkout.js script served from your Octany account at {octany-url}/js/checkout.js. The script registers the custom element and opens checkout when the visitor interacts with it.
<octany-widget>is the integration entrypoint you place on your page.- Octany renders the checkout experience and keeps payment handling inside Octany.
Communication uses browser postMessage events so the checkout can open, resize, redirect, and recover across common browser privacy restrictions.
§ 01.2 Install #
Two tags. The order matters — the script needs to be on the page before the element renders.
<!DOCTYPE html> <html> <head> <!-- Stylesheet exposes account-specific theme tokens --> <link rel="stylesheet" href="https://app.octany.com/100/checkout/appearance"> </head> <body> <!-- Drop the element wherever you want a "Subscribe" CTA --> <octany-widget url="https://app.octany.com" account-id="100" product-id="4662" success-url="https://example.se?success" abort-url="https://example.se?abort" type="iframe" ></octany-widget> <!-- Bundle injects the modal iframe and registers the element --> <script src="https://app.octany.com/js/checkout.js"></script> </body> </html>
The url attribute is your Octany host. The account-id is the numeric account ID used by the classic integration. The appearance stylesheet URL exposes your account's brand colors as CSS custom properties on the host page.
§ 01.3 Element attributes #
| Attribute | Required | Notes |
|---|---|---|
| url | yes | Octany host, e.g. https://app.octany.com. |
| account-id | yes | Numeric account ID. |
| product-id | yes | Single ID, or pipe-separated for tabbed multi-product (4662|4663). |
| type | yes | iframe (renders in place) or button (CTA that opens the modal). |
| success-url | Redirect after successful payment. | |
| abort-url | Redirect when user aborts. | |
| tab-title | Pipe-separated tab labels for multi-product (Bli månadsgivare|Engångsgåva). | |
| page-title | Pipe-separated heading per product, shown above the form. | |
| label | Button label when type="button". | |
| locale | sv, en, etc. Defaults to en. | |
| amount | Integer in öre/cents. Overrides product price for "name your price". Must be at least the product minimum and the platform floor for the currency: SEK/NOK/DKK 1000, EUR/USD/GBP 100. | |
| custom-price | Boolean. Set to false to hide the "choose your own amount" checkbox on donation products and lock the visitor to the preset price. Default true. | |
| price-with-vat | Boolean. Display prices including VAT. | |
| price-description | Custom price-line label. | |
| reference-id | Use this to correlate. Lands on the resulting subscription/order and on every webhook. | |
| reference-name | Human-readable label shown alongside the resource in admin. | |
| email, first-name, last-name | Pre-fill customer fields. | |
| company, phone | Pre-fill business / contact fields. | |
| line1, line2, zip, city, country | Pre-fill billing address fields. | |
| personal-identity-number | Swedish personnummer pre-fill. | |
| accepted-terms | Pre-check the terms acceptance. | |
| method | Force a specific billing method (e.g. card, swish). | |
| use-spar | Boolean. Whether to look up Swedish address from SPAR. Default true. | |
| continue | Resume an existing checkout session by anonymous ID. | |
| metadata | JSON-encoded object passed through to the resulting order. | |
| custom-fields | JSON-encoded object of custom field values keyed by field ID. See Preset custom fields. | |
| version | 1 applies legacy z-index rules. | |
| safari-url-redirect | iOS Safari third-party-cookie workaround target. See note below. |
§ 01.4 Iframe vs. button #
The type attribute picks the rendering mode.
type="iframe"
The form renders in place where you put the element. Auto-resizes via postMessage from the inner iframe. Best for landing pages.
<octany-widget url="https://app.octany.com" account-id="100" product-id="4662" type="iframe"></octany-widget>
type="button"
Renders a CTA button. Clicking it opens the modal iframe full-screen. Best for "Subscribe" / "Donate" CTAs scattered across a page.
<octany-widget url="https://app.octany.com" account-id="100" product-id="4662" label="Become a member" type="button"></octany-widget>
§ 01.5 Multiple products in one flow #
Pipe-separate product-id and pair with matching tab-title / page-title. Useful for monthly + one-off donation flows in a single CTA.
<octany-widget url="https://app.octany.com" account-id="100" product-id="4662|4663" tab-title="Bli månadsgivare|Engångsgåva" page-title="Ge en gåva varje månad|Ge en engångsgåva" success-url="https://example.se?success" type="iframe"></octany-widget>
§ 01.6 Custom metadata #
The metadata attribute accepts a JSON-encoded object that lands on the order. Useful for campaign tags, source pages, or any structured field you'd otherwise stuff into reference_id. The widget watches the attribute via MutationObserver — if you change it after render, it propagates to the open modal.
<octany-widget url="https://app.octany.com" account-id="100" product-id="4662" metadata='{"campaign":"spring-2025","source":"footer"}' type="iframe"></octany-widget>
UTM parameters from the host page URL (utm_source, utm_medium, utm_campaign, utm_content, utm_term) are auto-captured and forwarded — you don't need to wire them.
§ 01.7 Preset custom fields #
The custom-fields attribute fills in your account's custom fields in advance. It takes a JSON-encoded object keyed by custom field ID. Use it to tag a gift with a campaign or event on a field the donor never sees, or to skip questions the host page already knows the answer to. It's separate from metadata, which keeps working as before and is stored unchanged.
<octany-widget url="https://app.octany.com" account-id="100" product-id="4662" custom-fields='{"1":"Afrika","12":"Spring gala 2026"}' metadata='{"campaign":"spring-gala"}' type="iframe"></octany-widget>
Find a field's ID in Octany admin under Products → Custom fields — it's the number at the end of the URL when you open the field.
- Fields the widget shows are prefilled in the modal, and the donor can change them. When every shown field is prefilled (headings don't count), the custom fields step is skipped. It only appears if a value is rejected when the donor continues.
- Fields the widget doesn't show are validated when the checkout starts and saved behind the scenes.
- When the order or subscription is created, the preset values are saved together with the donor's answers. If the donor answered the same field, their answer wins. From there they follow the normal path, including the sync to the contact profile when the order is confirmed.
Accepted values
| Field type | Value |
|---|---|
| Text, text area, dedication | String. |
| Dropdown, radio buttons | A choice ID, e.g. "34". |
| Multiple checkboxes | An array of choice IDs, e.g. ["34","35"]. |
| Checkbox | true/false or "1"/"0". |
| Date | A date string, normalized to YYYY-MM-DD. Send YYYY-MM-DD to be safe. |
§ 01.8 Success / abort URLs #
On success: the modal posts close-modal with { type: 'success', successUrl } and the host page navigates to your success-url. On abort, it navigates to abort-url if set, otherwise just closes the modal.
Placeholders in success-url
Before redirecting, the classic checkout substitutes a fixed set of placeholders in the URL. Use them when you want a per-order landing page without an extra round-trip to your backend.
| Placeholder | Replaced with |
|---|---|
{firstName} | Customer's first name. |
{lastName} | Customer's last name. |
{email} | Customer's email address. |
{customerId} | Octany customer ID. |
{orderId} | Resulting order ID (one-off purchases). |
{subscriptionId} | Resulting subscription ID (recurring products). |
{product} | Product name, URL-encoded. |
{total} | Total amount in öre/cents. |
{provider} | Billing provider/type used for the payment, e.g. stripe, swish, trustly, or billecta. |
<octany-widget url="https://app.octany.com" account-id="100" product-id="4662" success-url="https://example.se/thanks?order={orderId}&amount={total}&provider={provider}" type="iframe"></octany-widget>
Which placeholders apply depends on the kind of checkout: {orderId} for one-off orders, {subscriptionId} for subscriptions. Unrecognised placeholders are left untouched.
UTM tags are not forwarded. The widget captures utm_source/medium/campaign/content/term from the host page URL and stores them on the resulting order's utm_parameters for attribution, but they are not appended to success-url. If you need UTMs on the redirect, put them in success-url yourself when you render the element.
order.paid / subscription.created.
§ 01.9 When to use something else #
The classic widget is solid for what it does. For a new build, look at the alternatives first:
- Donations and fundraising — use the modern Insamling experiences. Donation, Membership, 1-click Swish, and Greeting are purpose-built for campaign pages, editorial pages, and seasonal giving.
- SaaS, ecommerce, or multi-product carts — use Checkout. It exposes a hosted checkout URL, an embeddable cart, and the
window.OctanyJS API.
Migrating away is mostly mechanical: replace the <octany-widget> element with the relevant loader snippet or hosted-checkout link. Webhook handling on your backend stays identical.