---
title: Warm up third-party connections early with preconnect
description: >-
  Shopify already preconnects to the third-party origins of render-blocking
  resources in the head. Add your own preconnect hints only for origins the
  platform can't discover.
source_url:
  html: >-
    https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-preconnect
  md: >-
    https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-preconnect.md
api_name: liquid
---

# Warm up third-party connections early with preconnect

Shopify already preconnects to the third-party origins that serve render-blocking resources in your `<head>`. Add `<link rel="preconnect">` yourself only for origins that the platform can't discover from the rendered HTML.

**Most themes don't need preconnect hints:**

Shopify inspects the rendered `<head>` on every storefront response and automatically preconnects to the first three third-party origins that serve render-blocking scripts or stylesheets there, sending those hints in the `Link` header before the HTML reaches the browser. A hint you write in the HTML for one of those origins is redundant, and it's discovered later than the header. Add a hint only for an origin that isn't referenced by a render-blocking resource in the `<head>`.

***

## Why

When the browser parses a `preconnect` hint, it initiates the full connection handshake: DNS lookup, TCP connection, and TLS handshake. Resources from that domain can use the ready connection immediately. The impact per connection is small, but it's cumulative with multiple external domains.

`preconnect` is an improvement over `dns-prefetch`, which only performs the DNS lookup. `preconnect` does the DNS lookup and the TCP and TLS handshakes.

### What Shopify does automatically

On every storefront HTML response, Shopify scans the rendered `<head>` for render-blocking resources, meaning `<script src>` tags without `async`, `defer`, `type="module"`, or `nomodule`, and `<link rel="stylesheet">` tags that aren't disabled. For those resources, the platform:

* Preloads up to 10 of them through `Link` headers, which the browser receives before the HTML body.
* Preconnects to the first three third-party origins among them. Origins that match your store's domain, the request host, or `cdn.shopify.com` don't count as third-party.
* Always preconnects to the Shopify CDN asset host, in both CORS and non-CORS mode.

Because these hints travel in the response headers, they're acted on earlier than anything you can write in the document. Anything you add for the same origins duplicates work the platform has already done.

***

## How

```html
<link rel="preconnect" href="https://external-domain.com" crossorigin />
```

The `crossorigin` attribute tells the browser to open the connection in CORS mode. Add it **only** when the first resources you'll fetch from that domain use CORS (fonts, `fetch()` requests, and so on). Omit it for domains that serve non-CORS resources like regular scripts, stylesheets, or images. Browsers keep CORS and non-CORS connections separate, so a mismatch means the preconnected socket can't be reused and the browser opens a second connection, defeating the purpose.

If a domain serves both CORS resources (fonts) and non-CORS resources (CSS), then you need two hints:

```html
<link rel="preconnect" href="https://example.com">
<link rel="preconnect" href="https://example.com" crossorigin>
```

### When to use preconnect

Add a hint only when the origin is late-discoverable, meaning the platform can't see it in the rendered `<head>`. In practice, that's an origin that's first requested by JavaScript at runtime, by an app embed, or by a resource further down the `<body>`. Examples include a video host that's only contacted after a player initializes, or a payment widget provider whose script is injected by another script.

Don't preconnect to:

* An origin that already serves a render-blocking script or stylesheet in the `<head>`, because Shopify already preconnects to it.
* Your store's own domain, because the browser is already connected to it.
* Domains that the page doesn't actually use.
* The same domain that you're already preloading, because that's redundant.
* Shopify's own domains (`cdn.shopify.com`, `monorail-edge.shopifysvc.com`). The platform already manages these connections.

### Limit to one or two critical domains

Preconnect has a cost, even if small, and it's on top of the three origins that Shopify already preconnects to. Identify the one or two most critical late-discovered third-party domains and preconnect to those. Use `dns-prefetch` for other, less critical third-party domains. Don't use both `preconnect` and `dns-prefetch` for the same domain, because `preconnect` already includes the DNS lookup.

### Shopify domains you don't need to preconnect to

Don't add a preconnect hint for `cdn.shopify.com`. The platform already sends one in the `Link` header of the main document response, so a hint in your HTML is redundant, and it's discovered later than the header. On top of that, asset URLs are [moving to the store's own domain](https://changelog.shopify.com/posts/changes-to-asset-urls) under a `/cdn` path, so a page might load no assets from `cdn.shopify.com` at all. In that case the extra connection is pure cost. The [`CdnPreconnect`](https://shopify.dev/docs/storefronts/themes/tools/theme-check/checks/cdn-preconnect) theme check flags this.

The platform loads Shopify's analytics, consent, and monitoring scripts through `content_for_header`. The platform handles their connection timing.

Only preconnect to third-party domains that your theme or installed apps reference late, such as font files requested from inside a stylesheet, video hosts, or payment widget providers.

### How preconnect relates to Early Hints

Shopify Liquid filters like `preload_tag` and `stylesheet_tag` with the `preload: true` parameter trigger [Early Hints (HTTP 103)](https://performance.shopify.com/blogs/blog/early-learnings-for-early-hints-at-shopify) responses. These responses include `Link` headers that warm up connections before the HTML arrives, and so do the automatic preloads and preconnects that the platform derives from your `<head>`.

If a third-party domain is already covered by a Liquid preload filter or by the automatic hints, then an additional `preconnect` hint for the same domain is redundant.

`preconnect` is most useful for third-party domains that appear neither in a Liquid filter nor in a render-blocking `<head>` resource, for example, domains contacted by app scripts or external embeds at runtime.

***

## Examples

A font provider is the common case where a hint still earns its place. The stylesheet origin is in the `<head>`, so Shopify preconnects to it, but the font files come from a second origin that's only discovered after the CSS parses:

```liquid
{%- comment -%}
  The font files are requested from inside the stylesheet, so this origin isn't
  visible in the rendered `<head>` and the platform can't preconnect to it.
{%- endcomment -%}
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>


{%- comment -%} Don't preconnect to the store's own domain or to cdn.shopify.com {%- endcomment -%}
{%- comment -%} <link rel="preconnect" href="https://your-store.myshopify.com"> {%- endcomment -%}
```

**Note:**

Self-hosting fonts on the Shopify CDN removes the need for this hint entirely. See [Self-host web fonts on Shopify CDN](https://shopify.dev/docs/storefronts/themes/best-practices/performance/self-host-web-fonts).

```liquid
{%- comment -%}
  Preconnect to YouTube if the page has embedded videos. No `crossorigin` here: the
  iframe and the thumbnail images are non-CORS requests, so a CORS-mode socket wouldn't
  be reused.
{%- endcomment -%}
{%- if section.settings.video_url contains 'youtube' -%}
  <link rel="preconnect" href="https://www.youtube.com">
  <link rel="preconnect" href="https://i.ytimg.com">
{%- endif -%}
```

***

## Testing

* Check the `Link` response header on the document request in the [Chrome DevTools Network panel](https://developer.chrome.com/docs/devtools/network) first. If the origin you're about to preconnect to is already listed there, then the platform has it covered and your hint adds nothing.
* Compare connection timing before and after adding `preconnect`.
* Before: orange and pink connection bars appear when the resource is discovered.
* After: connection is established earlier, and the resource downloads immediately.

***

## References

* [Use `preload` resource hints sparingly](https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-preload-resource-hints-sparingly)
* [Self-host web fonts on Shopify CDN](https://shopify.dev/docs/storefronts/themes/best-practices/performance/self-host-web-fonts)
* [Serve assets from Shopify CDN](https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-shopify-cdn)

***
