Asad Khilji — Blog Post

Logo for Asad Khilji

5 Quick Wins to Speed Up Your Shopify Theme

Drop LCP and boost conversion with these low-risk tweaks: image policy, app audit, render budget, fonts, and Liquid includes.

1) Set an Image Policy

Most Shopify LCP issues are images. Make the rules explicit and enforce them in theme code:

Policy: Next-gen formats (`avif, webp`), fixed dimensions, `loading="lazy"` below the fold, and responsive sizes via `srcset`/`sizes` or image_url filters.

Liquid snippet (hero image)

{% raw %}{% assign hero = section.settings.hero | default: product.featured_image %}
{% if hero %}
  <img
    src="{{ hero | image_url: width: 1200, format: 'webp' }}"
    srcset="
      {{ hero | image_url: width: 640,  format: 'webp' }} 640w,
      {{ hero | image_url: width: 960,  format: 'webp' }} 960w,
      {{ hero | image_url: width: 1200, format: 'webp' }} 1200w,
      {{ hero | image_url: width: 1600, format: 'webp' }} 1600w"
    sizes="(max-width: 768px) 95vw, 1200px"
    width="1200" height="{{ 1200 | divided_by: hero.aspect_ratio | round }}"
    alt="{{ hero.alt | escape }}"
    decoding="async"
    fetchpriority="high"
  >
{% endif %}{% endraw %}

Tip: Use fetchpriority="high" only for the single LCP image on the start view.

2) Run an App Audit

Each app can inject CSS/JS and 3rd-party requests. Keep what drives revenue; remove, delay, or conditionally load the rest.

  • Inventory: In Admin → Apps, list all apps & their theme assets/snippets.
  • Measure: Lighthouse + Network tab → find scripts > 50KB or long tasks > 50 ms.
  • Action: Disable pages where an app isn’t needed using template checks or route guards.

Conditional load example

{% raw %}{% if template.name == 'product' %}
  {% render 'reviews-widget' %}
{% endif %}{% endraw %}

3) Create a Render Budget

Set guardrails so your theme stays fast as features ship.

  • LCP: < 2.5s on 4G/Slow-3G test profile
  • Total JS: < 150KB compressed on first load
  • Requests: < 60 on homepage (first view)

Budget gate in CI (pseudo)

# run in CI after build
lighthouse-ci https://preview-url \
  --budgetsFile=budgets.json --assert.assertions="categories.performance<=0.9:warn"

budgets.json sample

[
  { "path": "/*", "resourceCounts": [{ "resourceType": "script", "budget": 20 }], "timings": [{ "metric": "interactive", "budget": 4000 }] }
]

4) Fix Your Fonts

Fonts are sneaky LCP killers. Serve fewer, smaller, and earlier.

  • Use system stack or a single custom family (wght subset only).
  • Self-host WOFF2, add preload + font-display: swap.
  • Inline a tiny critical CSS block for above-the-fold text.

Theme head include

<link rel="preload" as="font" type="font/woff2" href="{{ 'Inter-400.woff2' | asset_url }}" crossorigin>
<style>@font-face{font-family:Inter;src:url({{ 'Inter-400.woff2' | asset_url }}) format('woff2');font-weight:400;font-style:normal;font-display:swap}</style>

5) Slim Your Liquid Includes

Big partials render slowly. Break them up and avoid heavy logic on first paint.

Replace global monoliths (e.g., a header that renders mega menus, search, recommendations) with lazy sections or defer non-critical includes below the fold.

Defer non-critical snippet

{% raw %}{% capture after_fold %}
  {% render 'size-guide' %}
  {% render 'recently-viewed' %}
{% endcapture %}
<div id="after-fold" hidden>{{ after_fold }}</div>
<script>requestIdleCallback(()=>{document.getElementById('after-fold').hidden=false})</script>{% endraw %}

One-Page Checklist

  • Hero/LCP image uses image_url widths, sizes, and correct dimensions.
  • Apps audited; non-essentials removed or loaded only where needed.
  • Budgets defined (LCP, total JS, requests) and enforced in CI.
  • Fonts: one family, WOFF2, preload + font-display: swap.
  • Liquid includes trimmed; non-critical widgets deferred.

Reach Out

Asad Khilji

Have a question or want me to audit your storefront? I’ll reply promptly.

Mount Olive, NJ, USA

Contact Me