Quality, Performance, Accessibility, and Shipping Intermediate 12 min read

Performance Audit Checklist

A comprehensive checklist for auditing and optimizing Shopify theme performance, covering images, JavaScript, CSS, and Core Web Vitals.

Fast themes convert better. A comprehensive performance audit ensures your theme loads quickly, responds instantly, and provides a smooth shopping experience.

Core Web Vitals

Google’s Core Web Vitals are the key metrics for user experience:

MetricTargetWhat It Measures
LCP (Largest Contentful Paint)< 2.5sLoading performance
INP (Interaction to Next Paint)< 200msInteractivity
CLS (Cumulative Layout Shift)< 0.1Visual stability

Performance Audit Checklist

Images

## Image Optimization
- [ ] Use `image_url` with appropriate widths
- [ ] Include `srcset` for responsive images
- [ ] Add `loading="lazy"` for below-fold images
- [ ] Add `loading="eager"` for hero/LCP images
- [ ] Set explicit `width` and `height` attributes
- [ ] Use `fetchpriority="high"` for LCP image
- [ ] Avoid oversized images (match display size)
- [ ] Use WebP format when possible

Image Best Practices

{# Hero image (LCP candidate) #}
{{ product.featured_image | image_url: width: 1200 | image_tag:
loading: 'eager',
fetchpriority: 'high',
width: product.featured_image.width,
height: product.featured_image.height,
sizes: '(max-width: 768px) 100vw, 50vw'
}}
{# Product grid images (lazy loaded) #}
{{ product.featured_image | image_url: width: 600 | image_tag:
loading: 'lazy',
width: 600,
height: 600,
sizes: '(max-width: 768px) 50vw, 25vw'
}}

JavaScript

## JavaScript Optimization
- [ ] Load scripts with `defer` attribute
- [ ] Minimize third-party scripts
- [ ] Use native JS over large libraries
- [ ] Lazy load non-critical scripts
- [ ] Avoid render-blocking JavaScript
- [ ] Split code by template (load only what's needed)
- [ ] Use event delegation for dynamic content
- [ ] Debounce/throttle scroll and resize handlers

JavaScript Loading

{# Defer non-critical scripts #}
<script src="{{ 'theme.js' | asset_url }}" defer></script>
{# Lazy load scripts for specific features #}
{%- if template.name == 'product' -%}
<script src="{{ 'product.js' | asset_url }}" defer></script>
{%- endif -%}

CSS

## CSS Optimization
- [ ] Inline critical CSS for above-fold content
- [ ] Load non-critical CSS asynchronously
- [ ] Remove unused CSS selectors
- [ ] Minimize CSS bundle size
- [ ] Avoid `@import` in CSS files
- [ ] Use CSS custom properties for theming
- [ ] Minimize specificity and nesting

CSS Loading Strategies

{# Critical CSS inline #}
<style>
{# Above-fold styles #}
.header { ... }
.hero { ... }
</style>
{# Non-critical CSS with preload #}
<link rel="preload" href="{{ 'theme.css' | asset_url }}" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="{{ 'theme.css' | asset_url }}"></noscript>

Fonts

## Font Optimization
- [ ] Use `font-display: swap` or `optional`
- [ ] Preload critical fonts
- [ ] Limit font weights and styles
- [ ] Use system fonts as fallbacks
- [ ] Subset fonts if using custom uploads

Font Loading

{# Preload critical fonts #}
<link rel="preload" href="{{ settings.type_heading_font | font_url }}" as="font" type="font/woff2" crossorigin>
{# Font face with swap #}
{{ settings.type_heading_font | font_face: font_display: 'swap' }}

Third-Party Resources

## Third-Party Optimization
- [ ] Audit all third-party scripts
- [ ] Remove unused apps/scripts
- [ ] Lazy load chat widgets
- [ ] Use facade patterns for embeds
- [ ] Self-host critical third-party resources
- [ ] Add `dns-prefetch` for external domains

Resource Hints

{# DNS prefetch for external domains #}
<link rel="dns-prefetch" href="https://cdn.shopify.com">
<link rel="preconnect" href="https://cdn.shopify.com" crossorigin>
{# Preload critical resources #}
<link rel="preload" href="{{ 'theme.css' | asset_url }}" as="style">

Layout Stability (CLS)

## Layout Stability
- [ ] Reserve space for images (aspect-ratio or padding)
- [ ] Reserve space for dynamic content
- [ ] Avoid inserting content above existing content
- [ ] Use CSS transforms for animations
- [ ] Set explicit dimensions for ads/embeds
- [ ] Preload fonts to prevent FOUT/FOIT

Preventing Layout Shifts

/* Reserve space for images */
.product-card__image-wrapper {
aspect-ratio: 1;
background: var(--color-background-subtle);
}
/* Reserve space for lazy-loaded content */
.product-recommendations {
min-height: 400px;
}

Liquid Optimization

## Liquid Performance
- [ ] Minimize Liquid loops inside loops
- [ ] Use `limit` on large collections
- [ ] Cache repeated calculations with `assign`
- [ ] Avoid unnecessary `render` calls
- [ ] Use `{% raw %}{% liquid %}{% endraw %}` for multiple operations
- [ ] Paginate large collections

Liquid Best Practices

{# Good: Cache repeated values #}
{%- assign product_price = product.price | money -%}
{%- for i in (1..3) -%}
{{ product_price }}
{%- endfor -%}
{# Good: Limit collection loops #}
{%- for product in collection.products limit: 12 -%}
{% render 'product-card', product: product %}
{%- endfor -%}
{# Good: Use liquid tag for multiple operations #}
{%- liquid
assign featured = collection.products | where: 'available' | first
assign price = featured.price | money
assign title = featured.title
-%}

Testing Tools

Shopify Tools

## Shopify Performance Testing
- [ ] Theme Editor Performance report
- [ ] Lighthouse via Chrome DevTools
- [ ] Web Vitals Chrome extension
- [ ] Shopify Theme Inspector (Chrome extension)

External Tools

## External Testing Tools
- [ ] PageSpeed Insights
- [ ] WebPageTest.org
- [ ] GTmetrix
- [ ] Chrome DevTools (Performance tab)
- [ ] Chrome DevTools (Network tab, slow 3G)

Performance Budget

Set limits for your theme:

ResourceBudget
Total page weight< 2MB
JavaScript< 300KB
CSS< 100KB
Images (initial)< 500KB
Fonts< 100KB
Third-party< 200KB

Audit Template

# Performance Audit Report
**Date:** 2024-01-15
**Page:** Homepage / Collection / Product
**Device:** Mobile / Desktop
## Metrics (Before)
- LCP: \_\_\_s
- INP: \_\_\_ms
- CLS: \_\_\_
- Total page size: \_\_\_KB
- Requests: \_\_\_
## Issues Found
1.
2.
3.
## Fixes Applied
1.
2.
3.
## Metrics (After)
- LCP: \_\_\_s
- INP: \_\_\_ms
- CLS: \_\_\_
- Total page size: \_\_\_KB
- Requests: \_\_\_

Quick Wins

Immediate Impact

  1. Lazy load below-fold images
  2. Defer non-critical JavaScript
  3. Preload LCP image
  4. Remove unused apps
  5. Optimize hero image size

Medium Impact

  1. Inline critical CSS
  2. Implement font-display: swap
  3. Add resource hints
  4. Paginate collections
  5. Use native lazy loading

Practice Exercise

Audit a theme page:

  1. Run Lighthouse on mobile
  2. Identify top 3 performance issues
  3. Implement fixes
  4. Re-run Lighthouse
  5. Document improvement

Key Takeaways

  1. Core Web Vitals are the key metrics
  2. Images are often the biggest opportunity
  3. JavaScript should be deferred and minimal
  4. Layout stability requires reserved space
  5. Testing tools help identify issues
  6. Performance budgets keep you accountable
  7. Quick wins provide immediate improvement

What’s Next?

The next lesson covers the Accessibility Checklist for inclusive theme development.

Finished this lesson?

Mark it complete to track your progress.

Discussion

Loading comments...