SEODec 4, 2025·14 min read

Shopify SEO: Dynamic Heading Tags, Typography Overrides, and Performance Wins

Capconvert Team

Content Strategy

TL;DR

Most Shopify stores ship with broken heading hierarchies, bloated font stacks, and CSS that quietly sabotages their Core Web Vitals. The damage rarely shows up in the theme editor. It shows up in Google Search Console - pages flagged with poor LCP, creeping CLS scores, and organic traffic that plateaus for no obvious content reason. The problem isn't that Shopify is a bad platform for SEO.

Most Shopify stores ship with broken heading hierarchies, bloated font stacks, and CSS that quietly sabotages their Core Web Vitals. The damage rarely shows up in the theme editor. It shows up in Google Search Console - pages flagged with poor LCP, creeping CLS scores, and organic traffic that plateaus for no obvious content reason. The problem isn't that Shopify is a bad platform for SEO. According to the Core Web Vitals Technology Report, Shopify leads WordPress on mobile CWV pass rates - around 65% versus 44% as of late 2025 - thanks to its excellent default infrastructure: fast servers, a global CDN via Cloudflare, automatic image format conversion, and pre-optimized base themes. The problem is what merchants and developers layer on top: apps injecting scripts globally, themes loading six font weights nobody asked for, and heading structures that confuse crawlers into ignoring your most important content. This guide covers three specific technical levers that interact in ways most Shopify SEO advice overlooks. Get heading tags right and search engines understand your page hierarchy. Control typography loading and you protect both brand consistency and visual stability. Chain those wins together and your store doesn't just rank - it converts faster because it loads faster.

Why Shopify Themes Ship With Broken Heading Hierarchies

The Shopify Dawn theme homepage is not optimized for great SEO by default. When auditing a Shopify store with a tool like Ahrefs, it will warn you that the H1 tag is empty - because the shop's logo is wrapped in an H1 tag with no text in it. This is a missed opportunity to help search engines understand what your page is about.

This isn't a Dawn-specific quirk. Most Shopify themes automatically include a heading tag around the logo or store name, and search engine crawlers like Google or Bing will ignore a heading tag if it's wrapped around an image or logo. The result: your homepage has an H1 that communicates nothing, your product pages may have duplicate H1s from breadcrumb plugins, and your collection pages sometimes prefix "Collection:" before the actual heading text.

Common heading problems include multiple H1 tags on a single page, improper use of H2 and H3, empty or unnecessary heading tags in header and footer sections, and overuse of H2 tags where a div would be more appropriate. These issues result in a confusing content structure for search engines, ultimately hurting rankings.

The deeper issue is architectural. A frequently recurring problem in Shopify themes is multiple H1 heading tags. For best SEO, there should be one H1 on a page and the rest as H2, H3, H4 headings. If a theme has a section - say, a slideshow - with an H1 heading in it and you include that section multiple times on the same page, you end up stuck with multiple H1 headings. You can't simply edit the section code to change H1 to H2 because then you'd lose the H1 entirely.

How Dawn Handles the H1 Conditionally

Looking at the actual Dawn theme source code reveals an interesting pattern. In Dawn's header.liquid, the logo is wrapped in an H1 tag only when the page type is 'index' (the homepage). On all other pages, it renders without the H1 wrapper. This means Dawn attempts conditional heading logic - but it still assigns the H1 to an image rather than descriptive text.

On Shopify product pages, the H1 is the title of the product, and on collection pages the H1 is the name of the collection. So the heading problem is primarily a homepage issue in Dawn. But third-party themes and custom sections compound the problem on every page type.

Building Dynamic Heading Tags With Liquid Logic

The fix requires making heading tags context-aware through Liquid template logic. Rather than hard-coding H1 or H2 into section files, you add a schema setting that lets each section declare its heading level.

The solution is adding a new setting to the section to allow you to select it as an H1 or H2 section. Here is the pattern. In your section's {% schema %} block, add a select input:

{
  "type": "select",
  "id": "heading_type",
  "label": "Heading type",
  "options": [
    { "label": "H1", "value": "h1" },
    { "label": "H2", "value": "h2" }
  ]
}

Then in the section's Liquid markup, wrap the heading output in a conditional:

{%- if section.settings.heading_type == 'h2' -%}
  <h2 class="section-heading">{{ block.settings.title }}</h2>
{%- else -%}
  <h1 class="section-heading">{{ block.settings.title }}</h1>
{%- endif -%}

After making this change, changing the heading type setting for the section toggles between H1 and H2 output. Since you're sometimes using an H2 instead of an H1, the text may appear in a different style - every theme is different, so you'll need to edit your CSS styles for the H2 so it looks as intended.

The Homepage H1 Fix: A Two-Stage Process

For the homepage specifically, the fix involves two steps. First, remove the H1 tag that wraps your shop logo in the header. Second, add an H1 back to your homepage in the content.

In the header.liquid file, search for the id "header__heading-link" and replace the H1 with a div to eliminate the unnecessary H1 tag. Then use one of two approaches:

  • Custom Liquid block: Add a Custom Liquid section to the homepage template with your keyword-optimized H1 inside it. Simple, isolated, won't affect other pages.
  • Conditional rich-text output:

Modify sections/rich-text.liquid so the Heading field within the Rich text block outputs as an H1 on the homepage but as an H2 on every other page, avoiding multiple H1 tags on internal pages.

The second approach is more elegant because it gives content editors a familiar interface. They type the heading in the theme editor. The Liquid template decides what HTML tag wraps it based on request.page_type.

Validating Your Heading Structure

After making changes, don't trust the theme preview. Use the Detailed SEO Chrome extension or SEO Pro Extension and navigate to the Headings section to verify each heading was updated correctly. View Page Source is the ultimate truth. Run every page template - homepage, product, collection, blog post - and confirm:

  • Exactly one H1 per page
  • H2 and H3 tags nested sequentially without skipping levels
  • No heading tags wrapping images, icons, or non-text elements
  • Footer and header regions use divs instead of semantic headings for navigation labels

Subheadings should be nested sequentially - H2, then H3, then H4. Skipping from H1 to H3 doesn't break rendering, but it signals to crawlers that your content hierarchy has gaps.

Typography Loading: The Hidden CLS Killer

Font loading is where design intent collides with performance reality. Typography plays a crucial role in branding and user experience, but web fonts can significantly affect your store's performance if not handled correctly. Most Shopify themes - especially those using custom fonts - include multiple font files, weights, and styles that load during every page visit.

Two phenomena cause measurable damage. FOIT - Flash of Invisible Text - is when the browser loads the page without the text while the web font is being downloaded, then suddenly draws the page. This is considered a bad user experience because all written content is blocked during download time.

FOUT - Flash of Unstyled Text - is when the browser uses a system font while the web font is being downloaded, then redraws the text with the web font once available. There are going to be several differences between the system font and the web font.

Both affect Core Web Vitals directly. LCP measures how long it takes for the largest visible element on your page - often a hero heading or image - to fully render. When your hero heading uses a custom font that hasn't loaded yet, LCP waits. And late font swaps cause Cumulative Layout Shift. When a custom font swaps in where a fallback was rendering, different character metrics cause text blocks to reflow - pushing content down or up, moving buttons, rearranging page elements. CLS directly affects Google's page experience ranking signals.

Choosing the Right font-display Strategy

The font-display CSS descriptor controls what users see while fonts load. Four values matter:

  • swap: Zero block period, infinite swap period. Shows fallback immediately, swaps to custom font whenever it arrives.
  • fallback: ~100ms block period, ~3 second swap window. If the font doesn't arrive within 3 seconds, the fallback sticks.
  • optional: ~100ms block period, no swap period. The browser may skip the custom font entirely on slow connections.
  • block: Short block period (~3s), infinite swap. Hides text while loading. Avoid this for body text.

The current best practice for body text is font-display: swap combined with a metric-adjusted fallback font. With this setup, the fallback and custom font are so metrically similar that the swap produces almost no CLS. Users see text immediately, in a fallback that closely matches the final appearance.

For Shopify themes, set this in your @font-face declaration or use Liquid's built-in font filter: {{ settings.type_body_font | font_face: font_display: 'swap' }}.

Reducing Font File Weight

Every font weight and style - bold, italic, light - is a separate file download. If your theme loads Regular, Medium, SemiBold, Bold, and Italic variants of a font, that is five font files, each adding a network request. Audit which variants are actually displayed on your pages and remove loading for variants that are not used.

Practical thresholds: - Limit font files to 2–3 per font family. Stick to core weights like regular and bold.

  • Keep combined font file sizes under 100KB. If you're seeing 300KB+ on font files alone, it's time for a cleanup.
  • Subset your web fonts - strip out characters you don't use and cut font file sizes by 70%. Your English store doesn't need Cyrillic characters.

Use WOFF2 format exclusively for modern browsers. WOFF2 uses Brotli compression, which produces the smallest file size and is supported by all modern browsers.

Preloading Fonts and Critical CSS for Faster LCP

Reducing font weight is only half the equation. The other half is sequencing - making sure the browser downloads critical fonts before it encounters text that needs them.

Before preload, fonts couldn't download until the DOM and CSSOM were generated - the browser needed to download the HTML and linked CSS files first to discover which font files to fetch. With preload, front-end developers can tell the browser to download the font files at the same time as the CSS files. The faster the fonts download, the faster they can be rendered.

In your theme.liquid, add preload hints high in the <head>, above your CSS references:

<link rel="preload"
      href="{{ settings.type_header_font | font_url }}"
      as="font"
      type="font/woff2"
      crossorigin>
<link rel="preload"
      href="{{ settings.type_body_font | font_url }}"
      as="font"
      type="font/woff2"
      crossorigin>

Over-preloading every font file in your theme is unnecessary and can lead to slower page loads from fetching resources that aren't immediately needed. Stick to preloading only the most critical fonts - typically your heading and body text regular weight. Skip italic variants and below-the-fold display fonts.

Inlining Critical CSS

While Shopify is great at loading components on an as-needed basis, this can lead to too many CSS files loading on a single page. This becomes a problem for components above the fold because their CSS is render-blocking, meaning the page won't appear until those files are loaded. The solution is to inline the critical styles - the CSS needed for elements above the fold - directly into the page.

Keep critical CSS small - target under 14KB after minification. Prioritize above-the-fold content only. Structure your approach by page type: product detail pages need product image, price, and CTA styles inline; collection pages need grid and filter styles; the homepage needs hero and navigation styles.

This optimization can be taken further by dynamically rendering critical styles for different page types. It's especially effective for product detail pages, since most customer traffic enters a site through this side door rather than the homepage.

How App Bloat Undoes Your Performance Gains

You can perfect your heading hierarchy and optimize every font file, only to watch a single app installation push your LCP past Google's threshold.

Installed Shopify apps are the single biggest cause of Core Web Vitals failure on Shopify stores. Every app can inject JavaScript and CSS onto every page of your store, even pages where that app is not used. The math is stark: on average, a new Shopify app adds 50KB to 150KB of JavaScript to every page load. For a store that is right at the LCP threshold - 2.3 to 2.5 seconds - a single app installation can push it over the edge.

Some apps add code directly to your theme files during installation. Uninstalling the app may not remove this code. You need to manually check the snippets/ and sections/ directories for leftover files. This is one of the most common causes of mysterious performance regressions - a store owner uninstalls an app from the admin but the injected code persists in the theme. Build a monthly performance review cadence. Check Search Console's Core Web Vitals report for field data across your entire store, use PageSpeed Insights for individual product, collection, and homepage URLs, and monitor after every app installation, theme update, and seasonal campaign launch.

Measuring Real Impact: Lab Data vs. Field Data

Shopify's Speed Score in the admin dashboard is based on Lighthouse lab data from a single simulated visit. Core Web Vitals in Google Search Console use field data from real Chrome users over a 28-day rolling window. These numbers can differ significantly because real users have different devices, network speeds, and interaction patterns than the Lighthouse simulation.

Lab data tells you what could be slow. Field data tells you what is slow for your actual customers. Always prioritize field data for decision-making and use lab data for debugging specific issues.

The INP Factor: Why Interaction Speed Matters More Now

Interaction to Next Paint (INP) is now a stable Core Web Vital metric, and has officially replaced First Input Delay (FID). This shift happened in March 2024, and its implications for Shopify stores are still underappreciated.

FID only measured the input delay of the very first interaction on the page. INP, in contrast, considers all relevant interactions during a visit and measures Input Delay, Processing Time, and Presentation Delay. This allows INP to better represent and assess perceived responsiveness.

For Shopify stores, this means every add-to-cart button click, every variant selector change, and every filter interaction on a collection page is now measured. INP has a "good" threshold of 200ms or less. Third-party app scripts that block the main thread - review widgets, chat tools, popups - are the primary offenders. The connection to heading tags and typography might not be obvious, but it's real. A bloated CSS file that includes unused font declarations still needs to be parsed by the browser. That parsing occupies the main thread. When a user clicks "Add to Cart" while the browser is still processing CSS, the input delay increases and INP suffers.

Putting It All Together: An Implementation Sequence

The order matters. Fixing these issues in the wrong sequence can mask problems or create new ones. Week 1: Audit and baseline. Run PageSpeed Insights on your homepage, top product page, and top collection page. Record LCP, CLS, and INP. Use the Detailed SEO Chrome extension to audit heading structure on every page template. Document every heading tag - its level, content, and whether it wraps text or an image. Week 2: Fix heading hierarchy. Remove the H1 from your logo in header.liquid. Add dynamic heading settings to every reusable section. Set one and only one H1 per page template. Validate with View Source on every page type. Week 3: Optimize typography. Audit loaded font files in Chrome DevTools Network tab (filter by "font"). Remove unused weights. Subset files for your target languages. Add font-display: swap to all @font-face declarations. Implement preload hints for critical fonts. Match fallback fonts metrically using tools like the Fallback Font Generator. Week 4: Cut render-blocking CSS and audit apps. Inline critical above-the-fold CSS for each page type. Defer non-critical stylesheets. Audit every installed app's script impact individually using Chrome DevTools Performance panel. Remove unused apps and manually delete leftover code from your theme's snippets/ directory. Ongoing: Monitor and protect.

Performance regressions on Shopify are almost always caused by something that was recently added. Set a calendar reminder for monthly checks. The most common cause of Shopify CWV regression is a new app installation that injects JavaScript globally. The second most common cause is seasonal campaign elements - banners, popups, timers - added for a sale event and forgotten afterward. --- These three areas - heading structure, typography performance, and CSS delivery - are not isolated optimizations. They share a common thread: controlling what the browser does in the first 2.5 seconds of a page load. A 100ms delay in load time reduces conversions by 1%. Google's Core Web Vitals are a confirmed ranking factor since 2021. The median Shopify store LCP is 4.2 seconds - nearly double Google's "Good" threshold of 2.5 seconds.

The stores that close that gap don't do it with a single speed optimization app or a theme swap. They do it by understanding how HTML semantics, font loading behavior, and CSS delivery interact at the rendering pipeline level. Every heading tag that tells Google what your page is about, every font file you trim, and every kilobyte of CSS you move out of the critical path compounds into a store that both search engines and shoppers prefer.

Ready to optimize for the AI era?

Get a free AEO audit and discover how your brand shows up in AI-powered search.

Get Your Free Audit