Embedding iframe Guidelines

ℹ️

If you are using React as the framework of choice for the frontend, we highly recommend using our SDK as we will handle the cross-domain issues for you under the SDK

Embedding iframe allows you to seamlessly embed a hosted Breeze payment page directly within your web application. This approach is recommended when we want to avoid redirecting users to the hosted page on Breeze to keep the user experience on your web application seamless.

How It Works

  1. Your application creates a payment session on your backend server
  2. The iframe loads the hosted payment URL
📘

To comply with HTML guidelines for cross-domain payments, please ensure allow="payment *; camera *; accelerometer *; gyroscope *; microphone *" is enabled on the iframe. Also ensure you add the query parameter ?cross_domain_name=[merchant-domain-here] to the src url as seen below.

cross_domain_name must be the exact hostname of the page embedding the iframe, without the https:// — for example www.xyz.com if the user is on www.xyz.com, or xyz.com if they are not. Do not hardcode this value: set it from window.location.hostname so it always matches the page the user is actually on.


<iframe
  id="breeze-payment-page"
  src="https://pay.breeze.cash/page_xxx/pcs_xxx?cross_domain_name=[merchant-domain-here]"
  style={{ width: '100%', height: '100dvh', border: 0 }}
  allow="payment *; camera *; accelerometer *; gyroscope *; microphone *"
/>
  1. Users complete payment within the embedded iframe
  2. Your application validates the payment page status to your backend server
  3. Your application handles the success or failure states appropriately on your frontend

Enabling Google Pay on an embedded iframe

Google Pay relies on the browser's Payment Request API to invoke the native wallet drawer. When this API is unavailable inside the iframe, Google Pay silently falls back to a degraded PAN_ONLY flow instead of producing a network token (CRYPTOGRAM_3DS). This results in all Google Pay transactions being treated as manually-keyed card numbers (FPAN) rather than tokenized cards (DPAN), which reduces authorization rates and loses the liability shift that tokenized payments provide.

To enable the full Google Pay flow, two attributes are required on the iframe:

  • allow="payment ..." — grants the Permissions Policy for payment handling (already shown in the example above).
  • If you set a sandbox attribute on the iframe, you must also include allow-payment-request. The sandbox attribute blocks the Payment Request API by default, so without this value the native Google Pay drawer can never be rendered.
⚠️

If you are not setting a sandbox attribute at all, no extra configuration is needed — the Payment Request API is allowed by default. Only add allow-payment-request when a sandbox attribute is already present.

<iframe
  id="breeze-payment-page"
  src="https://pay.breeze.cash/page_xxx/pcs_xxx?cross_domain_name=[merchant-domain-here]"
  style={{ width: '100%', height: '100dvh', border: 0 }}
  sandbox="allow-scripts allow-same-origin allow-popups allow-forms allow-payment-request"
  allow="payment *; camera *; accelerometer *; gyroscope *; microphone *"
/>

How to verify:

  • On desktop Chrome, inspect the embedded iframe element and confirm both allow="payment ..." and (if sandbox is set) allow-payment-request are present.
  • On an Android device with a card enrolled for contactless payment in the Google Wallet app, complete a test Google Pay transaction and confirm it is processed as CRYPTOGRAM_3DS (DPAN) rather than PAN_ONLY (FPAN).
📘

Once the iframe is correctly configured, the FPAN/DPAN split is determined entirely by the issuer — specifically whether each user's card has been enrolled in network tokenization (Visa Token Service / Mastercard MDES) by their bank. This is outside the merchant's and Breeze's control.

Enabling Apple Pay on an embedded iframe

To enable Apple Pay for iframe usage, please register your domain on the dashboard page and refer to the instructions on the page.

⚠️

Subdomains management

Apple Pay treats www.xyz.com and xyz.com as two different domains. The cross_domain_name value must exactly match the hostname in the user's address bar, and that exact hostname must be domain-certified. If they differ — for example your site is reachable on both xyz.com and www.xyz.com and the embed hardcodes one of them — the Apple Pay sheet opens and immediately closes with "Payment not completed" for every user on the other hostname, before any charge is attempted. Card and Google Pay are unaffected, which makes this easy to miss.

To avoid this:

  • Set cross_domain_name from window.location.hostname instead of a fixed string, and
  • Request domain certification for every hostname your users can reach (e.g. both xyz.com and www.xyz.com) and host the certification file on each — or redirect all traffic to one canonical hostname.

Steps to be completed:

  • Adding the domain certification for every hostname users can reach
  • Ensure cross_domain_name is passed as a query parameter in the URL
  • Ensure cross_domain_name exactly matches the hostname in the user's address bar (set it from window.location.hostname)

Did this page help you?