Skip to content

Performance

Most shoppers in the Gulf browse on phones, often on mobile data. Sahil scores 90+ on Lighthouse mobile; aim for the same.

Measure Target
Largest Contentful Paint under 2.5 s on a mid-range phone
Interaction to Next Paint under 200 ms
Cumulative Layout Shift under 0.1
JavaScript, compressed under 50 KB for the first page
CSS, compressed under 40 KB

Sooquna measures real visits (web vitals) and shows them to the merchant, so regressions show up.

Always use image_url with image_tag:

{{ product.featured_image | image_url: width: 900 | image_tag: sizes: '(min-width: 990px) 33vw, 100vw' }}

You get WebP from the CDN, a srcset of sizes, width and height (no layout shift) and lazy loading. For the main image of the page (the hero, the first product image), load it eagerly:

{{ section.settings.image | image_url: width: 1600 | image_tag: preload: true, sizes: '100vw' }}

preload: true adds fetchpriority="high" and turns off lazy loading. Use it once per page. A useful rule: preload the image of the first section (section.index == 1), lazy-load the rest.

  • Load scripts with defer (script_tag adds it), never in the <head> without it.
  • Prefer small scripts per feature, loaded only where the feature is (a {% javascript %} in its section).
  • No jQuery or large frameworks: the platform’s APIs (cart, sections, search) are small fetch calls.
  • One main stylesheet, plus {% stylesheet %} per section for section-only CSS.
  • Inline only what the first screen needs, if anything.

Self-host WOFF2, subset with unicode-range, font-display: swap, and preload one file. See Fonts.

  • Look up by handle (collections['sale']), don’t loop to find.
  • limit: every loop that can grow, and paginate lists.
  • Pages of the live theme are cached; avoid output that changes on every request (timestamps, random values), or cached pages will always look stale or never cache well.

Was this page helpful?