The original checkout custom element.
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.
window.Octany), and ongoing feature work. Use the classic widget when an existing integration already depends on it.
§ 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://octany.example/100/checkout/appearance"> </head> <body> <!-- Drop the element wherever you want a "Subscribe" CTA --> <octany-widget url="https://octany.example" 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://octany.example/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://octany.example. |
| 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". | |
| 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. | |
| 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://octany.example" 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://octany.example" 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://octany.example" 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://octany.example" 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 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.
order.paid / subscription.created.
§ 01.8 postMessage events #
Most integrations don't need to listen for these. They are documented for debugging and for cases where the host page wants to react to checkout events.
| event.data.name | Direction | Purpose |
|---|---|---|
| open-modal | iframe → host | Show the modal iframe with payload data. |
| close-modal | iframe → host | Hide the modal; redirect to success/abort URL if set. |
| size | iframe → host | Auto-resize the in-place iframe ({ width, height, productId }). |
| redirect | iframe → host | Navigate the top window to event.data.data.url. |
| are-you-ready / i-am-ready | both | Handshake used by continue=… session resume. |
| amount-change | host → iframe | Sent when the amount attribute is changed at runtime. |
| metadata-change | host → iframe | Sent when the metadata attribute changes. |
§ 01.9 When to migrate to v2 #
The classic widget is solid for what it does. Migrate when you need:
- A UUID-based account identity. Checkout uses account UUIDs; the classic widget uses the numeric ID.
- Multi-product carts where each line item has its own quantity.
- The JS API (
window.Octany.cart.add,requestCheckoutUrl, etc.) for SPA flows. - UTM and reference-id capture via a single
Octany.set(...)call instead of per-element attributes. - Future Octany features — new payment methods and SCA improvements ship to Checkout first.
The migration is mostly mechanical: replace the <octany-widget> element with a hosted-checkout link or Octany.checkout() call. Webhook handling on your backend stays identical.