Octany. for/devs view as .md
§ 01 — Classic widget

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.

Heads up — legacy Classic widget is still supported and stable. New integrations should prefer Checkout — it has a cleaner URL surface, a JS API (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.

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 #

AttributeRequiredNotes
urlyesOctany host, e.g. https://octany.example.
account-idyesNumeric account ID.
product-idyesSingle ID, or pipe-separated for tabbed multi-product (4662|4663).
typeyesiframe (renders in place) or button (CTA that opens the modal).
success-urlRedirect after successful payment.
abort-urlRedirect when user aborts.
tab-titlePipe-separated tab labels for multi-product (Bli månadsgivare|Engångsgåva).
page-titlePipe-separated heading per product, shown above the form.
labelButton label when type="button".
localesv, en, etc. Defaults to en.
amountInteger in öre/cents. Overrides product price for "name your price".
price-with-vatBoolean. Display prices including VAT.
price-descriptionCustom price-line label.
reference-idUse this to correlate. Lands on the resulting subscription/order and on every webhook.
reference-nameHuman-readable label shown alongside the resource in admin.
email, first-name, last-namePre-fill customer fields.
company, phonePre-fill business / contact fields.
line1, line2, zip, city, countryPre-fill billing address fields.
personal-identity-numberSwedish personnummer pre-fill.
accepted-termsPre-check the terms acceptance.
methodForce a specific billing method (e.g. card, swish).
use-sparBoolean. Whether to look up Swedish address from SPAR. Default true.
continueResume an existing checkout session by anonymous ID.
metadataJSON-encoded object passed through to the resulting order.
version1 applies legacy z-index rules.
safari-url-redirectiOS 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.

Don't trust the redirect Same rule as Checkout — the source of truth that a payment cleared is the webhook, not the redirect. Show a "finalising…" state on your success page and wait for 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.nameDirectionPurpose
open-modaliframe → hostShow the modal iframe with payload data.
close-modaliframe → hostHide the modal; redirect to success/abort URL if set.
sizeiframe → hostAuto-resize the in-place iframe ({ width, height, productId }).
redirectiframe → hostNavigate the top window to event.data.data.url.
are-you-ready / i-am-readybothHandshake used by continue=… session resume.
amount-changehost → iframeSent when the amount attribute is changed at runtime.
metadata-changehost → iframeSent 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:

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.