# Serve JavaScript SDK on Custom Domains

<p>RudderStack serves the JavaScript SDK through Amazon S3, delivered via the Amazon CloudFront CDN.</p>
<p>This guide covers the steps to use your own domain instead of the RudderStack domains for serving the JavaScript SDK.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="setup-overview">Setup overview</h2><p>Create a new distribution by following these steps:</p>
<ol>
<li>Log in to your <a href="https://aws.amazon.com/console/" >AWS console</a>.</li>
<li>Click <strong>Services</strong> and go to <strong>Network &amp; Content Delivery</strong> &gt; <strong>CloudFront</strong>.</li>
<li>Click <strong>Create a CloudFront distribution</strong>.</li>
</ol>
<p>The following table gives a high-level overview of the required cache policy, origin request policy, and response headers policy for serving the JavaScript SDK:</p>
<table>
  <thead>
      <tr>
          <th>Cache policy</th>
          <th>Origin request policy</th>
          <th>Response headers policy (optional)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="#cache-policy-settings" >Cache policy settings</a></td>
          <td><a href="#sdk-origin-request-policy-settings" >Origin request policy settings</a></td>
          <td><code>None</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="step-1-configure-distribution">Step 1: Configure distribution</h2><p>The following sections highlight the <strong>required</strong> distribution settings for serving the SDK.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="origin">Origin</h4>

<figure class="image--main "  >
    <a 
         href="/docs/images/user-guides/custom-domains/custom-domains-1.webp"
        
        >
        <img src="/docs/images/user-guides/custom-domains/custom-domains-1.webp" 
         alt="Custom domains distribution settings"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<p>The following table summarizes the settings:</p>
<table>
  <thead>
      <tr>
          <th>Field</th>
          <th>Setting</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Origin domain</td>
          <td><code>cdn.rudderlabs.com</code></td>
      </tr>
      <tr>
          <td>Protocol</td>
          <td><code>HTTPS Only</code></td>
      </tr>
      <tr>
          <td>HTTPS port</td>
          <td><code>443</code></td>
      </tr>
      <tr>
          <td>Minimum origin SSL protocol</td>
          <td><code>TLSv1.2</code></td>
      </tr>
      <tr>
          <td>Name</td>
          <td><code>cdn.rudderlabs.com</code></td>
      </tr>
      <tr>
          <td>Enable Origin Shield</td>
          <td><code>No</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="default-cache-behavior-settings">Default cache behavior settings</h4>

<figure class="image--main "  >
    <a 
         href="/docs/images/user-guides/custom-domains/custom-domains-2-new.webp"
        
        >
        <img src="/docs/images/user-guides/custom-domains/custom-domains-2-new.webp" 
         alt="Custom domains distribution settings"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<p>The following table summarizes the settings:</p>
<table>
  <thead>
      <tr>
          <th>Field</th>
          <th>Setting</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Compress objects automatically</td>
          <td><code>Yes</code></td>
      </tr>
      <tr>
          <td>Viewer protocol policy</td>
          <td><code>Redirect HTTP to HTTPS</code></td>
      </tr>
      <tr>
          <td>Allowed HTTP methods</td>
          <td><code>GET</code>, <code>HEAD</code>, <code>OPTIONS</code>, <code>PUT</code>, <code>POST</code>, <code>PATCH</code>, <code>DELETE</code></td>
      </tr>
      <tr>
          <td>Restrict viewer access</td>
          <td><code>No</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="cache-key-and-origin-requests">Cache key and origin requests</h4><p>Select <strong>Cache policy and origin request policy (recommended)</strong> and configure the following settings:</p>

<figure class="image--main "  >
    <a 
         href="/docs/images/user-guides/custom-domains/js-sdk-cache-key-origin-requests.webp"
        
        >
        <img src="/docs/images/user-guides/custom-domains/js-sdk-cache-key-origin-requests.webp" 
         alt="Custom domains distribution settings"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<p>The following table summarizes the settings:</p>
<table>
  <thead>
      <tr>
          <th>Field</th>
          <th>Setting</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cache policy</td>
          <td>See <a href="#cache-policy-settings" >Cache policy settings</a></td>
      </tr>
      <tr>
          <td>Origin request policy</td>
          <td>See <a href="#sdk-origin-request-policy-settings" >Origin request policy settings</a>.</td>
      </tr>
      <tr>
          <td>Response headers policy</td>
          <td><code>None</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="cache-policy-settings">Cache policy settings</h4>

<figure class="image--main "  >
    <a 
         href="/docs/images/user-guides/custom-domains/js-sdk-cache-policy-settings.webp"
        
        >
        <img src="/docs/images/user-guides/custom-domains/js-sdk-cache-policy-settings.webp" 
         alt="Cache policy settings for serving JS SDK"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<p>The following table summarizes the settings:</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h5 id="details"><strong>Details</strong></h5><table>
  <thead>
      <tr>
          <th>Field</th>
          <th>Setting</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Name</td>
          <td>Name of your cache policy, for example,<code>jssdk-caching-policy</code>.</td>
      </tr>
      <tr>
          <td>Description</td>
          <td>Add your policy description here.</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h5 id="ttl-settings"><strong>TTL settings</strong></h5><table>
  <thead>
      <tr>
          <th>Field</th>
          <th>Setting</th>
          <th>Notes</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Minimum TTL</td>
          <td><code>0</code> (in seconds)</td>
          <td>Ensures the no-store header is respected.</td>
      </tr>
      <tr>
          <td>Maximum TTL</td>
          <td><code>31536000</code> (in seconds)</td>
          <td>Allows CloudFront to use the <strong>Cache-Control</strong> value from origin if it is greater than <code>0</code>.</td>
      </tr>
      <tr>
          <td>Default TTL</td>
          <td><code>300</code> (in seconds)</td>
          <td>Used when origin does not include <strong>Cache-Control</strong> headers.</td>
      </tr>
  </tbody>
</table>
<p>For the RudderStack CDN, CloudFront is configured with a long default TTL (one year) to maximize cache efficiency, and rely on invalidations during releases to refresh content.</p>
<p>RudderStack recommends configuring the prescribed <a href="#ttl-settings" >TTLs settings</a> when setting up a custom domain. For the reasoning behind these recommendations, see the <a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html#ExpirationDownloadDist" >AWS documentation</a>.</p>
<p>This ensures that the custom domain’s CloudFront distribution always respects the origin <strong>Cache-Control</strong> and <strong>Age</strong> headers as the TTLs defined by RudderStack. Since these headers are managed by RudderStack, they may be updated in the future to improve reliability and correctness.</p>
<p>In cases where you need to control browser-side caching policies instead of relying solely on RudderStack’s origin settings, you can configure a CloudFront response headers policy with the <strong>Override origin</strong> option enabled for <strong>Cache-Control</strong> headers.</p>

<blockquote class="warning">
  <div class="tip-quote">
    
    <div class="tip-text">If you are using a different cloud provider for your custom domain, make sure to set the maximum TTL value to <code>300</code>, that is, 5 minutes.</div>
  </div>
</blockquote>
<!-- end-chunk -->
<!-- begin-chunk -->
<h5 id="cache-key-settings"><strong>Cache key settings</strong></h5><table>
  <thead>
      <tr>
          <th>Field</th>
          <th>Setting</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Headers</td>
          <td><code>None</code></td>
      </tr>
      <tr>
          <td>Query strings</td>
          <td><code>All</code></td>
      </tr>
      <tr>
          <td>Cookies</td>
          <td><code>None</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h5 id="compression-support"><strong>Compression support</strong></h5><p>Select both Gzip and Brotli.</p>
<p>Then, click <strong>Create</strong> to generate the cache policy.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="sdk-origin-request-policy-settings">Origin request policy settings</h4><p>Create a new origin request policy with the following settings:</p>

<figure class="image--main "  >
    <a 
         href="/docs/images/user-guides/custom-domains/js-sdk-origin-request-policy.webp"
        
        >
        <img src="/docs/images/user-guides/custom-domains/js-sdk-origin-request-policy.webp" 
         alt="Origin request policy settings"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<table>
  <thead>
      <tr>
          <th>Field</th>
          <th>Setting</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Name</td>
          <td>Enter the origin request policy name, for example, <code>jssdk-origin-request-policy</code></td>
      </tr>
      <tr>
          <td>Headers</td>
          <td><code>Include the following headers</code></td>
      </tr>
      <tr>
          <td>Add header</td>
          <td><ul><li><code>Access-Control-Request-Headers</code></li><li><code>Access-Control-Request-Method</code></li><li><code>Content-Encoding</code></li><li><code>Origin</code></li></ul></td>
      </tr>
      <tr>
          <td>Query strings</td>
          <td><code>All</code></td>
      </tr>
      <tr>
          <td>Cookies</td>
          <td><code>None</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="additional-distribution-settings">Additional distribution settings</h4>

<p>The following table summarizes the settings:</p>
<table>
  <thead>
      <tr>
          <th>Field</th>
          <th>Setting</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Price class</td>
          <td><code>Use all edge locations(best performance)</code></td>
      </tr>
      <tr>
          <td>Alternate domain name(CNAME)</td>
          <td><code>&lt;YOUR_CUSTOM_DOMAIN&gt;</code></td>
      </tr>
      <tr>
          <td>SSL Certificate</td>
          <td>Add your custom SSL Certificate. <br /><br />See <a href="#use-custom-ssl-certificates" >Use custom SSL certificates</a> for more information.</td>
      </tr>
      <tr>
          <td>Supported HTTP versions</td>
          <td><code>HTTP/2</code></td>
      </tr>
      <tr>
          <td>Standard logging</td>
          <td><code>Off</code></td>
      </tr>
      <tr>
          <td>IPv6</td>
          <td><code>On</code></td>
      </tr>
  </tbody>
</table>

<figure class="image--main "  >
    <a 
         href="/docs/images/user-guides/custom-domains/custom-domains-3.webp"
        
        >
        <img src="/docs/images/user-guides/custom-domains/custom-domains-3.webp" 
         alt="Custom domains distribution settings"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="step-2-deploy-distribution">Step 2: Deploy distribution</h2>

<p>Click <strong>Create distribution</strong> and wait for CloudFront to be deployed:</p>

<figure class="image--main "  >
    <a 
         href="/docs/images/user-guides/custom-domains/custom-domains-deploy-distribution.webp"
        
        >
        <img src="/docs/images/user-guides/custom-domains/custom-domains-deploy-distribution.webp" 
         alt="CloudFront deployment"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="add-cname-record-to-dns">Add CNAME Record to DNS</h4><p>Once your distribution is deployed, create a CNAME record for the subdomain you wish to use along with the distribution URL.</p>
<table>
  <thead>
      <tr>
          <th>Name</th>
          <th>Value</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Subdomain you wish to use (used in the creation of the distribution). <br /><br /><strong>Note</strong>: This will vary based on your DNS provider but will typically be just the subdomain. For example: for <code>cdn.yourdomain.com</code> you would use <code>cdn</code>.</td>
          <td>The CDN URL for the created distribution. Example: <code>&lt;prefix&gt;.cloudfront.net</code></td>
      </tr>
  </tbody>
</table>

<figure class="image--main "  >
    <a 
         href="/docs/images/user-guides/custom-domains/custom-domains-6.webp"
        
        >
        <img src="/docs/images/user-guides/custom-domains/custom-domains-6.webp" 
         alt="CDN distribution URL"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="step-3-serve-sdk">Step 3: Serve SDK</h2><p>See the following sections to serve the SDK depending on your installation method:</p>
<ul>
<li><a href="#cdn" >SDK installation using CDN</a></li>
<li><a href="#npm" >SDK installation using NPM</a></li>
</ul>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="cdn">CDN</h4><div class="rs-tabs">
	<div class="rs-tabs__list">
		<button type="button" class="rs-tabs__tab"
			id="tab-feacdb"
		
		>Latest</button>
		<button type="button" class="rs-tabs__tab"
			id="tab-bdceaf"
		
		>Legacy (SDK v1.1 or below)</button>
	</div>
	
<div class="rs-tabs__panel" id="panel-feacdb">

<p>Paste the following <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-javascript-sdk/installation/#using-cdn" >snippet</a> in your website&rsquo;s <code>&lt;head&gt;</code> section and update the URL from:</p>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">var sdkBaseUrl = &#34;https://cdn.rudderlabs.com&#34;;</code></pre></div>
</div>
<p>to:</p>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">var sdkBaseUrl=&#34;https://&lt;YOUR_CUSTOM_DOMAIN&gt;&#34;</code></pre></div>
</div>
<p>Replace <code>&lt;YOUR_CUSTOM_DOMAIN&gt;</code> in the above snippet with your domain URL.</p>
<blockquote class="warning">
  <div class="tip-quote">
    
    <div class="tip-text"><p>Make sure that the <a href="#step-1-configure-distribution" >distribution settings</a> are configured correctly and <strong>no</strong> paths are blocked. Otherwise, the events may not flow through correctly.</p>
<p>For example, paths like <code>&lt;YOUR_CUSTOM_DOMAIN&gt;/v3/modern/plugins/rsa-plugins.js</code> and <code>&lt;YOUR_CUSTOM_DOMAIN&gt;/3.12.0/modern/plugins/rsa-plugins.js</code> should both be accessible. Otherwise, the SDK may not be able to load properly.</p>
</div>
  </div>
</blockquote>

</div>

<div class="rs-tabs__panel" id="panel-bdceaf" hidden>

<ul>
<li>If you&rsquo;re loading the JavaScript SDK <strong>asynchronously</strong>, paste the <a href="https://www.rudderstack.com/docs/archive/javascript-sdk/1.1/quick-start-guide/#using-a-cdn" >snippet</a> in your website&rsquo;s <code>&lt;head&gt;</code> section and update the URL from:</li>
</ul>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">&#34;https://cdn.rudderlabs.com/v1.1/rudder-analytics.min.js&#34;</code></pre></div>
</div>
<p>to:</p>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">&#34;https://&lt;YOUR_CUSTOM_DOMAIN&gt;/v1.1/rudder-analytics.min.js&#34;</code></pre></div>
</div>
<ul>
<li>If you&rsquo;re loading the JavaScript SDK <strong>synchronously</strong>, paste the <a href="https://www.rudderstack.com/docs/archive/javascript-sdk/1.1/quick-start-guide/#using-a-cdn" >snippet</a> in your website&rsquo;s <code>&lt;head&gt;</code> section and update the URL from:</li>
</ul>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">&lt;script src=&#34;https://cdn.rudderlabs.com/v1.1/rudder-analytics.min.js&#34;&gt;&lt;/script&gt;</code></pre></div>
</div>
<p>to:</p>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">&lt;script src=&#34;https://&lt;YOUR_CUSTOM_DOMAIN&gt;/v1.1/rudder-analytics.min.js&#34;&gt;&lt;/script&gt;</code></pre></div>
</div>
<p>Replace <code>&lt;YOUR_CUSTOM_DOMAIN&gt;</code> in the above snippet with your domain URL.</p>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="npm">NPM</h4><p>Since you have used the NPM module for integrating the SDK directly into your application, there is no configuration required for serving the core SDK.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="additional-configuration">Additional configuration</h4>
<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text"><p>Note that this section is only applicable for:</p>
<ul>
<li>npm installations</li>
<li>Customized CDN installations not following the <a href="https://www.rudderstack.com/docs/user-guides/how-to-guides/self-hosting-js-sdk/#prerequisites" >default directory structure</a> that the SDK uses to automatically fetch the plugins and device mode destinations.</li>
</ul></div>
  </div>
</blockquote>

</html>
<p>This section covers some additional configuration required for loading the device mode destinations and plugins:</p>
<div class="rs-tabs">
	<div class="rs-tabs__list">
		<button type="button" class="rs-tabs__tab"
			id="tab-bceafd"
		
		>Latest</button>
		<button type="button" class="rs-tabs__tab"
			id="tab-acdfeb"
		
		>Legacy (SDK v1.1 or below)</button>
	</div>
	
<div class="rs-tabs__panel" id="panel-bceafd">

<p>Configure the <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-javascript-sdk/load-js-sdk/" ><code>load</code> API</a> option for plugins as follows <strong>if</strong> you are not using the <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-javascript-sdk/installation/#sdk-imports-for-bundling-tools-that-process-dynamic-imports" ><code>@rudderstack/analytics-js/bundled</code></a> package that bundles all the plugins into the SDK package.</p>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">rudderanalytics.load(WRITE_KEY, DATA_PLANE_URL, {
  pluginsSDKBaseURL: &#34;https://&lt;YOUR_CUSTOM_DOMAIN&gt;/v3/modern/plugins&#34;
});</code></pre></div>
</div>
<p>To load <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-javascript-sdk/migration-guide/#additional-configuration-for-loading-device-mode-destinations" >device mode destinations</a>, use the following <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-javascript-sdk/load-js-sdk/" ><code>load</code> API</a> option:</p>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">rudderanalytics.load(WRITE_KEY, DATA_PLANE_URL, {
  destSDKBaseURL: &#34;https://&lt;YOUR_CUSTOM_DOMAIN&gt;/v3/modern/js-integrations&#34;
});</code></pre></div>
</div>
<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text"><p>The JavaScript SDK automatically replaces <code>/v3</code> in the configured URL with the current SDK version to load the most compatible integrations and plugins. So, make sure to proxy the whole RudderStack CDN domain instead of specific paths.</p>
<p>For example, if you specify <code>https://&lt;YOUR_CUSTOM_DOMAIN&gt;/v3/modern/js-integrations</code> for loading device mode destinations, then you might see the network request going to <code>https://&lt;YOUR_CUSTOM_DOMAIN&gt;/3.23.0/modern/js-integrations/&lt;DEST_NAME&gt;.min.js</code> to load the destination integration SDKs.</p>
</div>
  </div>
</blockquote>
</html>

</div>

<div class="rs-tabs__panel" id="panel-acdfeb" hidden>

<p>To <a href="https://www.rudderstack.com/docs/archive/javascript-sdk/1.1/version-migration-guide/##loading-device-mode-destinations" >load device mode destinations</a>, use the following additional <a href="https://www.rudderstack.com/docs/archive/javascript-sdk/1.1/load-js-sdk/#loading-options" ><code>load</code> API option</a>:</p>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">rudderanalytics.load(WRITE_KEY, DATA_PLANE_URL, {
    destSDKBaseURL: &#34;https://&lt;YOUR_CUSTOM_DOMAIN&gt;/v1.1/js-integrations&#34;
});</code></pre></div>
</div>
<p>Replace <code>&lt;YOUR_CUSTOM_DOMAIN&gt;</code> in the above snippet with your domain URL.</p>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="use-custom-ssl-certificates">Use custom SSL certificates</h2>

<p>To use a custom domain for your use case, you can request or import an SSL certificate with your CDN provider. Note that this is an <strong>optional</strong> setting.</p>
<p>To use the AWS Certificate Manager with CloudFront, choose the relevant ACM/IAM certificate in the <strong>Custom SSL certificate</strong> field:</p>

<figure class="image--main "  >
    <a 
         href="/docs/images/user-guides/custom-domains/custom-domains-8.webp"
        
        >
        <img src="/docs/images/user-guides/custom-domains/custom-domains-8.webp" 
         alt="Custom SSL certificate"  
         
         
        decoding="async" loading="lazy" class="img-shortcode"/>
    </a>
    
</figure>

<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text">You can choose your subdomain or use a wildcard domain <code>*.yourdomain.com</code> to set up multiple subdomains.</div>
  </div>
</blockquote>

</html>
<p>The AWS Certificate Manager will guide you through the verification by email or DNS TXT records. You will be able to choose your own domain for SSL certificates once verified.</p>

<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="custom-request-header-for-gcp-external-load-balancer">Custom request header for GCP external load balancer</h2>

<p>If you&rsquo;re setting up a custom domain using the <a href="https://cloud.google.com/load-balancing/docs/https" >GCP External HTTPS Load Balancer</a>, make sure to <a href="https://cloud.google.com/load-balancing/docs/https/custom-headers#working-with-request" >add a custom request header</a> in your backend service configuration:</p>
<table>
  <thead>
      <tr>
          <th>Header</th>
          <th>Value</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>Host</code></td>
          <td><code>cdn.rudderlabs.com</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="faq">FAQ</h2><!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="why-do-i-see-store-clientdataincookie-or-rudderencrypt-parse-errors-on-track-calls">Why do I see <code>Store clientDataInCookie</code> or <code>RudderEncrypt</code> parse errors on <code>track</code> calls?</h4><p>Upgrade to the <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-javascript-sdk/installation/" >latest JavaScript SDK version</a> to resolve this issue.</p>
<p>Note that proxying the SDK CDN does not fix this error on its own. If issues persist on Safari or iOS after you upgrade, proxy all three domains listed in <a href="https://www.rudderstack.com/docs/user-guides/how-to-guides/custom-domains/#domains-to-proxy" >Use Custom Domains</a> and see <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-javascript-sdk/faq/" >JavaScript SDK FAQ</a>.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="can-i-overcome-ad-blockers-by-serving-the-javascript-sdk-on-my-domain">Can I overcome ad blockers by serving the JavaScript SDK on my domain?</h4><p>Many popular ad blockers block specific SDK-related downloads and API calls based on the domain name and URL. You can serve the SDK on your CDN to circumvent this issue.</p>
<br />
