Performance & SEO

Shopify handles hosting-level performance (servers, CDN, uptime) for you — what's left in a theme developer's control is how efficiently a theme renders and how well it's marked up for search engines. Both come down to specific, checkable practices rather than vague advice.

Theme performance basics

The single biggest lever most themes have is images — using image_tag or a proper srcset (covered in lesson 11) instead of one oversized file avoids the most common source of slow-loading pages. Beyond images: load JavaScript with defer so it doesn't block rendering, avoid render-blocking third-party scripts in theme.liquid's <head>, and prefer a handful of small, focused sections over one enormous monolithic template.

Liquid non-blocking script loading
<script src="{{ 'theme.js' | asset_url }}" defer></script>

Shopify's built-in performance tooling

Shopify exposes a Theme Store performance benchmark and Core Web Vitals data directly for any theme, calculated from real shopper page loads rather than a synthetic lab test — useful for spotting a regression after a theme change, since the numbers reflect actual traffic instead of a single test run.

Meta tags and canonical URLs

A well-built theme.liquid generates title tags, meta descriptions, and canonical URLs dynamically per page rather than hardcoding one value site-wide:

Liquid dynamic head tags
<title>{{ page_title }}{% if current_tags %} – tagged "{{ current_tags | join: ', ' }}"{% endif %}{% unless current_page == 1 %} – Page {{ current_page }}{% endunless %}</title>
<meta name="description" content="{{ page_description | escape }}">
<link rel="canonical" href="{{ canonical_url }}">

Shopify computes sensible defaults for page_title, page_description, and canonical_url automatically based on the current resource, so a theme mainly needs to output them correctly rather than build them from scratch.

Structured data (JSON-LD)

Adding schema.org structured data helps search engines understand a page well enough to show rich results — star ratings, price, and availability directly in search listings. A product template typically embeds this as a JSON-LD script block built from the same product object already used elsewhere on the page:

Liquid product structured data
<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": {{ product.title | json }},
  "image": {{ product.featured_image | image_url: width: 800 | json }},
  "offers": {
    "@type": "Offer",
    "price": {{ product.price | divided_by: 100.0 | json }},
    "priceCurrency": {{ cart.currency.iso_code | json }}
  }
}
</script>

Piping every value through the json filter matters here — it correctly escapes quotes and special characters for valid JSON, which a plain Liquid output wouldn't necessarily do.

Sitemap and robots behavior

Shopify automatically generates and maintains /sitemap.xml and a default robots.txt for every store, including handling canonicalization of duplicate URLs (like a product reachable through more than one collection) — this is one area a theme developer doesn't need to build manually, though Shopify does allow overriding robots.txt rules through the Admin when a store has specific needs.

Note: a fast, well-marked-up theme still can't compensate for thin or duplicate product content — structured data and page speed help search engines understand and prefer a page, but they don't substitute for the underlying content actually being worth ranking.