Embedded hosted checkout
Embedded hosted checkout lets your page keep its layout while COPE renders the payment form inside an iframe. Your site owns the surrounding experience. COPE owns the checkout route, payment collection, tax finality, order creation, and buyer-facing terminal states. Use embedded checkout when you need a custom storefront or in-page checkout modal. Use redirect checkout when the simplest integration is enough or when a browser blocks the iframe flow.Requirements
Before creating embedded checkout sessions:- Create a Checkout SDK publishable key for the COPE business.
- Register every parent page origin that may host the iframe, for example
https://shop.example.com. - Use an origin only: scheme, host, and optional port. Do not include a path, query string, fragment, or userinfo.
- Use HTTPS in production.
http://localhostis only for development and test environments. - Configure allowed success and cancel URLs for redirect-based completion or fallback.
checkout({ embed_origin }). https://shop.example.com and https://www.shop.example.com are different origins.
Create an iframe checkout
| Field | Meaning |
|---|---|
checkout.checkoutUrl | Hosted checkout redirect route, for example https://app.cope.com/checkout/:token. |
checkout.embedCheckoutUrl | Iframe route, for example https://app.cope.com/checkout/embed/:token. |
checkout.embedOrigin | The approved parent origin returned by COPE when embed_origin is valid. |
mountCheckout() refuses to mount when checkout.embedOrigin is missing or does not exactly match window.location.origin.
Mount behavior
mountCheckout() creates the iframe for you:
srcischeckout.embedCheckoutUrl.titledefaults toCOPE checkout.allowis set topayment *for browser wallet support.referrerPolicyis set tono-referrer.widthis set to100%.min-heightis set to720px.- No
sandboxattribute is added by the SDK.
Fallbacks
Setfallback: "redirect" for buyer-safe recovery if the iframe does not complete the trusted ready handshake before readyTimeoutMs.
fallback: "error", the SDK calls:
Events
The iframe sends sanitized events to the SDK. Callback payloads do not include checkout credentials, payment client secrets, or buyer PII.onMessage when you need the raw sanitized event stream:
onSuccess and onCancel are convenience callbacks derived from terminal events.
Security model
Embedded checkout has two layers of authorization:- COPE validates
embed_originagainst the business checkout embed domain allowlist when checkout is created. - The iframe route validates the same embed contract before rendering checkout UI.
targetOrigin; it never uses *. It accepts iframe messages only when:
event.originmatches the checkout iframe origin.event.sourceis the mounted iframe window.event.data.sourceiscope.checkout.event.data.versionis1.
/checkout/embed/:token is intended for iframe rendering.
Test your integration
Use a development or staging page that matches the origin you registered for the COPE business. Exercise the full flow before launch:- Create a cart.
- Add a product and payment plan.
- Set buyer identity.
- Reprice.
- Create checkout with
embed_origin. - Mount the iframe and inspect the postMessage conversation.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
embed_origin_not_allowed during checkout creation | The page origin is not registered for the COPE business. | Register the exact parent origin and create a new checkout session. |
mountCheckout requires checkout.embedOrigin | Checkout was created without embed_origin, or the API rejected the embed origin. | Pass embed_origin: window.location.origin and check the checkout response. |
Checkout embed origin ... does not match current origin | Checkout was created for a different parent origin. | Create checkout from the same origin that will mount it. |
| Iframe never becomes ready | The token is invalid, expired, blocked by headers, or the mount handshake failed. | Use fallback: "redirect" and inspect onError and browser console output. |
| Browser wallet is unavailable | Wallet domain registration or cross-origin iframe payment permissions are incomplete. | Confirm the iframe uses allow="payment *" and verify wallet domain setup for the parent and checkout origins. |