> For the complete documentation index, see [llms.txt](https://the-wishlist-documentation.gitbook.io/the-wishlist-documentation-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://the-wishlist-documentation.gitbook.io/the-wishlist-documentation-docs/developer-reference/optimising-shopify-site-performance.md).

# Optimising Shopify Site Performance

## JavaScript Performance & Optimisation

This page covers how the Wishlist app loads JavaScript, what we have done to optimise it, and the steps you can take in your theme to minimise its impact on your store's performance.

> **Note on overall TBT:** If your store's total TBT is high, the Wishlist is typically one of several contributors. Email marketing, review apps, and chat widgets commonly account for a larger share of JavaScript weight. The recommendations in this page address the Wishlist contribution specifically — deferring and scoping those other scripts will have the greatest overall impact on your remaining TBT.

***

### What the app loads

The Wishlist app injects a single JavaScript bundle into every page of your Shopify store via Shopify's ScriptTag API. This is the standard integration method for private Shopify apps — Shopify controls the injection globally, so the script loads on every page by design.

| Resource    | Details                                                                          |
| ----------- | -------------------------------------------------------------------------------- |
| **Bundle**  | `wh-fe.au-aws.thewishlist.io/wishlist/wishlist.js`                               |
| **Size**    | \~206 KB (as of latest release)                                                  |
| **Loading** | Asynchronous — not render-blocking                                               |
| **Caching** | `Cache-Control` headers enabled — browser caches the script after the first load |

The script loads **asynchronously**, meaning it does not block the browser from rendering your page content while it downloads. This has been verified via Lighthouse, which does not flag the Wishlist script as a render-blocking resource.

***

### What we have optimised

#### Bundle size optimisation

The JavaScript bundle has been optimised to \~206 KB.  This reduces the amount of JavaScript that needs to be downloaded and parsed by the browser on every page load, contributing to improved Total Blocking Time (TBT) and overall page performance.

#### Browser caching

The bundle is now served with `Cache-Control` headers, so the script is cached in the browser after the first visit. Returning visitors and users navigating between pages will load the script from their local cache rather than re-downloading it on every request.

#### Inline product JSON (collection pages)

Previous versions of `twc-wishlist-button.liquid` output a full `{{ product | json }}` block for every product on a collection page. On a typical collection page with 50–72 products, this could require approximately 1 MB of inlined HTML — a significant contributor to page weight and a risk factor for Google's 2 MB HTML crawl limit.

We have replaced this with a filtered output that includes only the fields required by the Wishlist app.  Applying this reduces in-line product JSON to \~450KB.

Please replace the original ProductJson code with the following (typically located in `product-card.liquid`, although it depends on the theme).

```
<script type="application/json" id="ProductJson-{{ product_card_product.id }}">
  {{ product_card_product | json }}
</script>
```

\=>

```liquid
{%- capture variants_json -%}
          [
            {%- for variant in product_card_product.variants -%}
              {
                "id": {{ variant.id | json }},
                "title": {{ variant.title | json }},
                "price": {{ variant.price | json }},
                "available": {{ variant.available | json }},
                "featured_image": {{ variant.featured_image | json }},
                "image_id": {{ variant.image_id | json }},
                "image": {{ variant.image  | json }},
                "option1": {{ variant.option1  | json }},
                "option2": {{ variant.option2  | json }},
                "option3": {{ variant.option3  | json }}
              }{%- unless forloop.last -%},{%- endunless -%}
            {%- endfor -%}
          ]
        {%- endcapture -%}

        {%- capture product_json -%}
        {
          "id": {{ product_card_product.id | json }},
          "title": {{ product_card_product.title | json }},
          "price": {{ product_card_product.price | json }},
          "options": {{ product_card_product.options | json }},
          "featured_image": {{ product_card_product.featured_image | json }},
          "images": {{ product_card_product.images | json }},
          "variants": {{ variants_json | strip_newlines | strip }}
        }
        {%- endcapture -%}
        <script type="application/json" id="ProductJson-{{ product_card_product.id }}">{{ product_json | strip_newlines | strip }}</script>
```

Contact support if you need assistance.

***

### Disabling the Wishlist on specific pages

By default, the Wishlist script loads and initialises on every page. If your store has pages where the Wishlist is not present — such as the cart, blog, account, or static content pages — you can suppress initialisation on those pages using the disable flag.

When the flag is set, the script still downloads (it is injected globally by Shopify) but performs no rendering, makes no API calls, and executes no Wishlist logic. This reduces unnecessary JavaScript execution and eliminates API activity on pages where it serves no purpose.

#### Option A — Suppress on specific templates (recommended)

Add the following block to your `theme.liquid` file, **before** the Wishlist script tag. Adjust the template list to match your store's structure.

```liquid
{% if template == 'cart'
  or template == 'blog'
  or template == 'article'
  or template == 'page'
  or template == 'customers/account'
  or template == 'customers/order'
  or template == 'customers/addresses' %}
  <script>window.theWishlistDisable = true;</script>
{% endif %}
```

#### Option B — Allow only on specific templates

If you prefer an allowlist approach — only enabling the Wishlist on templates where it is explicitly needed:

```liquid
{% unless template == 'index'
  or template == 'collection'
  or template == 'product'
  or template == 'search' %}
  <script>window.theWishlistDisable = true;</script>
{% endunless %}
```

> **Note:** Custom landing pages or theme sections that include Wishlist buttons outside the standard templates should be added to your allowlist. If the flag is set on a page that does contain Wishlist elements, the hearts will not render.

#### Verifying the flag is working

With the flag active on a given page, open your browser's developer tools and check the console. You should see no Wishlist API calls in the Network tab, and no Wishlist initialisation messages. The script file itself will still appear in the Network tab as a cached resource — this is expected.

***

### Recommendations for theme integrations

A number of performance issues raised by merchants relate to theme customisations rather than the core app. The following are the most common:

#### Render-blocking CSS

Your audit tool may flag a file named `twc-wishlist.css` as render-blocking, however, the `twc-wishlist.css` stylesheet is loaded using Shopify’s standard `stylesheet_tag`, consistent with how the theme’s other stylesheets are loaded: &#x20;

`{{ 'custom.scss.css' | asset_url | stylesheet_tag }}`&#x20;

&#x20;`{{ 'twc-wishlist.css' | asset_url | stylesheet_tag }}`&#x20;

Because it is loaded as a standard stylesheet in the theme `<head>`, browsers may identify it as render-blocking. This is expected behaviour and ensures the wishlist styling is available before the page is displayed, preventing unstyled or shifting wishlist elements.

#### `ReferenceError: theWishlist is not defined`

This error occurs when theme code calls into the Wishlist integration before the script has finished loading and initialising. The most common cause is a theme customisation that references `theWishlist` in an inline script that executes too early.

Wrap any theme code that calls into the Wishlist in a ready check:

```javascript
document.addEventListener('twc:ready', function () {
  // your theWishlist calls here
});
```

If the event name differs in your version of the app, check the integration guide or contact support to confirm the correct ready event.

#### Wishlist trigger accessibility

The Wishlist app renders its trigger as a `<button>` element. If your audit flags an `<a href="/pages/wishlist">` link with no accessible text, this is coming from your theme's header or navigation, not the app itself. Add an `aria-label` to that element in your theme:

```html
<a href="/pages/wishlist" aria-label="View your wishlist">
  <!-- icon -->
</a>
```

***

### Changelog

| Date      | Change                                                               |
| --------- | -------------------------------------------------------------------- |
| July 2026 | Cache-Control headers enabled on JS bundle                           |
| July 2026 | JS Bundle reduced from \~255 KB to \~206 KB                          |
| July 2026 | `theWishlistDisable` flag added                                      |
| July 2026 | `twc-wishlist-button.liquid` updated to filtered product JSON output |
