Shopify SEO Titles and Meta Descriptions for 5,000 Products: Templates That Scale
Nobody hand-writes 10,000 title tags and meta descriptions. Here is the three-layer system we use on large Shopify catalogs: Liquid fallbacks, metafield-driven templates and bulk editing, without creating duplicates.

- When the SEO fields are blank, Shopify falls back to the product title plus shop name and a truncated product description, which is how large catalogs end up with thousands of near-identical snippets.
- Google says programmatic meta descriptions are appropriate for large database-driven sites, so templates are fine as long as each output is specific to the page.
- Use three layers: hand-written copy for the top 5% of pages, metafield-driven templates for the middle, and a Liquid fallback in theme.liquid for everything else.
- Shopify product CSVs accept SEO Title (up to 70 characters) and SEO Description (up to 320 characters), but a blank cell in an overwrite import erases the existing value.
- Measure duplicates, not just missing fields: export every title and description and count exact matches before and after each bulk change.
A store with 5,000 products has 5,000 title tags and 5,000 meta descriptions to manage, plus every collection, page and article. Nobody writes 10,000 fields by hand, and nobody should. What most large Shopify stores do instead is nothing, which means Shopify's defaults decide how the whole catalog looks in Google.
This guide shows how to replace those defaults with a system: a Liquid fallback that makes every blank field useful, metafields that feed product-specific details into templates, and a bulk editing workflow that doesn't wipe your data.
What Shopify outputs when the SEO fields are blank#
Every product, collection, page and blog post in the Shopify admin has a "Search engine listing" section with a page title, a meta description and a URL handle. When you save those fields, Shopify stores the values in the title_tag and description_tag metafields in the global namespace. When you leave them blank, the theme falls back.
| Resource | Title tag if blank | Meta description if blank |
|---|---|---|
| Product | Product title, plus shop name (theme-dependent) | Product description, truncated |
| Collection | Collection title, plus shop name | Collection description, truncated |
| Tag-filtered collection | Collection title + "tagged [tag]" | Same as the parent collection |
| Paginated collection | Collection title + "Page 2" | Same as page 1 |
| Blog article | Article title, plus shop name | Article excerpt or body, truncated |
The title fallback is usually acceptable. The description fallback is where large catalogs fall apart. Product descriptions on big stores often start with the same boilerplate: a shipping promise, a brand paragraph or a spec header. Truncate that to 160 characters and 3,000 products share one meta description.
Why templated meta descriptions are fine (when done properly)#
There is a myth that every meta description must be hand-written. Google's own snippet documentation says the opposite for big catalogs: for large database-driven sites, "programmatic generation of the descriptions can be appropriate and are encouraged."
The condition is that each output is specific to its page. Google's guidance on titles warns against boilerplate that repeats across many pages, and it will rewrite titles and snippets it considers unhelpful. A template that produces "Buy Product | Store" 5,000 times is boilerplate. A template that pulls the model name, the key spec, the starting price and a delivery fact is not.
Two things to keep in mind:
- Google rewrites snippets often. A meta description is a suggestion. A good one still wins more often than a bad one, and it's what shows in many AI answer previews and social shares.
- Titles matter more than descriptions for rankings. The description mostly affects click-through rate. The title affects both.
The three-layer system#
We split every large catalog into three tiers and treat each one differently.
| Layer | Pages | Who writes | Where it lives |
|---|---|---|---|
| 1. Hand-written | Top 5% by revenue or impressions, all money collections | A human, from Search Console queries | Shopify SEO fields |
| 2. Metafield template | The next 20–40% of products | Template + one short custom field per product | Product metafields |
| 3. Liquid fallback | Everything else | Nobody, the theme builds it | theme.liquid or a snippet |
The fallback goes in first because it fixes every page at once. Then you work top-down, replacing fallbacks with hand-written copy where the traffic justifies it.
Layer 3: the Liquid fallback in theme.liquid#
The idea is simple. If a product or collection has a custom SEO field, use it. If it doesn't, build something specific from data Shopify already has: title, product type, vendor, starting price and product count.
Create snippets/seo-meta.liquid and render it in layout/theme.liquid in place of the existing <title> and meta description tags:
{%- liquid
assign seo_title = page_title
assign seo_desc = page_description | strip_html | strip_newlines | strip
assign promise = shop.metafields.custom.shipping_promise.value
case request.page_type
when 'product'
if product.metafields.global.title_tag == blank and product.type != blank
assign seo_title = product.title | append: ' | ' | append: product.type
endif
if product.metafields.global.description_tag == blank
assign from_price = product.price_min | money_without_trailing_zeros | strip_html
assign hook = product.metafields.custom.meta_hook.value | default: product.type
assign seo_desc = product.title | append: '. ' | append: hook | append: '. From ' | append: from_price | append: '. ' | append: promise
endif
when 'collection'
if collection.metafields.global.description_tag == blank
assign seo_desc = 'Shop ' | append: collection.all_products_count | append: ' ' | append: collection.title | append: ' from ' | append: shop.name | append: '. ' | append: promise
endif
endcase
-%}
<title>
{{ seo_title | escape }}
{%- if current_tags %} – {{ current_tags | join: ', ' | escape }}{% endif -%}
{%- if current_page != 1 %} – Page {{ current_page }}{% endif -%}
{%- unless seo_title contains shop.name %} | {{ shop.name | escape }}{% endunless -%}
</title>
<meta name="description" content="{{ seo_desc | truncate: 158 | escape }}">A few notes on how this behaves:
page_titlealready returns the custom SEO title when one exists, so the template only runs when the field is empty.- The
shipping_promisevalue is a single shop-level metafield ("Free freight delivery in the lower 48", for example). Change it once, and every fallback description updates. - Prices render in the currency of the storefront context. Googlebot mostly crawls from the US, so on multi-currency stores that's usually the price Google sees.
- Tag pages and paginated pages get a suffix so they aren't exact duplicates of the parent. Whether tag pages should be indexed at all is a separate question, covered in tag pages vs collections vs filters.
Layer 2: metafields that make templates specific#
The fallback is only as good as the data behind it. "From $4,299" helps. "8 ft, 1-inch three-piece slate, solid hardwood" helps far more. That kind of detail doesn't exist in Shopify's standard fields, so we add it with metafields.
Create a product metafield definition under Settings → Metafields and metaobjects → Products:
- Name: Meta hook
- Namespace and key:
custom.meta_hook - Type: Single line text
- Guidance for writers: 60–80 characters, the one fact a buyer would want before clicking
Examples of good hooks:
| Product | Meta hook |
|---|---|
| 8 ft slate pool table | 1-inch three-piece slate, solid oak frame, installation included |
| 36-inch built-in gas grill | Five 304 stainless burners, 950 sq in cooking area, propane or natural gas |
| 4-person barrel sauna | Thermally modified wood, 8 kW heater, ships in two freight boxes |
| 10x12 polycarbonate greenhouse | 6 mm twin-wall panels, aluminum frame, roof vents included |
Writing one 70-character line per product is realistic. A copywriter can do several hundred a day from a spec sheet. Writing a full 155-character description per product is not, and the output isn't much better.
Product metafields also appear in Shopify's CSV export as columns named like Meta hook (product.metafields.custom.meta_hook), so hooks can be written in a spreadsheet and imported in bulk. Variant metafields are not supported in CSV import, so keep hooks at the product level.
Title templates that scale#
Titles need more care than descriptions because they carry ranking weight. Shopify's admin accepts up to 70 characters in the SEO title field and suggests staying around 60 to avoid truncation. We aim for 50–60.
| Page type | Template | Example |
|---|---|---|
| Product | Model + key spec + product type | Ashford 8 ft Slate Pool Table, Oak |
| Product (brand-searched) | Brand + model + type | Ashford Classic 8 ft Pool Table |
| Collection | Keyword + qualifier | 8 ft Pool Tables: Slate, Delivered and Installed |
| Collection (long tail) | Keyword + audience or use | Outdoor Pool Tables for Covered Patios |
| Blog article | The search question, answered | How Big a Room Do You Need for an 8 ft Pool Table? |
Two rules keep product titles from colliding:
- Put the distinguishing attribute early. If you sell 40 grills, "Built-In Gas Grill | Brand" appears 40 times. "36-inch 5-Burner Built-In Gas Grill" appears once.
- Don't repeat the keyword. Google's title guidance calls out repeated words as spam-like. "Pool Table | Pool Tables | Buy Pool Tables" gets rewritten.
Meta description formulas#
For hand-written and template descriptions, we use a small set of formulas and rotate them by page type so the SERP doesn't look like a wall of clones.
| Formula | Best for | Example |
|---|---|---|
| Spec + price + delivery | Products | 8 ft pool table with 1-inch slate and solid oak frame. From $4,299 with free freight delivery and installation. |
| Count + range + reason | Collections | Compare 24 outdoor saunas from 2 to 6 person, with electric and wood-burning heaters. Free delivery in the lower 48. |
| Question + promise | Guides | How much room does an 8 ft pool table need? Room-size charts for every cue length, plus what to do in tight spaces. |
Keep each one between roughly 120 and 158 characters, lead with the most specific fact and never put the store name at the start.
Bulk editing without destroying data#
There are four ways to edit SEO fields in bulk on Shopify, and each has a trap.
1. Native product CSV import#
Export products, edit the SEO Title and SEO Description columns, then import with "Overwrite products with matching handles". Shopify's docs list the limits as 70 characters for SEO Title and 320 for SEO Description, and blank cells fall back to the product title and description.
2. The admin bulk editor#
Select products, choose Bulk edit, then add the SEO title and SEO description columns from the column picker. Good for fixing 50 products. Painful for 5,000.
3. Spreadsheet-style import apps#
Native CSV only covers products. For collections, pages, blog posts, redirects and translations, most large stores use a spreadsheet-style import/export app that reads and writes the global.title_tag and global.description_tag fields for every resource type. The same blank-cell caution applies, so read the app's docs on how it treats empty values.
4. The Admin API#
For developers, the GraphQL Admin API accepts an seo input with title and description on product and collection updates. This is the right route when titles are generated from a PIM or ERP.
Finding and fixing duplicates#
Missing fields are easy to spot. Duplicates are the real problem at scale, and they're invisible in the admin. After every bulk change, export and count.
Column A: URL
Column B: Title tag (from a crawl)
Column C: Meta description (from a crawl)
Column D: =COUNTIF(B:B, B2) // duplicate title count
Column E: =COUNTIF(C:C, C2) // duplicate description count
Column F: =LEN(B2) // title lengthCrawl the rendered pages rather than trusting the CSV, because the CSV shows stored values and the crawl shows what the theme actually outputs. Anything with a count above 1 needs a more specific template or a hand-written field.
Duplicate titles are usually a symptom of duplicate pages. If two products share a title because they're the same item in two colors, that's a variant question, covered in Shopify variants and the 2,048-variant limit. For the other duplication sources Shopify creates, see Shopify duplicate content.
Collections deserve hand-written fields#
For collections, skip the template entirely on anything that targets a commercial keyword. A store with 5,000 products might have 150 collections, and those are the pages that rank for the highest-value searches. Write every title and description by hand, based on the queries each collection already gets in Search Console. Our collection page SEO guide covers the rest of the page.
International stores and Chinese brands#
If you sell in several languages through Shopify Markets, every translated product needs its own SEO title and description. Shopify's Translate & Adapt app and most translation apps expose these fields, but machine translation of a 60-character title often lands at 75 characters in German or reads unnaturally in English.
For Chinese brands writing English metadata from Chinese source data, the most common problem we see is the supplier title leaking into the SEO title: "2026 New Hot Sale Car Phone Holder Magnetic Universal". Write titles in the words Western buyers search, not the words used on marketplaces. We cover this in more depth on our Chinese brands and international SEO pages.
A two-week rollout for a 5,000-product store#
| Days | Work |
|---|---|
| 1–2 | Crawl the store. Export titles and descriptions. Count duplicates by page type. |
| 3–4 | Build the Liquid fallback on a duplicate theme. Test products, collections, tags and pagination. |
| 5 | Publish the theme. Create the meta_hook and shipping_promise metafields. |
| 6–10 | Write hooks for the top 1,000 products by revenue. Import via CSV. |
| 11–14 | Hand-write titles and descriptions for every money collection and the top 5% of products. Recrawl and recount. |
Then check Search Console after four to eight weeks. Filter by page groups (/products/ and /collections/) and compare click-through rate at similar average positions. That's the metric this work moves. For everything else to audit alongside it, run through the Shopify SEO checklist.
Questions people ask about this
Where does Shopify store SEO titles and meta descriptions?
When you fill in the search engine listing fields in the Shopify admin, the values are stored as metafields in the global namespace: title_tag and description_tag. Themes output them through the page_title and page_description Liquid objects. If the fields are blank, the theme falls back to the resource title and a truncated description, which is why blank fields cause duplicates on large catalogs.
Is it OK to use templates for Shopify meta descriptions?
Yes, if each output is specific to its page. Google's snippet documentation says programmatic generation is appropriate for large database-driven sites. The problem is templates that only swap the product name into generic text. Pull in a real differentiator such as a key spec, starting price or delivery fact, and hand-write the fields for your highest-value pages.
How long should a Shopify SEO title be?
Shopify allows up to 70 characters in the SEO title field and suggests keeping it around 60 to avoid truncation. We aim for 50 to 60 characters, with the distinguishing attribute (size, model, key spec) early in the title. Google truncates to fit the device width, so front-load what matters and leave the store name for the end.
Can I bulk edit Shopify SEO titles with a CSV?
For products, yes. The product CSV has SEO Title and SEO Description columns. Export, edit, and import with overwrite enabled. Remove every column you are not changing first, because blank cells in included columns erase existing values. Collections, pages and blog posts are not in the native CSV, so they need a spreadsheet-style import app or the Admin API.
Should the meta description include the price?
For products with stable pricing it usually improves click-through, especially for high-ticket items where buyers want a range before clicking. If you run frequent sales, render the price from Liquid so it updates automatically, and accept that Google may show a slightly stale snippet until it recrawls. For collections, a price range or "from" price works well.
Want this done on your store?
SEO for Shopify stores with 1,000 to 100,000 SKUs: faceted navigation, variants, crawl budget, programmatic collections with metaobjects and internal linking at scale.
More from Technical SEO

The Shopify Apps Slowing Down Your Store and Quietly Hurting SEO (Plus a 20-Minute Audit)
Shopify apps slow down your store, leave code behind after you uninstall them, and sometimes change what Google sees. This 20-minute audit shows where to look and what to remove.

Crawled – Currently Not Indexed on Shopify: Why Google Skips Your Pages
Crawled – currently not indexed means Google fetched a page and chose to leave it out. On Shopify most of those URLs are harmless; here is how to find the few that cost you sales and fix them.

Shopify Speed Optimization: Fixing LCP on Collection Pages Without Killing Apps
Why Shopify collection pages fail LCP, how to find the real LCP element, and the fixes in order: image loading, animations, app scripts and Liquid render time.