Skip to main content

Serve Elements from Your Domain

By default, Web Elements load from js.basistheory.com. The SDK script, the element iframes, and the API requests all reference the Basis Theory domain. For most integrations this is exactly what you want — there is nothing to host and nothing to operate.

Some teams need the SDK to load from their own domain instead. Common reasons:

  • A Content Security Policy that is difficult to extend to third-party domains.
  • A requirement that every network request a customer's browser makes stays on the company's own domain.
  • Brand consistency in browser developer tools and network logs.

Custom domain hosting (sometimes called "whitelabeling") serves the SDK and element iframes from a domain you control — for example pay.your-company.com — while Basis Theory continues to host, secure, and operate everything behind it. Your card data handling and PCI scope do not change: sensitive values are still captured inside Basis Theory-controlled iframes, never by your application.

Custom domain hosting is a managed capability. Basis Theory provisions and operates the domain routing for you. Contact us to get started.


How it works

You point a subdomain you own (for example pay.your-company.com) at Basis Theory. From the browser's perspective, every part of the integration is served from that one domain:

ResourceDefaultOn your custom domain
Loader and SDK scriptjs.basistheory.compay.your-company.com
Element iframesjs.basistheory.compay.your-company.com
API requestsapi.basistheory.compay.your-company.com/api

The SDK adapts to this automatically. The loader script detects the domain it was served from at runtime. When that domain is your custom domain rather than js.basistheory.com, the SDK derives the locations of the SDK bundle and the element iframes from your domain, and routes its API calls back through your domain. Basis Theory forwards those requests on to the Basis Theory API behind the scenes.

This detection is driven entirely by where you load the script from — so the only change in your application is the script's src.


Setup

1. Request a custom domain

Contact us with the subdomain you want to use (for example pay.your-company.com). Basis Theory will set up the domain routing and TLS certificate, and confirm the DNS records you need to add.

Use a dedicated subdomain that runs none of your own application code. See Serve from a dedicated origin below — this is a security requirement, not a recommendation.

2. Add the DNS record

Add the DNS record Basis Theory provides for your subdomain. Once it propagates and the certificate is issued, your subdomain serves the SDK.

3. Load the SDK from your domain

Update your script tag to point at your domain instead of js.basistheory.com. Everything else stays the same.

<script src="https://pay.your-company.com/{version}/web-elements/basis-theory.js"></script>

<script>
document.addEventListener('DOMContentLoaded', async () => {
const bt = window.BasisTheory('<PUBLIC_API_KEY>');

const cardNumber = bt.createElement('cardNumber');
await cardNumber.mount('#card-number-container');
});
</script>

That is the entire code change. You do not pass a base URL or any custom domain option to BasisTheory() — initialization is identical to a standard integration. The loader resolves the SDK bundle, the element iframes, and the API base from the domain it was loaded from.

Custom domain hosting applies to the CDN <script> integration. When you install the SDK from npm, your bundler serves the SDK code and there is no Basis Theory-hosted script to relocate.


Security

Custom domain hosting changes where the SDK is served from, so two of the protections described in the security guide work differently. Read this section before going live.

Serve from a dedicated origin

The iframes that capture card data are isolated from your application by the same-origin policy. That isolation is what guarantees your application's JavaScript cannot read the raw values a user types into an element. On a standard integration the iframes live on js.basistheory.com, a different origin from your site, so the isolation is automatic.

When you serve Elements from your own domain, the element iframes must still live on an origin that runs none of your application code. A browser origin is the exact combination of scheme, host, and port — so pay.your-company.com and app.your-company.com are different origins, while pay.your-company.com/checkout and pay.your-company.com/elements are the same origin.

Do not serve Elements from the same origin that serves your own application. If your site's JavaScript and the element iframes share an origin, the boundary that prevents your code from accessing raw card data is lost — which can pull your application back into PCI scope. Always use a dedicated subdomain (for example pay.your-company.com) that hosts nothing but Basis Theory Elements.

Because of this requirement, dedicate the subdomain to Elements. Do not host your checkout page, marketing site, or any first-party scripts on it.

Prefer a cross-site domain

A dedicated subdomain like pay.your-company.com is a different origin from your application — but if your application also runs under your-company.com (for example on app.your-company.com), the two are still the same site. They share a registrable domain, and browsers apply cookie and CSRF protections at the site boundary, not the origin boundary. The default js.basistheory.com sits outside your site entirely (it is cross-site), so those protections always hold. A subdomain of your own site does not, which weakens your application's own defenses in two ways:

  • Cookies scoped with Domain=your-company.com are sent to pay.your-company.com, and any that are not HttpOnly can be read by JavaScript running on that origin.
  • SameSite=Lax and SameSite=Strict do not restrict requests from pay.your-company.com to your application, because same-site requests are not what those attributes guard against.

Prefer a registrable domain that is cross-site from your application whenever SameSite is what protects you from CSRF. If you must use a subdomain of your application's own site, treat it as a new attack surface on your side of the integration.

When a subdomain is unavoidable:

  • Audit your cookies so no sensitive cookie uses a Domain attribute that scopes it to the parent domain (Domain=your-company.com).
  • Prefer __Host- prefixed cookies for your application's own sessions — they are locked to a single host and are never sent to subdomains.
  • Enforce CSRF protection with explicit tokens or Origin/Referer validation rather than relying on SameSite alone.

Subresource Integrity

On a standard integration, the loader verifies the SDK bundle with a Subresource Integrity (SRI) hash baked in at build time, and you can optionally add an integrity attribute to the loader <script> tag yourself.

The build-time SRI hash is computed against the bundle as served from js.basistheory.com. When the SDK is served from your domain, that hash no longer applies, so the loader does not enforce SRI in custom domain mode. Likewise, do not add a static integrity attribute to a loader <script> tag pointed at your domain — a published hash for the js.basistheory.com bundle will not match, and the browser will refuse to load the script.

Integrity in this mode is provided by two layers instead:

  • HTTPS secures the bytes in transit between the browser and your domain.
  • Basis Theory-managed delivery serves the verified, unmodified SDK assets through the provisioned domain routing — the same artifacts published to the CDN.

The hash-based Content Security Policy baked into each element iframe is unaffected and continues to protect the iframe contents exactly as it does on a standard integration.

Content Security Policy on your page

If your application enforces its own Content Security Policy, allow your custom domain where you would otherwise allow *.basistheory.com:

<meta http-equiv="Content-Security-Policy"
content="frame-src https://pay.your-company.com;
script-src https://pay.your-company.com;
connect-src https://pay.your-company.com" />

Because the SDK, iframes, and API all resolve to your domain, your CSP can reference a single host. See the security guide and troubleshooting guide for the full list of directives.


Things to know

  • PCI scope is unchanged. Raw card data is still captured inside Basis Theory-controlled iframes and never touches your application, as long as you follow the dedicated-origin requirement.
  • Versioning works the same way. Pin a version in the script path exactly as you would on js.basistheory.com. See versioning guidance.
  • The API is reached through your domain. Tokenization and other SDK calls route to pay.your-company.com/api and are forwarded to the Basis Theory API. You continue to use a Public Application API key — no additional credentials are required.

Ready to set up a custom domain, or want to confirm whether it fits your integration? Contact us.