---
title: "Best practices for web integrations"
description: "Follow these best practices to get the most out of your integration"
url: "https://docs.adyen.com/online-payments/web-best-practices"
source_url: "https://docs.adyen.com/online-payments/web-best-practices.md"
canonical: "https://docs.adyen.com/online-payments/web-best-practices"
last_modified: "2025-09-04T11:40:00+02:00"
language: "en"
---

# Best practices for web integrations

Follow these best practices to get the most out of your integration

[View source](/online-payments/web-best-practices.md)

Follow these best practices to ensure your web Drop-in/Components integration is secure, performant, and compliant.

## Requirements

Before you begin, take into account the following requirements, limitations, and preparations.

| Requirement          | Description                                                                                                                                                                                                                                                                  |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Integration type** | Use these best practices to build your [Web Drop-in](/online-payments/build-your-integration/sessions-flow/?platform=Web\&integration=Drop-in) or [Web Components](/online-payments/build-your-integration/sessions-flow/?platform=Web\&integration=Components) integration. |

## Keep your integration up-to-date

[Staying up-to-date](/online-payments/upgrade-your-integration#staying-up-to-date) on the latest version of Drop-in/Components is crucial for new features, security updates, and compliance.

## Handle web framework re-renders

Modern [frameworks](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Frameworks_libraries) can re-render UI components, which can cause unexpected behavior in the checkout. To prevent this, initialize `AdyenCheckout` and mount your Components only once, when you are ready to display the payment methods.

Some web frameworks might require some extra attention when using specific approaches.

* **React.StrictMode**: this [leads to re-renders and re-executions](https://react.dev/reference/react/StrictMode) of effects and callbacks. Ensure that `AdyenCheckout` and Components are not initialized multiple times.
* **Custom hooks**: you can encapsulate the initialization of `AdyenCheckout` in a custom hook. If you do, ensure your hook returns the instance of the Component that you mount in your UI. And most importantly, make sure that the mounting is executed only once, in the React component that consumes that hook.

For example, when using a custom hook in React, ensure the component is not mounted multiple times on re-renders.

**Prevent multiple initializations with React custom hooks**

```javascript
import React, { useRef, useEffect } from 'react';
import { useAdyenCheckout } from './hooks/useAdyenCheckout; // Replace with your hook's path.

const CheckoutPaymentForm = ({ adyenCheckoutProps }) => {
  const container = useRef(null);
  const { dropin } = useAdyenCheckout(adyenCheckoutProps);

  useEffect(() => {
    // Ensure the container and the Drop-in instance are available.
    if (container.current && dropin) {
      // Mount the Drop-in component to the container element a single time.
      // Watch out for re-renders and do not let it be mounted multiple times.
      dropin.mount(container.current);
    }
  }, [dropin]);

  return <div ref={container} />;
};
```

## Manage Server-Side Rendering (SSR)

Drop-in/Components depend on browser APIs like `window` and `document`. If you use [SSR](https://developer.mozilla.org/en-US/docs/Glossary/SSR), make sure the code that creates an `AdyenCheckout` instance and mounts a Component is executed on the client side.

## Securely implement a custom pay button

If you use a custom pay button in your integration, you need to take a few things into account.

### Prevent multiple submissions

A shopper can trigger a payment in multiple ways, for example by selecting the **Pay** button, or by pressing the **Enter** key on their keyboard. To prevent multiple payments for the same order, you must disable your pay button as soon as a payment attempt has been made.

You can detect when the payment flow is triggered by using:

* `beforeSubmit` in your `AdyenCheckout` configuration for a [Sessions flow integration](/online-payments/build-your-integration/sessions-flow?platform=Web).
* `onSubmit` in your `AdyenCheckout` configuration for an [Advanced flow integration](/online-payments/build-your-integration/advanced-flow?platform=Web).

The `beforeSubmit` and `onSubmit` events are triggered when the pay button is selected.

The following example shows how to use the `beforeSubmit` callback to track the payment status and prevent multiple submissions.

**Prevent multiple payments with Sessions flow**

```javascript
let isPaymentInProgress = false;

const checkout = await AdyenCheckout({
  ...
  beforeSubmit: (state, component, actions) => {
    // If a payment is already in progress, reject the new submission.
    if (isPaymentInProgress) {
      actions.reject();
      return;
    }

    isPaymentInProgress = true;
    actions.resolve(state.data);
  }
});
```

### Unsupported payment methods

The custom pay button is not supported for:

* PayPal
* Klarna
* Click to Pay

For these payment methods, you must use the button provided by the Component.

## Use HTTPS for your checkout

To protect sensitive payment data, host your Adyen checkout on a page that uses [HTTPS](https://developer.mozilla.org/en-US/docs/Glossary/HTTPS).

In your live environment, you need to use HTTPS. It encrypts the connection between the shopper browser and your server, which prevents data interception and tampering. If you do not use HTTPS in production, it leads to security warnings and can cause payments to fail.

For local development and testing, you can use HTTP. However, make sure you switch to HTTPS before you go live. Read about [end-to-end online payments testing](/online-payments/go-live-checklist#end-to-end-testing) for more information.

## Avoid \<iframe> elements

We do not recommend integrating your checkout in an [\<iframe>](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/iframe) due to potential complexities. When an \<iframe> is hosted on a different domain than its parent, redirect payment flows doesn't work. This is because the \<iframe> can't redirect when the parent is a different domain. This restriction leads to failed transactions and a poor user experience. Some payment methods may also behave differently or require a specific configuration when used in an \<iframe>.

If you must use an \<iframe>, host it on the same domain as the parent page.

## Avoid WebViews

For native mobile apps, we recommend that you do not use [WebViews](https://en.wikipedia.org/wiki/WebView) to display the checkout.

WebViews are less secure and functional than native components and can cause performance issues, especially with payment methods that require redirects.

Instead, you should implement native components, for example:

* Custom Tabs for Android
* SFSafariViewController for iOS.

## Ensure browser compatibility

Our Drop-in/Components are designed to work seamlessly with recent versions of all major browsers. To ensure the highest security standards and optimal performance we focus on modern browsers that receive regular security updates.

### Supported desktop browsers

| Browser                                                | Version       |
| ------------------------------------------------------ | ------------- |
| [Chrome](https://www.google.com/chrome/)               | 80 or later   |
| [Safari](https://www.apple.com/safari/)                | 15.4 or later |
| [Firefox](https://www.firefox.com)                     | 74 or later   |
| [Microsoft Edge](https://www.microsoft.com/en-us/edge) | 80 or later   |
| [Opera](https://www.opera.com/)                        | 67 or later   |

### Supported mobile browsers

| Platform | Browser                                                                                | Version requirement                                         |
| -------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| iOS      | Safari or any browser using [WebKit](https://developer.apple.com/documentation/webkit) | [iOS 15.4](https://support.apple.com/en-us/108051) or later |
| Android  | [Chrome](https://play.google.com/store/apps/details?id=com.android.chrome)             | 80 or later                                                 |
|          | [Samsung Internet](https://www.samsung.com/us/apps/samsung-internet/)                  | 12 or later                                                 |

## Understand cookie usage

Drop-in/Components may set one cookie, **\_RP\_UID**, which is [generated by our internal risk management module](/risk-management/fraud-data-collection/#data-collection-data). This module is enabled by default and helps identify suspicious browsing or purchasing patterns. We do not recommend disabling it.\
Other cookies, from adyen.com, may be present if you previously visited our websites and accepted cookies. To see only the cookies used by your integration, clear your browser data or use an incognito window for testing.

## Account for interactions with browser extensions

We do not take responsibility for how Drop-in/Components interact with browser extensions like ad blockers, cookie managers, or password managers. An improperly configured extension can block an \<iframe> or other elements required for payment methods to function correctly.

## Enhance your integration with Adyen Uplift

We recommend that you use features of [Adyen Uplift](/uplift/) in your integration to increase payment conversion, simplify fraud management, and reduce the cost of payments.

## Manage client-side resources

There are two ways to load the client-side resources for Web Drop-in/Components:

* Recommended

  Load through the [Adyen Web npm package](https://www.npmjs.com/package/@adyen/adyen-web).
* [Embed the Adyen Web script and stylesheet into your HTML file](#embed-script-and-stylesheet).

Our integration guides for the [Sessions](/online-payments/build-your-integration/sessions-flow) and [Advanced](/online-payments/build-your-integration/advanced-flow) flows include the instructions for both options. If you decide to [embed the script and stylesheet into your HTML file](#embed-script-and-stylesheet), there are additional considerations.

### Embed the Adyen Web script and stylesheet into your HTML file

When embedding the script and stylesheet, make sure that the URL region matches with the region of your [live endpoints](/development-resources/live-endpoints) and the `environment` you configured for Drop-in/Components in your [Sessions](/online-payments/build-your-integration/advanced-flow), or [Advanced](/online-payments/build-your-integration/advanced-flow) flow integration.

We also recommend to use [Subresource Integrity hashes](#implement-subresource-integrity-hashes) to ensure security.

### Tab: v6.0.0

| Environment                          | URL                                                                                                                                                                                      |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Test                                 | https\://checkoutshopper-**test**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**test**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.css           |
| Europe (EU) live                     | https\://checkoutshopper-**live**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.css           |
| United States (US) live              | https\://checkoutshopper-**live-us**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live-us**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.css     |
| Australia (AU) live                  | https\://checkoutshopper-**live-au**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live-au**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.css     |
| Asia Pacific & Southeast (APSE) live | https\://checkoutshopper-**live-apse**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live-apse**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.css |
| India (IN) live                      | https\://checkoutshopper-**live-in**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live-in**.cdn.adyen.com/checkoutshopper/sdk/`version`/adyen.css     |

### Tab: v5.x.x or earlier

| Environment                          | URL                                                                                                                                                                                                                                                                           |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Test                                 | https\://checkoutshopper-**test**.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**test**.adyen.com/checkoutshopper/sdk/`version`/adyen.css We are currently redirecting `adyen.js` and other asset requests to https\://cdf6519016.cdn.adyen.com. |
| Europe (EU) live                     | https\://checkoutshopper-**live**.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live**.adyen.com/checkoutshopper/sdk/`version`/adyen.css                                                                                                        |
| United States (US) live              | https\://checkoutshopper-**live-us**.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live-us**.adyen.com/checkoutshopper/sdk/`version`/adyen.css                                                                                                  |
| Australia (AU) live                  | https\://checkoutshopper-**live-au**.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live-au**.adyen.com/checkoutshopper/sdk/`version`/adyen.css                                                                                                  |
| Asia Pacific & Southeast (APSE) live | https\://checkoutshopper-**live-apse**.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live-apse**.adyen.com/checkoutshopper/sdk/`version`/adyen.css                                                                                              |
| India (IN) live                      | https\://checkoutshopper-**live-in**.adyen.com/checkoutshopper/sdk/`version`/adyen.js https\://checkoutshopper-**live-in**.adyen.com/checkoutshopper/sdk/`version`/adyen.css                                                                                                  |

#### Implement Subresource Integrity hashes

We recommend that you implement [Subresource Integrity (SRI)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) to ensure that the files you are loading from Adyen have not been manipulated or tampered with by malicious actors.

To use the SRI hash, you need to add an `integrity` attribute when specifying `<script>` or `<link>` elements. Browsers will also check for the `crossorigin` attribute to ensure that the origin allows [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). If a browser detects that the file's hash does not match the specified hash, the browser will not load the resource. To know which browsers support SRI, refer to this [browser compatibility list](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity#Browser_compatibility).

Adyen provides the SRI hash that you include as the integrity attribute. You can find the SRI hashes for all versions of our JavaScript and CSS files in our [release notes](/online-payments/release-notes), under **Updating to this version**.

For example, here is how you specify version 4.2.0 `adyen.js` and `adyen.css` resources:

```js
<script src="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/4.2.0/adyen.js"
   integrity="sha384-SGA+BK9i1sG5N4BTCgRH6EGbopUK8WG/azn/TeIHYeBEXmEaB+NT+410Z9b1ii7Z"
   crossorigin="anonymous"></script>
```

```js
<link rel="stylesheet"
  href="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/4.2.0/adyen.css"
  integrity="sha384-oT6lIQpTr+nOu+yFBPn8mSMkNQID9wuEoTw8lmg2bcrFoDu/Ae8DhJVj+T5cUmsM"
  crossorigin="anonymous">
```

## Test your integration

When you have a working online payments integration, test:

* In a [secure context](/online-payments/go-live-checklist#end-to-end-testing)
* On real mobile devices

For more information, read:

* [End-to-end testing documentation](/online-payments/go-live-checklist#end-to-end-testing), providing more general testing advice.
* [Testing payments and modifications documentation](/development-resources/testing/payments-and-modifications/), listing scenarios you can test your integration on.

## See also

* [Web Drop-in integration](/online-payments/build-your-integration/?platform=web\\\&integration=drop-in)
* [Web Components integration](/online-payments/build-your-integration/?platform=web\\\&integration=components)
* [Upgrade your integration](/online-payments/upgrade-your-integration/)
* [Drop-in/Components release notes](/online-payments/release-notes/)
