How to Write a Product Description (Check Your Catalogue First)
Key takeaways
- Most advice on this topic assumes you are looking at an empty box. On the storefronts we read, that is rarely the situation: the box usually has something in it, and the problem is who else has the same something.
- The finding we had not published: among the stores that repeat a description at all, 33 have half or more of their read catalogue on repeated text, and 4 are at 100%: every product we could read was sharing its description with another product. In three of those four it was several shared blocks rather than one.
- This is not an artefact of tiny shops. Of those 33, only one had a catalogue under five products, and 29 had ten or more.
- So the useful first move is diagnosis, not drafting. The advice that helps a store at 8% repeated is different from the advice that helps a store at 100%, and you cannot tell which you are from inside the admin.
- Everything below came from endpoints any browser can fetch, on 225 live storefronts read on 2026-09-05.
You can measure this before you write a word
Arvio is an AI store operator. It runs this same count against your live catalogue, then drafts a replacement for each product it flags. Nothing is written until you approve it.
Find out which problem you have
Writing guides are written for a person sitting in front of an empty description box. That person exists. But when we read 225 live storefronts, the description box was usually not empty, and the thing that was actually wrong with a catalogue was almost never visible from any single product page.
The admin does not surface it either. The product list shows one row per product, so a description pasted onto forty products looks exactly like forty products that each have a description. The count is there if you go looking for it, but nothing puts it in front of you.
So start by counting: how many of my products are already carrying the same block of text? The answer changes what you should do next.
One warning before you read the number, because it decides whether any of this applies to you. If you publish each colourway as its own product — the same shoe in twelve colours, twelve product pages — those twelve legitimately share a description, and a count like this will call all twelve repeated. That is not a defect, and a store built that way can score very high here while being perfectly well run. Before acting on your percentage, open two or three of the products the count flags: if they are the same item in different colours, ignore the number. It is telling you about your catalogue structure, not about your descriptions.
⚠️ A spreadsheet export will not give you this number, even though it looks like it should. Shopify's product CSV is one row per variant, and Body (HTML) is filled in only on each product's first row, so sorting that column stacks up mostly blanks rather than duplicates. Counting those blanks would tell you the opposite of the truth.
This command gives the number in a few seconds. It is read-only, needs no login and no app, and writes nothing anywhere:
#!/usr/bin/env python3
# save as dupes.py, then: python3 dupes.py your-store.com
import json, re, sys, urllib.request
from collections import Counter
if len(sys.argv) < 2:
sys.exit("usage: python3 dupes.py your-store.com")
shop = "https://" + sys.argv[1].replace("https://", "").replace("http://", "").rstrip("/")
products, page = [], 1
while page <= 20: # 20 x 250 = 5,000 products
url = f"{shop}/products.json?limit=250&page={page}"
req = urllib.request.Request(url, headers={"User-Agent": "desc-check"})
try:
batch = json.load(urllib.request.urlopen(req)).get("products", [])
except Exception as e: # not every store publishes this
sys.exit(f"could not read {shop}/products.json ({e}).\n"
"Password-protected and unopened stores do not serve it.")
if not batch: break
products += batch; page += 1
def text(html): # tags out, whitespace collapsed
return re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", html or "")).strip().lower()
descs = [text(p.get("body_html")) for p in products]
filled = [d for d in descs if d]
counts = Counter(filled)
repeated = {d for d, c in counts.items() if c > 1}
in_dup = sum(1 for d in filled if d in repeated)
n = max(len(products), 1)
print(f"products read {len(products)}")
print(f"empty description {len(descs) - len(filled)}")
print(f"repeated text {in_dup} ({100*in_dup/n:.1f}% of catalogue)")
for d, c in counts.most_common(3):
if c > 1: print(f" x{c:<4} {d[:64]}")
The number that matters is the percentage on the third line. Everything in this article hangs off it.
What that percentage looked like on 225 stores
We ran the same two tests across every product we could read on 225 live storefronts. The prevalence figures — how common repetition is, how long descriptions run, how few are empty — we published separately in product description examples, and they are the context for this piece rather than its subject. The short version of that prior work: repetition is common, and the empty box is not where the damage is.
What that piece did not break out is how bad it gets inside the stores it affects. That is the distribution below.
Of the 111 storefronts carrying at least one repeated description, the share of their read catalogue sitting on repeated text fell out like this:
| Share of catalogue on repeated text | Stores |
|---|---|
| 100% — every product read shared its text with another | 4 |
| At least 75%, but not all | 10 |
| 50–74% | 19 |
| 25–49% | 29 |
| Under 25% | 49 |
Every share here is a share of what we could read, not of the whole catalogue: we read up to 50 products per store, and 126 of the 225 stores hit that cap. The Method section at the end says exactly which findings that touches.
Read the top three rows together: 33 stores at half the catalogue or worse. That is roughly a third of the affected group. The median affected store sits at 30.3%, so the group is not uniformly bad, it is split. Most affected stores have a containable problem. A third of them have a structural one.
The four at 100% are the ones worth pausing on. On those stores, every product we read was carrying text that also appears on another product. It is not always one block copied everywhere: the number of distinct repeated descriptions was 5, 3, 2 and 1 across the four. Only the last is the case people picture. Whatever they sell, the description field has stopped distinguishing any of it.
It is not a small-catalogue artefact
A store with three products trivially hits 100%, so we checked whether the 33 are just tiny shops.
Of the 33 stores at 50% or more, exactly one had a catalogue under five products. 29 of the 33 had ten or more. These are stores with enough products that nobody is going to notice the repetition by scrolling.
The measurement is the part that does not scale
You have now seen the check. Running it once tells you where you stand; the work after that is one product at a time, and that is the part that does not scale. Arvio drafts each replacement for you to approve or reject individually.
How to write one, once you know which problem you have
The writing advice is the same everywhere and it is mostly right. What changes with your percentage is which products you point it at, and in what order.
A description earns its place by answering the questions a product page leaves open. In practice that is four things:
- What it physically is. Material, dimensions, weight, what is in the box. This is the part a shared description always gets wrong, because it was written for a different object.
- Who it is for, stated as a situation. Not "perfect for everyone", but the specific occasion, room, skin type, riding style, whatever your category's axis is.
- The one objection that stops the sale. Sizing, compatibility, care, shipping restrictions. You already know what it is for your category, because you answer it in email every week.
- What makes this one different from the next one in the collection. This is the sentence that repeated text structurally cannot contain.
That last point is the whole reason the percentage matters. A shared description can be well written, on-brand, and persuasive, and still fail, because the job of a product description is to distinguish one product from the others beside it, and a description on forty products distinguishes nothing.
Where to start, by your number
Under 25%. Your repetition is probably clustered in one or two collections: variants that were duplicated, or a seasonal range someone filled in quickly. Find the clusters with the script above (the x4, x12 lines), rewrite those, and then treat the rest of the catalogue as a normal writing task: highest-traffic products first.
25–49%. Do not start at the top of the product list. Start with the repeated groups, largest group first. One rewrite there fixes the most pages, and it is the fastest way to move the number.
50% and above. Writing product by product will not close this in any reasonable amount of time. The descriptions need to be generated from the product data you already hold (vendor, type, options, variants) and then reviewed, rather than composed from scratch one at a time. On the mechanics of applying changes across a catalogue, we have a separate piece on editing descriptions at catalogue scale.
At or near 100%. Treat the current description as absent. It is carrying no product-specific information, so there is nothing to preserve and nothing to edit around. The fastest path is a fresh draft per product, reviewed before it goes live.
What we did not measure
- We read up to 50 products per store, and 126 of the 225 hit that cap. Over half the sample is therefore a 50-product slice rather than a whole catalogue, including 23 of the 33 stores at 50% or worse and two of the four shown at 100%. Every percentage here is a share of what we read. A store shown at 100% has every product we read sharing text with another product we read; we cannot claim that about products we did not read.
- We did not measure whether any of this costs sales. No traffic, no conversion, no revenue.
- Of the 230 hosts in the frame, 5 were unreadable. The endpoint did not return a usable catalogue. Those are n/a, excluded from every denominator above, and are not counted as zero.
FAQ
Does length tell me anything about whether mine are working?
Not much, and it is the wrong thing to measure first. A short description that answers the sizing question beats a long one that does not, and a long one shared across forty products is worse than either. We looked at the length spread separately in product description examples; for this article, how many products share the text matters more than how long it runs.
Is it actually a problem if two products share a description?
Two, on genuinely near-identical products, is not much of a problem. The failure mode this article is about is scale: the point where a description covers so many products that it cannot be describing any of them. The script above tells you which situation you are in.
Should I write descriptions myself or have a model draft them?
What matters is what the draft is written against. A draft generated from the product's own data (its variants, its options, its type) can be product-specific. A draft generated from the product title alone will read like the shared description you are trying to replace. Either way, review before publishing.
Does every product need its own description?
Every product that you expect someone to arrive at directly needs something on the page that answers the physical questions. What you do not need is the same paragraph on all of them.
Will rewriting descriptions improve my search ranking?
We did not measure that, and we are not going to claim it. The argument in this article is narrower and does not depend on search: a description that is on forty products is not telling a shopper which of the forty they are looking at.
Where do I start if every product is sharing text?
Highest-traffic products first, one at a time, reviewed before each goes live. The point of measuring first is that you now know the order matters. At that share of the catalogue, you are rebuilding rather than editing.
Method
Sample. 225 live Shopify storefronts, read on 2026-09-05, taken at random from a public list of stores whose owners had posted their own URL on the Shopify Community's Store Feedback board. Everything here came from endpoints any browser can fetch.
The funnel. 230 hosts attempted, 5 did not return a usable catalogue and were excluded, leaving 225 stores.
What we read. Up to 50 products per store from the public products endpoint. Description text is the description field with HTML tags stripped and whitespace collapsed. Two products count as sharing a description when that normalised text matches exactly; empty descriptions are counted as empty, not as copies of each other.
How severity is calculated. For each store with at least one repeated description, severity is the number of its read products carrying repeated text, divided by the number of products we read from that store. Stores with no repetition are not in the distribution.
Whether it looks like you. Stores that ask for feedback on a public board skew newer and smaller than Shopify as a whole. The largest bias is survivorship: the frame started from a larger list of candidate domains, and the ones that no longer resolved, returned errors, or were password-protected were dropped before we read anything. What is left is the stores still trading.
Arvio: AI Store Operator — install it on the Shopify App Store. It finds the products sharing text and drafts each replacement for your approval.
