August 30, 2026

Shopify product page audit checklist

Shopify product page audit checklist

You went looking for a product page audit checklist and you found one. Probably several. They agree with each other more than you'd expect: write longer descriptions, add more images, fill in the product type, keep the title short, add alt text, show a compare-at price.

What none of them gives you is the other half of the sentence. "Add more images" — more than how many? "Most stores only have one" would be a useful thing to know before you spend a weekend on it. "Fill in your product type" — is a blank product type an oversight, or does half the platform leave it blank on purpose?

Without that, a checklist can only do one thing to you: it makes every item look like a defect. You finish the list with forty items flagged across four hundred products and no way to tell which ones mean you're behind and which ones mean you're normal.

So we went and got the denominators. We read the public catalogues of 41 live Shopify storefronts — 20,604 products — and measured eleven of the items that show up on nearly every one of these checklists. What comes back is not the shape a checklist implies. Three of them are the majority state — not of stores, of products: on two of them, two thirds or more of every product we read would be marked as failing.

Key takeaways

  • Eleven common checklist items, with a number attached to each. Across 20,604 products on 41 live stores: description empty 2.7%, description under 200 characters 21.4%, no images at all 0.2%, one image or none 34.6%, three images or fewer 55.8%, product type blank 36.6%, no tags 19.9%, title over 60 characters 13.6%, single variant 65.6%, no compare-at price 73.2%, out of stock but still listed 10.3%.
  • The rare stuff is where the real mistakes are. Nobody leaves descriptions blank on purpose — 553 products (2.7%) had an empty description, spread over 13 of the 41 stores, and not one store had it on every product. Same shape for out-of-stock-but-still-listed: 31 stores had some, no store had it everywhere. Those are accidents, which is exactly why they're worth your morning.
  • Three of the eleven items are not defects. 65.6% of products have a single variant, 73.2% carry no compare-at price, 55.8% have three images or fewer. A "you should have variants" or "add a compare-at price" line item is asking you to change your merchandising, not fix your page.
  • The number that matters is how many stores fail a check on every product. Product type was blank on every product in 9 of the 41 stores; tags were blank on every product in 4. For those stores the checklist item isn't "fix 400 pages" — it's a week of work with a decision at the front of it.
  • You can measure your own store in about a minute. The script below reads your public /products.json, runs the same eleven checks, and prints your numbers next to ours.

Sample: 41 live Shopify stores, catalogues read 2026-08-26 and figures computed 2026-08-30, drawn at random from a public list of storefronts whose owners posted their own URL on the Shopify Community's Store Feedback board asking for critique. Not a cross-section of Shopify. Method is at the end.

Run the same eleven checks on your own store

Before reading our numbers, get yours. Shopify publishes every active product's fields on /products.json — no app, no login, nothing installed. Swap in your domain and run this:

# save as audit.py, then: python3 audit.py
import json, urllib.request
from collections import Counter

STORE = "your-store.com"          # swap in your own domain

BASELINE = {                      # 41 live stores, 20,604 products, read 2026-08-26
    "description empty":           2.7,
    "description under 200 chars": 21.4,
    "no images at all":            0.2,
    "1 image or none":            34.6,
    "3 images or fewer":          55.8,
    "product type blank":         36.6,
    "no tags":                    19.9,
    "title over 60 chars":        13.6,
    "single variant":             65.6,
    "no compare-at price":        73.2,
    "out of stock, still listed": 10.3,
}

prods, page, MAXPAGE = [], 1, 60          # 60 x 250 = 15,000 products
while page <= MAXPAGE:
    url = f"https://{STORE}/products.json?limit=250&page={page}"
    batch = json.load(urllib.request.urlopen(url))["products"]
    if not batch:
        break                     # stop on an EMPTY page, not a short one
    prods += batch
    page += 1
else:
    print(f"!! stopped at {MAXPAGE * 250} products - raise MAXPAGE. "
          f"The percentages below cover only part of your catalogue.\n")

hits = Counter()
for p in prods:
    body = p.get("body_html") or ""
    imgs = p.get("images") or []
    vs   = p.get("variants") or []
    tags = p.get("tags") or []
    if isinstance(tags, str):
        tags = [t for t in tags.split(",") if t.strip()]

    if len(body) == 0:                            hits["description empty"] += 1
    if len(body) < 200:                           hits["description under 200 chars"] += 1
    if len(imgs) == 0:                            hits["no images at all"] += 1
    if len(imgs) <= 1:                            hits["1 image or none"] += 1
    if len(imgs) <= 3:                            hits["3 images or fewer"] += 1
    if not (p.get("product_type") or "").strip(): hits["product type blank"] += 1
    if not tags:                                  hits["no tags"] += 1
    if len(p.get("title") or "") > 60:            hits["title over 60 chars"] += 1
    if len(vs) <= 1:                              hits["single variant"] += 1
    if vs and not any(v.get("compare_at_price") for v in vs):
                                                  hits["no compare-at price"] += 1
    if vs and not any(v.get("available") for v in vs):
                                                  hits["out of stock, still listed"] += 1

n = len(prods)
print(f"{n} published products on {STORE}\n")
print(f"{'check':<30}{'you':>8}{'41 stores':>12}")
for k, base in BASELINE.items():
    pct = 100 * hits[k] / n if n else 0
    print(f"{k:<30}{pct:>7.1f}%{base:>11.1f}%")

It stops paging when a page comes back empty, not when a page comes back short — a short page mid-catalogue is normal, and stopping there will undercount you badly. And the description length is the raw body_html character count including HTML tags, which is how we measured ours: it's a floor on "is there anything here at all," not a word count. The "under 200 characters" bucket includes the empty ones. Each test above is the same test we ran, so the two columns compare.

It only reads, and only the pages any visitor can already load: published products. Drafts and archived products aren't in it.

The eleven checks, and how many stores actually fail them

Check % of the 20,604 products Stores with any (of 41) Stores where it's every product
Description empty 2.7% (553) 13 0
Description under 200 chars 21.4% (4,407) 26 0
No images at all 0.2% (51) 8 0
One image or none 34.6% (7,119) 34 1
Three images or fewer 55.8% (11,498) 40 1
Product type blank 36.6% (7,536) 35 9
No tags 19.9% (4,095) 35 4
Title over 60 characters 13.6% (2,795) 29 1
Single variant 65.6% (13,516) 39 2
No compare-at price 73.2% (15,075) 40 12
Out of stock, still listed 10.3% (2,130) 31 0

Three of those rows sit inside others, so don't add them up: every product with no images is also counted in "one image or none," every empty description is also counted in "under 200 chars," and every one-image product is also inside "three images or fewer."

The last column is the one that pays for itself. A check that some stores fail on every single product is not a mistake being made four hundred times — it's a field that store never uses. Product type is blank everywhere in 9 of the 41 stores; tags are blank everywhere in 4; compare-at price is absent from every product in 12. Those stores didn't slip. They made a decision, or never made one, and either way "go fill in 400 product types" is a project, not a fix.

Turn it around and the rare items get more interesting, not less. Nobody in this sample left descriptions empty across their whole catalogue. Nobody left their entire catalogue out of stock and published. Those two only ever appear as scattered products inside otherwise-maintained stores — which is what "we missed one" looks like.

The checks worth acting on today

Ordered by how unusual they are. The rarer a thing is, the more likely somebody slipped rather than decided.

A product with no image at all. Only 51 products out of 20,604 — 0.2% — had zero images. That's the rarest thing in this whole dataset. If your store has some, they're almost certainly leftovers from an import or a half-finished draft that got published, and they're the first thing to look at.

An empty description. 553 products, 2.7%, across 13 of the 41 stores, none of which had it catalogue-wide. Same reading: a store with a blank description on some products is a store that writes descriptions and missed a few.

Out of stock, still listed. 10.3% — 2,130 products — were published with no available variant, in 31 of the 41 stores. Sometimes that's deliberate: you're holding the page for a restock. Sometimes you just didn't notice. No store in the sample had it everywhere, so it's not a house style anywhere; it's a per-product decision, and worth confirming you actually made it.

A title over 60 characters. 13.6%, 2,795 products, in 29 of 41 stores. Sixty characters is a convention about how much of a title survives in a search result, not a platform limit — Shopify will happily take longer. It's a cheap check and a minority condition, which is why it sits here rather than in the "everyone does it" bucket below.

Then there's the pile where the actual volume is: descriptions under 200 characters (21.4%, 4,407 products), no tags (19.9%, 4,095), one image or none (34.6%, 7,119), product type blank (36.6%, 7,536). These aren't accidents; they're too common for that. They're the backlog, and every one is a real page someone has to open, read, and decide about.

The three checks that are the majority state, not a defect

This is where the checklist and the data disagree.

Single variant — 65.6% of products. Two thirds of everything we read is one product with one variant, and 39 of the 41 stores have some. A candle comes one way. "Add variants" as an audit line item is asking you to change what you sell.

No compare-at price — 73.2% of products, and 12 stores don't use it anywhere. Compare-at is the strikethrough "was $40" price. Almost three quarters of products don't carry one, and nearly a third of stores in this sample have never set one on anything. Flagging that as a missing field misreads a pricing decision as a data gap.

Three images or fewer — 55.8% of products. The median product here has 3 images. Only 37.6% have five or more. So when a checklist says "use at least five images," it is describing a minority of the catalogue — a real bar you might want to clear, but not one you're currently below because you did something wrong. Note that the sharper cut is a different line: 34.6% have one image or none, and that's the one where a shopper genuinely can't see the thing from a second angle. "Below five" and "only one" are not the same finding, and a checklist with a single images row can't tell them apart.

We're not saying majority equals correct — plenty of things most stores do are still worth not doing. But an audit that reports all three of these as red rows is reporting that you're broken. It measured that you're average.

One thing these numbers can't do. They say how common something is. They don't say what it's worth. We have the public catalogues of these 41 stores and nothing else — no sales figures of any kind. Nothing here says a one-image product sells worse than a five-image one. If you want that, you need a test on your own store. And eleven checks is not a complete audit: page speed, theme layout, review widgets, and the actual quality of a description that exists are all outside what a catalogue endpoint can answer.

When the checklist stops being the hard part

If you ran the script and it flagged fifteen products, you're done in an afternoon. Open them, fix what needs fixing, close the tab. Nothing below applies to you.

The point where this changes isn't when the list gets long — it's when the list stops being the work. Say the script comes back with 380 products under 200 characters and 240 with a single image. You already know what to do; you knew before you searched. What you don't have is someone to open 380 product pages, read what's already there, decide which of them actually need something, write it against the real product, and not break the twelve that were fine.

That's the job Arvio is built for. It reads your live store daily and puts the rare-and-probably-accidental things first — the products with no description, the ones with no image — instead of handing you every deviation at equal weight. Then it writes the fix — the description, the title, the field — against the product it is looking at, and stops there. Nothing changes until you say so, and any change can be undone. It does the opening and the rewriting. The scoring is what the script above already gives you.

Disclosure: Arvio is our own product and it is paid — plans start at $9.90 per 30 days, with a 5-day trial. If your audit came back with fifteen flagged products, the script above and an afternoon are all you need, and we'd rather you did that. Arvio is for the catalogue where the list is four hundred long and stays four hundred long because nobody has a week.

FAQ

What should be on a Shopify product page audit checklist?

The items that recur across nearly every published checklist, and that you can actually measure, are: description present and not trivially short, image count, product type, tags, title length, variants, compare-at price, and whether an out-of-stock product is still published. The more useful question is which of those you're actually behind on. Measured across 20,604 products on 41 live stores, the failure rates run from 2.7% (empty description) to 73.2% (no compare-at price) — so treating all of them as equally urgent is the mistake the checklists build in.

How many images should a Shopify product page have?

The common advice is five or more. In this sample, 37.6% of products have five or more, the median product has 3, and 34.6% have one image or none. So five is a bar most products don't clear, and it's worth deciding whether you care. The line that separates a page a shopper can evaluate from one they can't is closer to the bottom: one image means the shopper never sees the back of it. If you're prioritising, go after the one-image products before the three-image ones.

How long should a Shopify product description be?

We can't answer that from this data, and neither can the checklists — nobody in this sample has conversion numbers attached. What we can tell you is where the floor sits: 2.7% of products have no description at all and 21.4% have under 200 characters of HTML — and since that count includes the tags, the text inside is shorter still. An empty description is rare enough (13 of 41 stores, and no store had it on everything) that it reads as an oversight rather than a style. Beyond "there is something real there," length is a judgement about the product, not a number to hit.

Is a blank product type or missing tags a problem?

It depends on whether you use those fields for anything. Product type is blank on 36.6% of products, and on every product in 9 of the 41 stores; tags are blank on 19.9%, and on every product in 4 stores. When a whole store has none, that's not 400 mistakes — it's a store that organises itself another way. They matter if you rely on them for automated collections, filtering, or reporting. If you don't, filling them in means starting a data-modelling project. That's a choice, and it's fine to say no.

Should every product have a compare-at price?

73.2% of the products we read don't have one, and 12 of the 41 stores have never set one on anything. Compare-at is the strikethrough reference price, and using it is a pricing and promotion decision. An audit tool that lists it as a missing field is counting an empty column. If you never run a sale price, leaving it blank is the correct state.

How do I audit image alt text on my Shopify product pages?

By hand, in the admin — open the product, open each image in the media section, and set its alt text there. We deliberately have no baseline for it: the public catalogue endpoint that produced every other number in this article doesn't return alt attributes at all, so we can't measure it on other people's stores. It's the one item on the standard checklist we can't put a denominator on.

Is a single-variant product something to fix?

No. 65.6% of products in this sample have a single variant, in 39 of the 41 stores. That's what a product with one size, one colour, and one configuration looks like in Shopify's data model. It's worth checking only in the opposite direction: if a product genuinely comes in several sizes and you created each one as a separate product, that's a duplicate problem, not a variant problem.

Method

Sample. 41 live Shopify storefronts, catalogues read 2026-08-26, figures computed 2026-08-30. Every number comes from /products.json, an endpoint any browser can fetch. The stores were drawn at random, with a fixed seed so the same set can be redrawn, from a public list of storefronts whose owners had posted their own URL on the Shopify Community's Store Feedback board asking for feedback.

How we got to 41. We read 720 topics from that board and pulled every store hostname out of the first post: 474 candidate domains. Asking each one for /products.json, 230 still returned a catalogue. From those 230 we drew 60 at random — random.Random(20260826).sample(sorted(hosts), 60), so the same 60 come back every time — then dropped the ones holding fewer than ten products and the ones whose catalogue ran past our read ceiling, which left 41: 20,604 products, the denominator on every percentage above.

Whether it looks like you. Stores that ask strangers for feedback skew newer and smaller, and the largest bias here is survivorship: 244 of the 474 candidates never returned a catalogue — 118 no longer resolve, 56 return 404, 31 are frozen for non-payment, 18 answer with something that isn't JSON (a password page, or not Shopify any more), and 21 return some other error.

What each check means, exactly. Description empty: body_html is zero characters. Under 200 chars: body_html is shorter than 200 characters including HTML tags — a floor test for "is anything there," not a word count, and it includes the empty ones. Images: count of product-level images as returned, with no variant-level de-duplication. "No images at all" is that count being zero; "one image or none" is one or zero; "three images or fewer" is three or fewer — each one contains the one before it, so they are not independent rows. Product type blank / no tags / title over 60 characters: the fields as returned. Single variant: the product record carries one variant or none — we counted variants and did not inspect variant titles, so a single variant with a custom name counts the same as Shopify's Default Title. No compare-at price: no variant carries a compare_at_price. Out of stock, still listed: the product appears in the published catalogue and no variant is available.

What we could not check. Alt text — the endpoint never returns it, so there is no alt figure here in either direction. The endpoint also shows only published products, so drafts and archived products are invisible to all of this, and nothing about page speed, theme, or layout is measurable this way.


Written by Adot Technologies Inc, the team behind Arvio: AI Store Operator for Shopify.

Arvio: AI Store Operator

Other AI tools give you a to-do list.
Arvio's AI store agent does the work.

Arvio scans your Shopify store daily, finds what needs fixing — SEO, prices, stock, product content — and drafts the fix. You approve it, Arvio ships it. Every edit can be undone.

Install on the Shopify App Store
4.9★ rated on Shopify App StoreFree trial availableEvery edit reversible